0001
0002 #ifndef _ASM_X86_LOCAL_H
0003 #define _ASM_X86_LOCAL_H
0004
0005 #include <linux/percpu.h>
0006
0007 #include <linux/atomic.h>
0008 #include <asm/asm.h>
0009
0010 typedef struct {
0011 atomic_long_t a;
0012 } local_t;
0013
0014 #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) }
0015
0016 #define local_read(l) atomic_long_read(&(l)->a)
0017 #define local_set(l, i) atomic_long_set(&(l)->a, (i))
0018
0019 static inline void local_inc(local_t *l)
0020 {
0021 asm volatile(_ASM_INC "%0"
0022 : "+m" (l->a.counter));
0023 }
0024
0025 static inline void local_dec(local_t *l)
0026 {
0027 asm volatile(_ASM_DEC "%0"
0028 : "+m" (l->a.counter));
0029 }
0030
0031 static inline void local_add(long i, local_t *l)
0032 {
0033 asm volatile(_ASM_ADD "%1,%0"
0034 : "+m" (l->a.counter)
0035 : "ir" (i));
0036 }
0037
0038 static inline void local_sub(long i, local_t *l)
0039 {
0040 asm volatile(_ASM_SUB "%1,%0"
0041 : "+m" (l->a.counter)
0042 : "ir" (i));
0043 }
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 static inline bool local_sub_and_test(long i, local_t *l)
0055 {
0056 return GEN_BINARY_RMWcc(_ASM_SUB, l->a.counter, e, "er", i);
0057 }
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 static inline bool local_dec_and_test(local_t *l)
0068 {
0069 return GEN_UNARY_RMWcc(_ASM_DEC, l->a.counter, e);
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 static inline bool local_inc_and_test(local_t *l)
0081 {
0082 return GEN_UNARY_RMWcc(_ASM_INC, l->a.counter, e);
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094 static inline bool local_add_negative(long i, local_t *l)
0095 {
0096 return GEN_BINARY_RMWcc(_ASM_ADD, l->a.counter, s, "er", i);
0097 }
0098
0099
0100
0101
0102
0103
0104
0105
0106 static inline long local_add_return(long i, local_t *l)
0107 {
0108 long __i = i;
0109 asm volatile(_ASM_XADD "%0, %1;"
0110 : "+r" (i), "+m" (l->a.counter)
0111 : : "memory");
0112 return i + __i;
0113 }
0114
0115 static inline long local_sub_return(long i, local_t *l)
0116 {
0117 return local_add_return(-i, l);
0118 }
0119
0120 #define local_inc_return(l) (local_add_return(1, l))
0121 #define local_dec_return(l) (local_sub_return(1, l))
0122
0123 #define local_cmpxchg(l, o, n) \
0124 (cmpxchg_local(&((l)->a.counter), (o), (n)))
0125
0126 #define local_xchg(l, n) (xchg(&((l)->a.counter), (n)))
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 #define local_add_unless(l, a, u) \
0138 ({ \
0139 long c, old; \
0140 c = local_read((l)); \
0141 for (;;) { \
0142 if (unlikely(c == (u))) \
0143 break; \
0144 old = local_cmpxchg((l), c, c + (a)); \
0145 if (likely(old == c)) \
0146 break; \
0147 c = old; \
0148 } \
0149 c != (u); \
0150 })
0151 #define local_inc_not_zero(l) local_add_unless((l), 1, 0)
0152
0153
0154
0155
0156
0157 #define __local_inc(l) local_inc(l)
0158 #define __local_dec(l) local_dec(l)
0159 #define __local_add(i, l) local_add((i), (l))
0160 #define __local_sub(i, l) local_sub((i), (l))
0161
0162 #endif