blob: acb4a3ca4088ab08d75c259ccb458cd5da09cc14 [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef __ASM_CMPXCHG_H
2#define __ASM_CMPXCHG_H
3
4#include <stdint.h>
5
6//TODO implement xchg using gcc's atomic builtins (http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html)
7//or maybe http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
8//__atomic_fetch_sub looks promising
9
10#define cmpxchg(ptr, o, n) __sync_val_compare_and_swap(ptr, o, n)
11/*#define xchg(ptr, n) ({typeof(*ptr) r; \
12 do{ \
13 r = *ptr; \
14 }while(!__sync_bool_compare_and_swap(ptr, r, n)); \
15 r; \
16})*/
17
18# define LOCK "lock;"
19# define LOCK_PREFIX "lock;"
20
21#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
22
23#define __xg(x) ((volatile long long *)(x))
24
25/*static inline void set_64bit(volatile unsigned long *ptr, unsigned long val)
26{
27 *ptr = val;
28}
29
30#define _set_64bit set_64bit*/
31
32/*
33 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
34 * Note 2: xchg has side effect, so that attribute volatile is necessary,
35 * but generally the primitive is invalid, *ptr is output argument. --ANK
36 */
37static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
38{
39 switch (size) {
40 case 1:
41 __asm__ __volatile__("xchgb %b0,%1"
42 :"=q" (x)
43 :"m" (*__xg(ptr)), "0" (x)
44 :"memory");
45 break;
46 case 2:
47 __asm__ __volatile__("xchgw %w0,%1"
48 :"=r" (x)
49 :"m" (*__xg(ptr)), "0" (x)
50 :"memory");
51 break;
52 case 4:
53 __asm__ __volatile__("xchgl %k0,%1"
54 :"=r" (x)
55 :"m" (*__xg(ptr)), "0" (x)
56 :"memory");
57 break;
58 case 8:
59 __asm__ __volatile__("xchg %0,%1"
60 :"=r" (x)
61 :"m" (*__xg(ptr)), "0" (x)
62 :"memory");
63 break;
64 }
65 return x;
66}
67
68/*
69 * Atomic compare and exchange. Compare OLD with MEM, if identical,
70 * store NEW in MEM. Return the initial value in MEM. Success is
71 * indicated by comparing RETURN with OLD.
72 */
73
74#if 0
75
76#define __HAVE_ARCH_CMPXCHG 1
77
78static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
79 unsigned long new, int size)
80{
81 int32_t prev;
82 switch (size) {
83 case 1:
84 __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
85 : "=a"(prev)
86 : "q"(new), "m"(*__xg(ptr)), "0"(old)
87 : "memory");
88 return prev;
89 case 2:
90 __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
91 : "=a"(prev)
92 : "r"(new), "m"(*__xg(ptr)), "0"(old)
93 : "memory");
94 return prev;
95 case 4:
96 __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %k1,%2"
97 : "=a"(prev)
98 : "r"(new), "m"(*__xg(ptr)), "0"(old)
99 : "memory");
100 return prev;
101 case 8:
102 __asm__ __volatile__("lock; cmpxchg %1,%2"
103 : "=a"(prev)
104 : "q"(new), "m"(*__xg(ptr)), "0"(old)
105 : "memory");
106 return prev;
107 }
108 return old;
109}
110
111/*
112static inline unsigned long __cmpxchg_local(volatile void *ptr,
113 unsigned long old, unsigned long new, int size)
114{
115 unsigned long prev;
116 switch (size) {
117 case 1:
118 __asm__ __volatile__("cmpxchgb %b1,%2"
119 : "=a"(prev)
120 : "q"(new), "m"(*__xg(ptr)), "0"(old)
121 : "memory");
122 return prev;
123 case 2:
124 __asm__ __volatile__("cmpxchgw %w1,%2"
125 : "=a"(prev)
126 : "r"(new), "m"(*__xg(ptr)), "0"(old)
127 : "memory");
128 return prev;
129 case 4:
130 __asm__ __volatile__("cmpxchgl %k1,%2"
131 : "=a"(prev)
132 : "r"(new), "m"(*__xg(ptr)), "0"(old)
133 : "memory");
134 return prev;
135 case 8:
136 __asm__ __volatile__("cmpxchgq %1,%2"
137 : "=a"(prev)
138 : "r"(new), "m"(*__xg(ptr)), "0"(old)
139 : "memory");
140 return prev;
141 }
142 return old;
143}*/
144
145#define cmpxchg(ptr,o,n)\
146 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
147 (unsigned long)(n),sizeof(*(ptr))))
148/*#define cmpxchg_local(ptr,o,n)\
149 ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
150 (unsigned long)(n),sizeof(*(ptr))))*/
151#endif
152
153#endif