add more lock primitives
[IRC.git] / Robust / src / Runtime / STM / stmlock.h
1 #ifndef _STMLOCK_H_
2 #define _STMLOCK_H_
3
4 #define SWAP_LOCK_BIAS                 1
5 #define CFENCE   asm volatile("":::"memory");
6
7 #define RW_LOCK_BIAS             0x01000000
8
9 #define LOCK_PREFIX \
10   ".section .smp_locks,\"a\"\n"   \
11   "  .align 4\n"                  \
12   "  .long 661f\n"             /* address */\
13   ".previous\n"                   \
14   "661:\n\tlock; "
15
16 void initdsmlocks(volatile unsigned int *addr);
17 //int write_trylock(volatile unsigned int *lock);
18 //void write_unlock(volatile unsigned int *lock);
19
20 /*
21 static inline void initdsmlocks(volatile unsigned int *addr) {
22   (*addr) = RW_LOCK_BIAS;
23 }
24 */
25
26 static inline int write_trylock(volatile unsigned int *lock) {
27   int retval=0;
28   __asm__ __volatile__("xchgl %0,%1"
29                        : "=r"(retval)
30                        : "m"(*lock), "0"(retval)
31                        : "memory");
32   return retval;
33 }
34
35 static inline void write_unlock(volatile unsigned int *lock) {
36   __asm__ __volatile__("movl $1, %0" : "+m" (*lock)::"memory");
37 }
38
39
40 static inline void atomic_add(int i, unsigned int *v) {
41   __asm__ __volatile__ (LOCK_PREFIX "addl %1,%0"
42                         : "+m" (*v)
43                         : "ir" (i));
44 }
45
46 static inline void read_unlock(volatile unsigned int *rw) {
47   __asm__ __volatile__ (LOCK_PREFIX "incl %0" : "+m" (*rw) : : "memory");
48 }
49
50 static inline void write_unlock(volatile unsigned int *rw) {
51   __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0"
52                         : "+m" (*rw) : "i" (RW_LOCK_BIAS) : "memory");
53 }
54
55 static inline void atomic_dec(volatile unsigned int *v) {
56   __asm__ __volatile__ (LOCK_PREFIX "decl %0"
57                         : "+m" (*v));
58 }
59
60 static inline void atomic_inc(volatile unsigned int *v) {
61   __asm__ __volatile__ (LOCK_PREFIX "incl %0"
62                         : "+m" (*v));
63 }
64
65 static inline int atomic_sub_and_test(int i, unsigned int *v) {
66   unsigned char c;
67
68   __asm__ __volatile__ (LOCK_PREFIX "subl %2,%0; sete %1"
69                         : "+m" (*v), "=qm" (c)
70                         : "ir" (i) : "memory");
71   return c;
72 }
73
74 #define atomic_read(v)          (*v)
75
76 static inline int read_trylock(volatile unsigned int  *lock) {
77   atomic_dec(lock);
78   if (atomic_read(lock) >= 0)
79     return 1; //can aquire a new read lock
80   atomic_inc(lock);
81   return 0; //failure
82 }
83
84 static inline int write_trylock(volatile unsigned int  *lock) {
85   if (atomic_sub_and_test(RW_LOCK_BIAS, *lock)) {
86     return 1; // get a write lock
87   }
88   atomic_add(RW_LOCK_BIAS, *lock);
89   return 0; // failed to acquire a write lock
90 }
91 #endif