d75d3f21b51bdba9c446b11ced61865fc59cfe51
[IRC.git] / Robust / src / Runtime / STM / stmlock.h
1 #ifndef _STMLOCK_H_
2 #define _STMLOCK_H_
3
4 #define likely(x) __builtin_expect((x),1)
5 #define unlikely(x) __builtin_expect((x),0)
6
7 #define SWAP_LOCK_BIAS                 1
8 #define CFENCE   asm volatile("":::"memory");
9
10 #define RW_LOCK_BIAS             0x01000000
11
12 #define LOCK_PREFIX \
13   ".section .smp_locks,\"a\"\n"   \
14   "  .align 4\n"                  \
15   "  .long 661f\n"             /* address */\
16   ".previous\n"                   \
17   "661:\n\tlock; "
18
19 static inline initdsmlocks(volatile unsigned int *addr) {
20   (*addr) = SWAP_LOCK_BIAS;
21 }
22 //int write_trylock(volatile unsigned int *lock);
23 //void write_unlock(volatile unsigned int *lock);
24
25 /*
26 static inline void initdsmlocks(volatile unsigned int *addr) {
27   (*addr) = RW_LOCK_BIAS;
28 }
29 */
30
31 static inline int write_trylock(volatile unsigned int *lock) {
32   int retval=0;
33   __asm__ __volatile__("xchgl %0,%1"
34                        : "=r"(retval)
35                        : "m"(*lock), "0"(retval)
36                        : "memory");
37   return retval;
38 }
39
40 static inline void write_unlock(volatile unsigned int *lock) {
41   __asm__ __volatile__("movl $1, %0" : "+m" (*lock)::"memory");
42 }
43
44
45 static inline void atomic_add(int i, volatile unsigned int *v) {
46   __asm__ __volatile__ (LOCK_PREFIX "addl %1,%0"
47                         : "+m" (*v)
48                         : "ir" (i));
49 }
50
51 static inline void rwread_unlock(volatile unsigned int *rw) {
52   __asm__ __volatile__ (LOCK_PREFIX "incl %0" : "+m" (*rw) : : "memory");
53 }
54
55 static inline void rwwrite_unlock(volatile unsigned int *rw) {
56   __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0"
57                         : "+m" (*rw) : "i" (RW_LOCK_BIAS) : "memory");
58 }
59
60 static inline void rwconvert_unlock(volatile unsigned int *rw) {
61   __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0"
62                         : "+m" (*rw) : "i" (RW_LOCK_BIAS-1) : "memory");
63 }
64
65 static inline void atomic_dec(volatile unsigned int *v) {
66   __asm__ __volatile__ (LOCK_PREFIX "decl %0"
67                         : "+m" (*v));
68 }
69
70 static inline void atomic_inc(volatile unsigned int *v) {
71   __asm__ __volatile__ (LOCK_PREFIX "incl %0"
72                         : "+m" (*v));
73 }
74
75 static inline int atomic_sub_and_test(int i, volatile unsigned int *v) {
76   unsigned char c;
77
78   __asm__ __volatile__ (LOCK_PREFIX "subl %2,%0; sete %1"
79                         : "+m" (*v), "=qm" (c)
80                         : "ir" (i) : "memory");
81   return c;
82 }
83
84 static inline unsigned long cas(volatile unsigned int* ptr) {
85   unsigned int prev;
86   __asm__ __volatile__("lock;"
87                        "cmpxchgl %1, %2;"
88                        : "=a"(prev)
89                        : "r"(0), "m"(*ptr), "a"(RW_LOCK_BIAS)
90                        : "memory");
91   return prev==RW_LOCK_BIAS;
92 }
93
94
95 #define atomic_read(v)          (*v)
96
97 static inline int rwread_trylock(volatile unsigned int  *lock) {
98   atomic_dec(lock);
99   if (likely(atomic_read(lock) >=0 ))
100     return 1; //can aquire a new read lock
101   atomic_inc(lock);
102   return 0; //failure
103 }
104
105 static inline int rwwrite_trylock(volatile unsigned int  *lock) {
106   if (likely(cas(lock))) {
107     return 1;
108   }
109   //  if (likely(atomic_sub_and_test(RW_LOCK_BIAS, lock))) {
110   // return 1; // get a write lock
111   //}
112   atomic_add(RW_LOCK_BIAS, lock);
113   return 0; // failed to acquire a write lock
114 }
115
116 static inline int rwconvert_trylock(volatile unsigned int  *lock) {
117   if (likely(atomic_sub_and_test((RW_LOCK_BIAS-1), lock))) {
118     return 1; // get a write lock
119   }
120   atomic_add((RW_LOCK_BIAS-1), lock);
121   return 0; // failed to acquire a write lock
122 }
123 #endif