Linux Audio

Check our new training course

Loading...
v4.10.11
  1/*
  2 * Generic C implementation of atomic counter operations. Usable on
  3 * UP systems only. Do not include in machine independent code.
  4 *
  5 * Originally implemented for MN10300.
  6 *
  7 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  8 * Written by David Howells (dhowells@redhat.com)
  9 *
 10 * This program is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU General Public Licence
 12 * as published by the Free Software Foundation; either version
 13 * 2 of the Licence, or (at your option) any later version.
 14 */
 15#ifndef __ASM_GENERIC_ATOMIC_H
 16#define __ASM_GENERIC_ATOMIC_H
 17
 18#include <asm/cmpxchg.h>
 19#include <asm/barrier.h>
 20
 21/*
 22 * atomic_$op() - $op integer to atomic variable
 23 * @i: integer value to $op
 24 * @v: pointer to the atomic variable
 25 *
 26 * Atomically $ops @i to @v. Does not strictly guarantee a memory-barrier, use
 27 * smp_mb__{before,after}_atomic().
 28 */
 29
 30/*
 31 * atomic_$op_return() - $op interer to atomic variable and returns the result
 32 * @i: integer value to $op
 33 * @v: pointer to the atomic variable
 34 *
 35 * Atomically $ops @i to @v. Does imply a full memory barrier.
 36 */
 37
 38#ifdef CONFIG_SMP
 39
 40/* we can build all atomic primitives from cmpxchg */
 41
 42#define ATOMIC_OP(op, c_op)						\
 43static inline void atomic_##op(int i, atomic_t *v)			\
 44{									\
 45	int c, old;							\
 46									\
 47	c = v->counter;							\
 48	while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)		\
 49		c = old;						\
 50}
 51
 52#define ATOMIC_OP_RETURN(op, c_op)					\
 53static inline int atomic_##op##_return(int i, atomic_t *v)		\
 54{									\
 55	int c, old;							\
 56									\
 57	c = v->counter;							\
 58	while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)		\
 59		c = old;						\
 60									\
 61	return c c_op i;						\
 62}
 63
 64#define ATOMIC_FETCH_OP(op, c_op)					\
 65static inline int atomic_fetch_##op(int i, atomic_t *v)			\
 66{									\
 67	int c, old;							\
 68									\
 69	c = v->counter;							\
 70	while ((old = cmpxchg(&v->counter, c, c c_op i)) != c)		\
 71		c = old;						\
 72									\
 73	return c;							\
 74}
 75
 76#else
 77
 78#include <linux/irqflags.h>
 79
 80#define ATOMIC_OP(op, c_op)						\
 81static inline void atomic_##op(int i, atomic_t *v)			\
 82{									\
 83	unsigned long flags;						\
 84									\
 85	raw_local_irq_save(flags);					\
 86	v->counter = v->counter c_op i;					\
 87	raw_local_irq_restore(flags);					\
 88}
 89
 90#define ATOMIC_OP_RETURN(op, c_op)					\
 91static inline int atomic_##op##_return(int i, atomic_t *v)		\
 92{									\
 93	unsigned long flags;						\
 94	int ret;							\
 95									\
 96	raw_local_irq_save(flags);					\
 97	ret = (v->counter = v->counter c_op i);				\
 98	raw_local_irq_restore(flags);					\
 99									\
100	return ret;							\
101}
102
103#define ATOMIC_FETCH_OP(op, c_op)					\
104static inline int atomic_fetch_##op(int i, atomic_t *v)			\
105{									\
106	unsigned long flags;						\
107	int ret;							\
108									\
109	raw_local_irq_save(flags);					\
110	ret = v->counter;						\
111	v->counter = v->counter c_op i;					\
112	raw_local_irq_restore(flags);					\
113									\
114	return ret;							\
115}
116
117#endif /* CONFIG_SMP */
118
119#ifndef atomic_add_return
120ATOMIC_OP_RETURN(add, +)
121#endif
122
123#ifndef atomic_sub_return
124ATOMIC_OP_RETURN(sub, -)
125#endif
126
127#ifndef atomic_fetch_add
128ATOMIC_FETCH_OP(add, +)
129#endif
130
131#ifndef atomic_fetch_sub
132ATOMIC_FETCH_OP(sub, -)
133#endif
134
135#ifndef atomic_fetch_and
136ATOMIC_FETCH_OP(and, &)
137#endif
138
139#ifndef atomic_fetch_or
140ATOMIC_FETCH_OP(or, |)
141#endif
142
143#ifndef atomic_fetch_xor
144ATOMIC_FETCH_OP(xor, ^)
145#endif
146
147#ifndef atomic_and
148ATOMIC_OP(and, &)
149#endif
150
151#ifndef atomic_or
152ATOMIC_OP(or, |)
153#endif
154
155#ifndef atomic_xor
156ATOMIC_OP(xor, ^)
157#endif
158
159#undef ATOMIC_FETCH_OP
160#undef ATOMIC_OP_RETURN
161#undef ATOMIC_OP
162
163/*
164 * Atomic operations that C can't guarantee us.  Useful for
165 * resource counting etc..
166 */
167
168#define ATOMIC_INIT(i)	{ (i) }
169
 
 
170/**
171 * atomic_read - read atomic variable
172 * @v: pointer of type atomic_t
173 *
174 * Atomically reads the value of @v.
175 */
176#ifndef atomic_read
177#define atomic_read(v)	READ_ONCE((v)->counter)
178#endif
179
180/**
181 * atomic_set - set atomic variable
182 * @v: pointer of type atomic_t
183 * @i: required value
184 *
185 * Atomically sets the value of @v to @i.
186 */
187#define atomic_set(v, i) WRITE_ONCE(((v)->counter), (i))
188
189#include <linux/irqflags.h>
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191static inline int atomic_add_negative(int i, atomic_t *v)
192{
193	return atomic_add_return(i, v) < 0;
194}
195
196static inline void atomic_add(int i, atomic_t *v)
197{
198	atomic_add_return(i, v);
199}
200
201static inline void atomic_sub(int i, atomic_t *v)
202{
203	atomic_sub_return(i, v);
204}
205
206static inline void atomic_inc(atomic_t *v)
207{
208	atomic_add_return(1, v);
209}
210
211static inline void atomic_dec(atomic_t *v)
212{
213	atomic_sub_return(1, v);
214}
215
216#define atomic_dec_return(v)		atomic_sub_return(1, (v))
217#define atomic_inc_return(v)		atomic_add_return(1, (v))
218
219#define atomic_sub_and_test(i, v)	(atomic_sub_return((i), (v)) == 0)
220#define atomic_dec_and_test(v)		(atomic_dec_return(v) == 0)
221#define atomic_inc_and_test(v)		(atomic_inc_return(v) == 0)
222
223#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
224#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
225
226static inline int __atomic_add_unless(atomic_t *v, int a, int u)
227{
228	int c, old;
229	c = atomic_read(v);
230	while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
231		c = old;
232	return c;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233}
 
 
 
 
 
 
 
