Fix tabbing.... Please fix your editors so they do tabbing correctly!!! (Spaces...
[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__