bug fix...code that was never exercised...
[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 void atomic_dec(volatile int *v) {
25   __asm__ __volatile__ (LOCK_PREFIX "decl %0"
26                         : "+m" (*v));
27 }
28
29 static inline void atomic_inc(volatile int *v) {
30   __asm__ __volatile__ (LOCK_PREFIX "incl %0"
31                         : "+m" (*v));
32 }
33
34 // this returns TRUE if the atomic subtraction results in
35 // a zero value--this way two threads cannot dec a value
36 // atomically, but then go ahead and both read zero,
37 // thinking they both are the last decrementer
38 static inline int atomic_sub_and_test(int i, volatile int *v) {
39   unsigned char c;
40
41   __asm__ __volatile__ (LOCK_PREFIX "subl %2,%0; sete %1"
42                         : "+m" (*v), "=qm" (c)
43                         : "ir" (i) : "memory");
44   return c;
45 }
46
47
48 static inline void atomic_add(int i, volatile int *v) {
49   __asm__ __volatile__ (LOCK_PREFIX "addl %1,%0"
50                         : "+m" (*v)
51                         : "ir" (i));
52 }
53
54 static inline int LOCKXCHG32(volatile int* ptr, int val){
55   int retval;
56   //note: xchgl always implies lock 
57   __asm__ __volatile__("xchgl %0,%1"
58                        : "=r"(retval)
59                        : "m"(*ptr), "0"(val)
60                        : "memory");
61   return retval;
62  
63 }
64
65
66 // LOCKXCH atomically does the following:
67 // INTPTR retval=*ptr; 
68 // *ptr=val; 
69 // return retval
70 #ifdef BIT64
71 static inline INTPTR LOCKXCHG(volatile INTPTR * ptr, INTPTR val){
72   INTPTR retval;
73   //note: xchgl always implies lock 
74   __asm__ __volatile__("xchgq %0,%1"
75                        : "=r"(retval)
76                        : "m"(*ptr), "0"(val)
77                        : "memory");
78   return retval;
79  
80 }
81 #else
82 #define LOCKXCHG LOCKXCHG32
83 #endif
84
85 /*
86 static inline int write_trylock(volatile int *lock) {
87   int retval=0;
88   __asm__ __volatile__("xchgl %0,%1"
89                        : "=r"(retval)
90                        : "m"(*lock), "0"(retval)
91                        : "memory");
92   return retval;
93 }
94 */
95
96 #ifdef BIT64
97 static inline INTPTR CAS(volatile void *ptr, unsigned INTPTR old, unsigned INTPTR new){
98   unsigned INTPTR prev;
99   __asm__ __volatile__("lock; cmpxchgq %1,%2"
100                        : "=a"(prev)
101                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
102                        : "memory");
103   return prev;
104 }
105
106 static inline long CAS32(volatile void *ptr, unsigned long old, unsigned long new){
107   unsigned long prev;
108   __asm__ __volatile__("lock; cmpxchgl %k1,%2"
109                        : "=a"(prev)
110                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
111                        : "memory");
112   return prev;
113 }
114 #else
115 static inline long CAS(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 #define CAS32 CAS
124 #endif
125
126
127 static inline int BARRIER(){
128   CFENCE;
129   return 1;
130 }
131
132 static inline int MBARRIER(){
133   MFENCE;
134   return 1;
135 }
136
137
138 #endif // ____MLP_LOCK_H__