234
 
235#endif /* __ASM_GENERIC_ATOMIC_H */
v3.15
  1/*
  2 * Generic C implementation of atomic counter operations. Usable on
  3 * UP systems only. Do not include in machine independent code.
  4 *
  5 * Originally implemented for MN10300.
  6 *
  7 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
  8 * Written by David Howells (dhowells@redhat.com)
  9 *
 10 * This program is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU General Public Licence
 12 * as published by the Free Software Foundation; either version
 13 * 2 of the Licence, or (at your option) any later version.
 14 */
 15#ifndef __ASM_GENERIC_ATOMIC_H
 16#define __ASM_GENERIC_ATOMIC_H
 17
 18#include <asm/cmpxchg.h>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 19
 20#ifdef CONFIG_SMP
 21/* Force people to define core atomics */
 22# if !defined(atomic_add_return) || !defined(atomic_sub_return) || \
 23     !defined(atomic_clear_mask) || !defined(atomic_set_mask)
 24#  error "SMP requires a little arch-specific magic"
 25# endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 26#endif
 27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 28/*
 29 * Atomic operations that C can't guarantee us.  Useful for
 30 * resource counting etc..
 31 */
 32
 33#define ATOMIC_INIT(i)	{ (i) }
 34
 35#ifdef __KERNEL__
 36
 37/**
 38 * atomic_read - read atomic variable
 39 * @v: pointer of type atomic_t
 40 *
 41 * Atomically reads the value of @v.
 42 */
 43#ifndef atomic_read
 44#define atomic_read(v)	(*(volatile int *)&(v)->counter)
 45#endif
 46
 47/**
 48 * atomic_set - set atomic variable
 49 * @v: pointer of type atomic_t
 50 * @i: required value
 51 *
 52 * Atomically sets the value of @v to @i.
 53 */
 54#define atomic_set(v, i) (((v)->counter) = (i))
 55
 56#include <linux/irqflags.h>
 57
 58/**
 59 * atomic_add_return - add integer to atomic variable
 60 * @i: integer value to add
 61 * @v: pointer of type atomic_t
 62 *
 63 * Atomically adds @i to @v and returns the result
 64 */
 65#ifndef atomic_add_return
 66static inline int atomic_add_return(int i, atomic_t *v)
 67{
 68	unsigned long flags;
 69	int temp;
 70
 71	raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */
 72	temp = v->counter;
 73	temp += i;
 74	v->counter = temp;
 75	raw_local_irq_restore(flags);
 76
 77	return temp;
 78}
 79#endif
 80
 81/**
 82 * atomic_sub_return - subtract integer from atomic variable
 83 * @i: integer value to subtract
 84 * @v: pointer of type atomic_t
 85 *
 86 * Atomically subtracts @i from @v and returns the result
 87 */
 88#ifndef atomic_sub_return
 89static inline int atomic_sub_return(int i, atomic_t *v)
 90{
 91	unsigned long flags;
 92	int temp;
 93
 94	raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */
 95	temp = v->counter;
 96	temp -= i;
 97	v->counter = temp;
 98	raw_local_irq_restore(flags);
 99
100	return temp;
101}
102#endif
103
104static inline int atomic_add_negative(int i, atomic_t *v)
105{
106	return atomic_add_return(i, v) < 0;
107}
108
109static inline void atomic_add(int i, atomic_t *v)
110{
111	atomic_add_return(i, v);
112}
113
114static inline void atomic_sub(int i, atomic_t *v)
115{
116	atomic_sub_return(i, v);
117}
118
119static inline void atomic_inc(atomic_t *v)
120{
121	atomic_add_return(1, v);
122}
123
124static inline void atomic_dec(atomic_t *v)
125{
126	atomic_sub_return(1, v);
127}
128
129#define atomic_dec_return(v)		atomic_sub_return(1, (v))
130#define atomic_inc_return(v)		atomic_add_return(1, (v))
131
132#define atomic_sub_and_test(i, v)	(atomic_sub_return((i), (v)) == 0)
133#define atomic_dec_and_test(v)		(atomic_dec_return(v) == 0)
134#define atomic_inc_and_test(v)		(atomic_inc_return(v) == 0)
135
136#define atomic_xchg(ptr, v)		(xchg(&(ptr)->counter, (v)))
137#define atomic_cmpxchg(v, old, new)	(cmpxchg(&((v)->counter), (old), (new)))
138
139static inline int __atomic_add_unless(atomic_t *v, int a, int u)
140{
141  int c, old;
142  c = atomic_read(v);
143  while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c)
144    c = old;
145  return c;
146}
147
148/**
149 * atomic_clear_mask - Atomically clear bits in atomic variable
150 * @mask: Mask of the bits to be cleared
151 * @v: pointer of type atomic_t
152 *
153 * Atomically clears the bits set in @mask from @v
154 */
155#ifndef atomic_clear_mask
156static inline void atomic_clear_mask(unsigned long mask, atomic_t *v)
157{
158	unsigned long flags;
159
160	mask = ~mask;
161	raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
162	v->counter &= mask;
163	raw_local_irq_restore(flags);
164}
165#endif
166
167/**
168 * atomic_set_mask - Atomically set bits in atomic variable
169 * @mask: Mask of the bits to be set
170 * @v: pointer of type atomic_t
171 *
172 * Atomically sets the bits set in @mask in @v
173 */
174#ifndef atomic_set_mask
175static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
176{
177	unsigned long flags;
178
179	raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */
180	v->counter |= mask;
181	raw_local_irq_restore(flags);
182}
183#endif
184
185/* Assume that atomic operations are already serializing */
186#define smp_mb__before_atomic_dec()	barrier()
187#define smp_mb__after_atomic_dec()	barrier()
188#define smp_mb__before_atomic_inc()	barrier()
189#define smp_mb__after_atomic_inc()	barrier()
190
191#endif /* __KERNEL__ */
192#endif /* __ASM_GENERIC_ATOMIC_H */