Blame view
include/asm-generic/atomic.h
4.8 KB
3f7e212df asm-generic: add ... |
1 |
/* |
acac43e2f atomic: Update co... |
2 3 4 |
* Generic C implementation of atomic counter operations. Usable on * UP systems only. Do not include in machine independent code. * |
3f7e212df asm-generic: add ... |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
* Originally implemented for MN10300. * * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public Licence * as published by the Free Software Foundation; either version * 2 of the Licence, or (at your option) any later version. */ #ifndef __ASM_GENERIC_ATOMIC_H #define __ASM_GENERIC_ATOMIC_H #ifdef CONFIG_SMP |
7505cb60c asm-generic/atomi... |
19 20 21 22 23 |
/* Force people to define core atomics */ # if !defined(atomic_add_return) || !defined(atomic_sub_return) || \ !defined(atomic_clear_mask) || !defined(atomic_set_mask) # error "SMP requires a little arch-specific magic" # endif |
3f7e212df asm-generic: add ... |
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#endif /* * Atomic operations that C can't guarantee us. Useful for * resource counting etc.. */ #define ATOMIC_INIT(i) { (i) } #ifdef __KERNEL__ /** * atomic_read - read atomic variable * @v: pointer of type atomic_t * |
37682177a asm-generic: don'... |
39 |
* Atomically reads the value of @v. |
3f7e212df asm-generic: add ... |
40 |
*/ |
7505cb60c asm-generic/atomi... |
41 |
#ifndef atomic_read |
f3d46f9d3 atomic_t: Cast to... |
42 |
#define atomic_read(v) (*(volatile int *)&(v)->counter) |
7505cb60c asm-generic/atomi... |
43 |
#endif |
3f7e212df asm-generic: add ... |
44 45 46 47 48 49 |
/** * atomic_set - set atomic variable * @v: pointer of type atomic_t * @i: required value * |
37682177a asm-generic: don'... |
50 |
* Atomically sets the value of @v to @i. |
3f7e212df asm-generic: add ... |
51 52 |
*/ #define atomic_set(v, i) (((v)->counter) = (i)) |
df9ee2927 Fix IRQ flag hand... |
53 |
#include <linux/irqflags.h> |
3f7e212df asm-generic: add ... |
54 55 56 57 58 59 60 61 |
#include <asm/system.h> /** * atomic_add_return - add integer to atomic variable * @i: integer value to add * @v: pointer of type atomic_t * * Atomically adds @i to @v and returns the result |
3f7e212df asm-generic: add ... |
62 |
*/ |
7505cb60c asm-generic/atomi... |
63 |
#ifndef atomic_add_return |
3f7e212df asm-generic: add ... |
64 65 66 67 |
static inline int atomic_add_return(int i, atomic_t *v) { unsigned long flags; int temp; |
df9ee2927 Fix IRQ flag hand... |
68 |
raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */ |
3f7e212df asm-generic: add ... |
69 70 71 |
temp = v->counter; temp += i; v->counter = temp; |
9e58143dc asm-generic: use ... |
72 |
raw_local_irq_restore(flags); |
3f7e212df asm-generic: add ... |
73 74 75 |
return temp; } |
7505cb60c asm-generic/atomi... |
76 |
#endif |
3f7e212df asm-generic: add ... |
77 78 79 80 81 82 83 |
/** * atomic_sub_return - subtract integer from atomic variable * @i: integer value to subtract * @v: pointer of type atomic_t * * Atomically subtracts @i from @v and returns the result |
3f7e212df asm-generic: add ... |
84 |
*/ |
7505cb60c asm-generic/atomi... |
85 |
#ifndef atomic_sub_return |
3f7e212df asm-generic: add ... |
86 87 88 89 |
static inline int atomic_sub_return(int i, atomic_t *v) { unsigned long flags; int temp; |
df9ee2927 Fix IRQ flag hand... |
90 |
raw_local_irq_save(flags); /* Don't trace it in an irqsoff handler */ |
3f7e212df asm-generic: add ... |
91 92 93 |
temp = v->counter; temp -= i; v->counter = temp; |
9e58143dc asm-generic: use ... |
94 |
raw_local_irq_restore(flags); |
3f7e212df asm-generic: add ... |
95 96 97 |
return temp; } |
7505cb60c asm-generic/atomi... |
98 |
#endif |
3f7e212df asm-generic: add ... |
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
static inline int atomic_add_negative(int i, atomic_t *v) { return atomic_add_return(i, v) < 0; } static inline void atomic_add(int i, atomic_t *v) { atomic_add_return(i, v); } static inline void atomic_sub(int i, atomic_t *v) { atomic_sub_return(i, v); } static inline void atomic_inc(atomic_t *v) { atomic_add_return(1, v); } static inline void atomic_dec(atomic_t *v) { atomic_sub_return(1, v); } #define atomic_dec_return(v) atomic_sub_return(1, (v)) #define atomic_inc_return(v) atomic_add_return(1, (v)) #define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) |
3eea44ea7 asm-generic/atomi... |
129 130 |
#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0) #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) |
3f7e212df asm-generic: add ... |
131 |
|
8b9d40691 asm-generic: make... |
132 133 134 135 136 137 138 139 |
#define atomic_xchg(ptr, v) (xchg(&(ptr)->counter, (v))) #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new))) #define cmpxchg_local(ptr, o, n) \ ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ (unsigned long)(n), sizeof(*(ptr)))) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) |
f24219b4e atomic: move atom... |
140 |
static inline int __atomic_add_unless(atomic_t *v, int a, int u) |
8b9d40691 asm-generic: make... |
141 142 143 144 145 |
{ int c, old; c = atomic_read(v); while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c) c = old; |
f24219b4e atomic: move atom... |
146 |
return c; |
8b9d40691 asm-generic: make... |
147 |
} |
3f7e212df asm-generic: add ... |
148 |
|
f6081bd3f asm-generic/atomi... |
149 150 151 152 153 154 155 |
/** * atomic_clear_mask - Atomically clear bits in atomic variable * @mask: Mask of the bits to be cleared * @v: pointer of type atomic_t * * Atomically clears the bits set in @mask from @v */ |
7505cb60c asm-generic/atomi... |
156 |
#ifndef atomic_clear_mask |
f6081bd3f asm-generic/atomi... |
157 |
static inline void atomic_clear_mask(unsigned long mask, atomic_t *v) |
3f7e212df asm-generic: add ... |
158 159 160 161 |
{ unsigned long flags; mask = ~mask; |
9e58143dc asm-generic: use ... |
162 |
raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */ |
f6081bd3f asm-generic/atomi... |
163 |
v->counter &= mask; |
9e58143dc asm-generic: use ... |
164 |
raw_local_irq_restore(flags); |
3f7e212df asm-generic: add ... |
165 |
} |
7505cb60c asm-generic/atomi... |
166 |
#endif |
3f7e212df asm-generic: add ... |
167 |
|
00b3c28bd asm-generic/atomi... |
168 169 170 171 172 173 174 |
/** * atomic_set_mask - Atomically set bits in atomic variable * @mask: Mask of the bits to be set * @v: pointer of type atomic_t * * Atomically sets the bits set in @mask in @v */ |
7505cb60c asm-generic/atomi... |
175 |
#ifndef atomic_set_mask |
00b3c28bd asm-generic/atomi... |
176 177 178 179 180 181 182 183 |
static inline void atomic_set_mask(unsigned int mask, atomic_t *v) { unsigned long flags; raw_local_irq_save(flags); /* Don't trace it in a irqsoff handler */ v->counter |= mask; raw_local_irq_restore(flags); } |
7505cb60c asm-generic/atomi... |
184 |
#endif |
00b3c28bd asm-generic/atomi... |
185 |
|
3f7e212df asm-generic: add ... |
186 187 188 189 190 |
/* Assume that atomic operations are already serializing */ #define smp_mb__before_atomic_dec() barrier() #define smp_mb__after_atomic_dec() barrier() #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() |
3f7e212df asm-generic: add ... |
191 192 |
#endif /* __KERNEL__ */ #endif /* __ASM_GENERIC_ATOMIC_H */ |