ad33a424408ffb3166d586ec660f4e528633484c
[IRC.git] / Robust / src / Runtime / mlp_lock.h
1 #ifndef ____MLP_LOCK_H__
2 #define ____MLP_LOCK_H__
3
4
5 #include "runtime.h"
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <assert.h>
10
11 #define __xg(x) ((volatile INTPTR *)(x))
12
13 #define CFENCE   asm volatile("":::"memory");
14 #define MFENCE   asm volatile("mfence":::"memory");
15
16 #define LOCK_PREFIX \
17   ".section .smp_locks,\"a\"\n"   \
18   "  .align 4\n"                  \
19   "  .long 661f\n"             /* address */\
20   ".previous\n"                   \
21   "661:\n\tlock; "
22
23
24 static inline int atomicincandread(volatile unsigned int *lock) {
25   int retval=1;
26   __asm__ __volatile__("lock; xadd %0,%1"
27                        : "=r"(retval)
28                        : "m"(*lock), "0"(retval)
29                        : "memory");
30   return retval;
31 }
32
33 static inline void atomic_dec(volatile int *v) {
34   __asm__ __volatile__ (LOCK_PREFIX "decl %0"
35                         : "+m" (*v));
36 }
37
38 static inline void atomic_inc(volatile int *v) {
39   __asm__ __volatile__ (LOCK_PREFIX "incl %0"
40                         : "+m" (*v));
41 }
42
43 // this returns TRUE if the atomic subtraction results in
44 // a zero value--this way two threads cannot dec a value
45 // atomically, but then go ahead and both read zero,
46 // thinking they both are the last decrementer
47 static inline int atomic_sub_and_test(int i, volatile int *v) {
48   unsigned char c;
49
50   __asm__ __volatile__ (LOCK_PREFIX "subl %2,%0; sete %1"
51                         : "+m" (*v), "=qm" (c)
52                         : "ir" (i) : "memory");
53   return c;
54 }
55
56
57 static inline void atomic_add(int i, volatile int *v) {
58   __asm__ __volatile__ (LOCK_PREFIX "addl %1,%0"
59                         : "+m" (*v)
60                         : "ir" (i));
61 }
62
63 static inline int LOCKXCHG32(volatile int* ptr, int val){
64   int retval;
65   //note: xchgl always implies lock 
66   __asm__ __volatile__("xchgl %0,%1"
67                        : "=r"(retval)
68                        : "m"(*ptr), "0"(val)
69                        : "memory");
70   return retval;
71  
72 }
73
74
75 // LOCKXCH atomically does the following:
76 // INTPTR retval=*ptr; 
77 // *ptr=val; 
78 // return retval
79 #ifdef BIT64
80 static inline INTPTR LOCKXCHG(volatile INTPTR * ptr, INTPTR val){
81   INTPTR retval;
82   //note: xchgl always implies lock 
83   __asm__ __volatile__("xchgq %0,%1"
84                        : "=r"(retval)
85                        : "m"(*ptr), "0"(val)
86                        : "memory");
87   return retval;
88  
89 }
90 #else
91 #define LOCKXCHG LOCKXCHG32
92 #endif
93
94 /*
95 static inline int write_trylock(volatile int *lock) {
96   int retval=0;
97   __asm__ __volatile__("xchgl %0,%1"
98                        : "=r"(retval)
99                        : "m"(*lock), "0"(retval)
100                        : "memory");
101   return retval;
102 }
103 */
104
105 #ifdef BIT64
106 static inline INTPTR CAS(volatile void *ptr, unsigned INTPTR old, unsigned INTPTR new){
107   unsigned INTPTR prev;
108   __asm__ __volatile__("lock; cmpxchgq %1,%2"
109                        : "=a"(prev)
110                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
111                        : "memory");
112   return prev;
113 }
114
115 static inline long CAS32(volatile void *ptr, unsigned long old, unsigned long new){
116   unsigned long prev;
117   __asm__ __volatile__("lock; cmpxchgl %k1,%2"
118                        : "=a"(prev)
119                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
120                        : "memory");
121   return prev;
122 }
123 #else
124 static inline long CAS(volatile void *ptr, unsigned long old, unsigned long new){
125   unsigned long prev;
126   __asm__ __volatile__("lock; cmpxchgl %k1,%2"
127                        : "=a"(prev)
128                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
129                        : "memory");
130   return prev;
131 }
132 #define CAS32 CAS
133 #endif
134
135
136 static inline int BARRIER(){
137   CFENCE;
138   return 1;
139 }
140
141 static inline int MBARRIER(){
142   MFENCE;
143   return 1;
144 }
145
146
147 #endif // ____MLP_LOCK_H__