just an explanation of LOCKXCH
[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
15 #define LOCK_PREFIX \
16   ".section .smp_locks,\"a\"\n"   \
17   "  .align 4\n"                  \
18   "  .long 661f\n"             /* address */\
19   ".previous\n"                   \
20   "661:\n\tlock; "
21
22
23 static inline void atomic_dec(volatile int *v) {
24   __asm__ __volatile__ (LOCK_PREFIX "decl %0"
25                         : "+m" (*v));
26 }
27
28 static inline void atomic_inc(volatile int *v) {
29   __asm__ __volatile__ (LOCK_PREFIX "incl %0"
30                         : "+m" (*v));
31 }
32
33 // this returns TRUE if the atomic subtraction results in
34 // a zero value--this way two threads cannot dec a value
35 // atomically, but then go ahead and both read zero,
36 // thinking they both are the last decrementer
37 static inline int atomic_sub_and_test(int i, volatile int *v) {
38   unsigned char c;
39
40   __asm__ __volatile__ (LOCK_PREFIX "subl %2,%0; sete %1"
41                         : "+m" (*v), "=qm" (c)
42                         : "ir" (i) : "memory");
43   return c;
44 }
45
46
47 static inline void atomic_add(int i, volatile int *v) {
48   __asm__ __volatile__ (LOCK_PREFIX "addl %1,%0"
49                         : "+m" (*v)
50                         : "ir" (i));
51 }
52
53 static inline int LOCKXCHG32(volatile int* ptr, int val){
54   int retval;
55   //note: xchgl always implies lock 
56   __asm__ __volatile__("xchgl %0,%1"
57                        : "=r"(retval)
58                        : "m"(*ptr), "0"(val)
59                        : "memory");
60   return retval;
61  
62 }
63
64
65 // LOCKXCH atomically does the following:
66 // INTPTR retval=*ptr; 
67 // *ptr=val; 
68 // return retval
69 #ifdef BIT64
70 static inline INTPTR LOCKXCHG(volatile INTPTR * ptr, INTPTR val){
71   INTPTR retval;
72   //note: xchgl always implies lock 
73   __asm__ __volatile__("xchgq %0,%1"
74                        : "=r"(retval)
75                        : "m"(*ptr), "0"(val)
76                        : "memory");
77   return retval;
78  
79 }
80 #else
81 #define LOCKXCHG LOCKXCHG32
82 #endif
83
84 /*
85 static inline int write_trylock(volatile int *lock) {
86   int retval=0;
87   __asm__ __volatile__("xchgl %0,%1"
88                        : "=r"(retval)
89                        : "m"(*lock), "0"(retval)
90                        : "memory");
91   return retval;
92 }
93 */
94
95 #ifdef BIT64
96 static inline INTPTR CAS(volatile void *ptr, unsigned INTPTR old, unsigned INTPTR new){
97   unsigned INTPTR prev;
98   __asm__ __volatile__("lock; cmpxchgq %1,%2"
99                        : "=a"(prev)
100                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
101                        : "memory");
102   return prev;
103 }
104 #else
105 static inline long CAS(volatile void *ptr, unsigned long old, unsigned long new){
106   unsigned long prev;
107   __asm__ __volatile__("lock; cmpxchgl %k1,%2"
108                        : "=a"(prev)
109                        : "r"(new), "m"(*__xg(ptr)), "0"(old)
110                        : "memory");
111   return prev;
112 }
113 #endif
114
115 static inline int BARRIER(){
116   CFENCE;
117   return 1;
118 }
119
120
121 #endif // ____MLP_LOCK_H__