-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathproxysql_atomic.h
82 lines (68 loc) · 2.13 KB
/
proxysql_atomic.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifdef PROXYSQL_USE_SPINLOCK
// PROXYSQL_USE_SPINLOCK is NOT define
// spinlock have been removed in 1.4.1 due to issue #977 , to compile in ARM
// this file is kept for reference, and will be completely removed in future
#ifndef PROXYSQL_ATOMIC
#define PROXYSQL_ATOMIC
/*
typedef unsigned spinlock;
typedef struct _rwlock_t rwlock_t;
struct _rwlock_t {
spinlock lock;
unsigned readers;
};
*/
#define atomic_inc(P) __sync_add_and_fetch((P), 1)
#define atomic_dec(P) __sync_add_and_fetch((P), -1)
/* Compile read-write barrier */
#define barrier() asm volatile("": : :"memory")
/* Pause instruction to prevent excess processor bus usage */
#define cpu_relax_pa() asm volatile("pause\n": : :"memory")
#define cpu_relax_us() usleep(1)
#define RELAX_TRIES 100
static inline unsigned xchg_32(void *ptr, unsigned x) {
__asm__ __volatile__("xchgl %0,%1"
:"=r" (x)
:"m" (*(volatile unsigned *)ptr), "0" (x)
:"memory");
return x;
}
static inline void spinlock_rwlock_init(rwlock_t *l) {
memset(l,0,sizeof(rwlock_t));
}
static inline void spinlock_init(spinlock *l) {
memset(l,0,sizeof(spinlock));
}
static inline void spin_lock(spinlock *lock) {
int i=RELAX_TRIES;
while (1) {
if (!xchg_32(lock, 1)) return;
while (*lock) { if (i) { i--; cpu_relax_pa(); } else { i=RELAX_TRIES; cpu_relax_us(); } }
}
}
static inline void spin_unlock(spinlock *lock) {
barrier();
*lock = 0;
}
static inline void spin_wrlock(rwlock_t *l) {
spin_lock(&l->lock);
int i=RELAX_TRIES;
while (l->readers) { if (i) { i--; cpu_relax_pa(); } else { i=RELAX_TRIES; cpu_relax_us(); } }
}
static inline void spin_wrunlock(rwlock_t *l) {
spin_unlock(&l->lock);
}
static inline void spin_rdlock(rwlock_t *l) {
int i=RELAX_TRIES;
while (1) {
atomic_inc(&l->readers);
if (!l->lock) return;
atomic_dec(&l->readers);
while (l->lock) { if (i) { i--; cpu_relax_pa(); } else { i=RELAX_TRIES; cpu_relax_us(); } }
}
}
static inline void spin_rdunlock(rwlock_t *l) {
atomic_dec(&l->readers);
}
#endif /* PROXYSQL_ATOMIC */
#endif // PROXYSQL_USE_SPINLOCK