Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 #ifndef _ARCH_LOCAL_H
  2 #define _ARCH_LOCAL_H
  3 
  4 #include <linux/percpu.h>
  5 
  6 #include <asm/system.h>
  7 #include <asm/atomic.h>
  8 #include <asm/asm.h>
  9 
 10 typedef struct {
 11         atomic_long_t a;
 12 } local_t;
 13 
 14 #define LOCAL_INIT(i)   { ATOMIC_LONG_INIT(i) }
 15 
 16 #define local_read(l)   atomic_long_read(&(l)->a)
 17 #define local_set(l, i) atomic_long_set(&(l)->a, (i))
 18 
 19 static inline void local_inc(local_t *l)
 20 {
 21         __asm__ __volatile__(
 22                 _ASM_INC "%0"
 23                 :"+m" (l->a.counter));
 24 }
 25 
 26 static inline void local_dec(local_t *l)
 27 {
 28         __asm__ __volatile__(
 29                 _ASM_DEC "%0"
 30                 :"+m" (l->a.counter));
 31 }
 32 
 33 static inline void local_add(long i, local_t *l)
 34 {
 35         __asm__ __volatile__(
 36                 _ASM_ADD "%1,%0"
 37                 :"+m" (l->a.counter)
 38                 :"ir" (i));
 39 }
 40 
 41 static inline void local_sub(long i, local_t *l)
 42 {
 43         __asm__ __volatile__(
 44                 _ASM_SUB "%1,%0"
 45                 :"+m" (l->a.counter)
 46                 :"ir" (i));
 47 }
 48 
 49 /**
 50  * local_sub_and_test - subtract value from variable and test result
 51  * @i: integer value to subtract
 52  * @l: pointer to type local_t
 53  *
 54  * Atomically subtracts @i from @l and returns
 55  * true if the result is zero, or false for all
 56  * other cases.
 57  */
 58 static inline int local_sub_and_test(long i, local_t *l)
 59 {
 60         unsigned char c;
 61 
 62         __asm__ __volatile__(
 63                 _ASM_SUB "%2,%0; sete %1"
 64                 :"+m" (l->a.counter), "=qm" (c)
 65                 :"ir" (i) : "memory");
 66         return c;
 67 }
 68 
 69 /**
 70  * local_dec_and_test - decrement and test
 71  * @l: pointer to type local_t
 72  *
 73  * Atomically decrements @l by 1 and
 74  * returns true if the result is 0, or false for all other
 75  * cases.
 76  */
 77 static inline int local_dec_and_test(local_t *l)
 78 {
 79         unsigned char c;
 80 
 81         __asm__ __volatile__(
 82                 _ASM_DEC "%0; sete %1"
 83                 :"+m" (l->a.counter), "=qm" (c)
 84                 : : "memory");
 85         return c != 0;
 86 }
 87 
 88 /**
 89  * local_inc_and_test - increment and test
 90  * @l: pointer to type local_t
 91  *
 92  * Atomically increments @l by 1
 93  * and returns true if the result is zero, or false for all
 94  * other cases.
 95  */
 96 static inline int local_inc_and_test(local_t *l)
 97 {
 98         unsigned char c;
 99 
100         __asm__ __volatile__(
101                 _ASM_INC "%0; sete %1"
102                 :"+m" (l->a.counter), "=qm" (c)
103                 : : "memory");
104         return c != 0;
105 }
106 
107 /**
108  * local_add_negative - add and test if negative
109  * @i: integer value to add
110  * @l: pointer to type local_t
111  *
112  * Atomically adds @i to @l and returns true
113  * if the result is negative, or false when
114  * result is greater than or equal to zero.
115  */
116 static inline int local_add_negative(long i, local_t *l)
117 {
118         unsigned char c;
119 
120         __asm__ __volatile__(
121                 _ASM_ADD "%2,%0; sets %1"
122                 :"+m" (l->a.counter), "=qm" (c)
123                 :"ir" (i) : "memory");
124         return c;
125 }
126 
127 /**
128  * local_add_return - add and return
129  * @i: integer value to add
130  * @l: pointer to type local_t
131  *
132  * Atomically adds @i to @l and returns @i + @l
133  */
134 static inline long local_add_return(long i, local_t *l)
135 {
136         long __i;
137 #ifdef CONFIG_M386
138         unsigned long flags;
139         if (unlikely(boot_cpu_data.x86 <= 3))
140                 goto no_xadd;
141 #endif
142         /* Modern 486+ processor */
143         __i = i;
144         __asm__ __volatile__(
145                 _ASM_XADD "%0, %1;"
146                 :"+r" (i), "+m" (l->a.counter)
147                 : : "memory");
148         return i + __i;
149 
150 #ifdef CONFIG_M386
151 no_xadd: /* Legacy 386 processor */
152         local_irq_save(flags);
153         __i = local_read(l);
154         local_set(l, i + __i);
155         local_irq_restore(flags);
156         return i + __i;
157 #endif
158 }
159 
160 static inline long local_sub_return(long i, local_t *l)
161 {
162         return local_add_return(-i, l);
163 }
164 
165 #define local_inc_return(l)  (local_add_return(1, l))
166 #define local_dec_return(l)  (local_sub_return(1, l))
167 
168 #define local_cmpxchg(l, o, n) \
169         (cmpxchg_local(&((l)->a.counter), (o), (n)))
170 /* Always has a lock prefix */
171 #define local_xchg(l, n) (xchg(&((l)->a.counter), (n)))
172 
173 /**
174  * local_add_unless - add unless the number is a given value
175  * @l: pointer of type local_t
176  * @a: the amount to add to l...
177  * @u: ...unless l is equal to u.
178  *
179  * Atomically adds @a to @l, so long as it was not @u.
180  * Returns non-zero if @l was not @u, and zero otherwise.
181  */
182 #define local_add_unless(l, a, u)                               \
183 ({                                                              \
184         long c, old;                                            \
185         c = local_read(l);                                      \
186         for (;;) {                                              \
187                 if (unlikely(c == (u)))                         \
188                         break;                                  \
189                 old = local_cmpxchg((l), c, c + (a));   \
190                 if (likely(old == c))                           \
191                         break;                                  \
192                 c = old;                                        \
193         }                                                       \
194         c != (u);                                               \
195 })
196 #define local_inc_not_zero(l) local_add_unless((l), 1, 0)
197 
198 /* On x86_32, these are no better than the atomic variants.
199  * On x86-64 these are better than the atomic variants on SMP kernels
200  * because they dont use a lock prefix.
201  */
202 #define __local_inc(l)          local_inc(l)
203 #define __local_dec(l)          local_dec(l)
204 #define __local_add(i, l)       local_add((i), (l))
205 #define __local_sub(i, l)       local_sub((i), (l))
206 
207 /* Use these for per-cpu local_t variables: on some archs they are
208  * much more efficient than these naive implementations.  Note they take
209  * a variable, not an address.
210  *
211  * X86_64: This could be done better if we moved the per cpu data directly
212  * after GS.
213  */
214 
215 /* Need to disable preemption for the cpu local counters otherwise we could
216    still access a variable of a previous CPU in a non atomic way. */
217 #define cpu_local_wrap_v(l)             \
218         ({ local_t res__;               \
219            preempt_disable();           \
220            res__ = (l);                 \
221            preempt_enable();            \
222            res__; })
223 #define cpu_local_wrap(l)               \
224         ({ preempt_disable();           \
225            l;                           \
226            preempt_enable(); })         \
227 
228 #define cpu_local_read(l)    cpu_local_wrap_v(local_read(&__get_cpu_var(l)))
229 #define cpu_local_set(l, i)  cpu_local_wrap(local_set(&__get_cpu_var(l), (i)))
230 #define cpu_local_inc(l)     cpu_local_wrap(local_inc(&__get_cpu_var(l)))
231 #define cpu_local_dec(l)     cpu_local_wrap(local_dec(&__get_cpu_var(l)))
232 #define cpu_local_add(i, l)  cpu_local_wrap(local_add((i), &__get_cpu_var(l)))
233 #define cpu_local_sub(i, l)  cpu_local_wrap(local_sub((i), &__get_cpu_var(l)))
234 
235 #define __cpu_local_inc(l)      cpu_local_inc(l)
236 #define __cpu_local_dec(l)      cpu_local_dec(l)
237 #define __cpu_local_add(i, l)   cpu_local_add((i), (l))
238 #define __cpu_local_sub(i, l)   cpu_local_sub((i), (l))
239 
240 #endif /* _ARCH_LOCAL_H */
241 
  This page was automatically generated by the LXR engine.