wrflock_acquire.cpp
2.59 KB
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
#include <errno.h>
#include <sched.h>
#include "futex.h"
#include "wrflock.h"
int wrflock_wacquire (wrflock_t *lock) {
uint32_t newdata32;
uint32_t data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
do {
if (data32 & WRACQUIRE_VALUE_MASK_32) {
errno=(EOVERFLOW);
return -1;
}
newdata32=data32 | WRACQUIRE_VALUE_MASK_32;
if (newdata32 & FRACQUIRE_VALUE_MASK_32) { //writer reached free barier - new readers goes to next loop
newdata32|=RDNXTLOOP_FLAG_MASK_32;
}
if (newdata32 & NEXTSTATE_WRITE_MASK_32) { //no barier, can take write lock
newdata32=(newdata32 ^ (NEXTSTATE_WRITE_MASK_32 | CURRSTATE_WRITE_MASK_32));
}
} while (!lock->data32[WRFLOCK_STATE_OFFSET].compare_exchange_weak(data32, newdata32, std::memory_order_relaxed, std::memory_order_relaxed));
return 0;
}
int wrflock_racquire (wrflock_t *lock) {
uint32_t newdata32;
uint32_t data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
while (data32 & RDNXTLOOP_FLAG_MASK_32) {
if (data32 & WRFLOCK_RWAITYIELD_MASK_32)
sched_yield();
else
futex_wait_bitset((int*)(&lock->data32[WRFLOCK_STATE_OFFSET]), data32, NULL, FUTEX_BITSET_MATCH_ANY, (data32 & WRFLOCK_PRIVATE_MASK_32)!=0);
data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
}
do {
if ((data32 & RDACQUIRE_COUNTER_MASK_32) == RDACQUIRE_COUNTER_MASK_32) {
errno=(EOVERFLOW);
return -1;
}
newdata32 = data32 + ((uint32_t)1 << RDACQUIRE_COUNTER_SHIFT_32);
} while (!lock->data32[WRFLOCK_COUNTERS_OFFSET].compare_exchange_weak(data32, newdata32, std::memory_order_relaxed, std::memory_order_relaxed));
data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
do {
newdata32 = data32 | RDACQUIRE_VALUE_MASK_32;
if (newdata32 & NEXTSTATE_READFREE_MASK_32) {
newdata32 = (newdata32 ^ (NEXTSTATE_READFREE_MASK_32 | CURRSTATE_READ_MASK_32));
}
} while (!lock->data32[WRFLOCK_STATE_OFFSET].compare_exchange_weak(data32, newdata32, std::memory_order_relaxed, std::memory_order_relaxed));
return 0;
}
int wrflock_facquire (wrflock_t *lock) {
uint32_t newdata32;
uint32_t data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
do {
if (data32 & FRACQUIRE_VALUE_MASK_32) {
errno=(EOVERFLOW);
return -1;
}
newdata32 = data32 | FRACQUIRE_VALUE_MASK_32;
if (newdata32 & NEXTSTATE_READFREE_MASK_32) {
newdata32 = (newdata32 ^ (NEXTSTATE_READFREE_MASK_32 | CURRSTATE_FREE_MASK_32));
}
} while (!lock->data32[WRFLOCK_STATE_OFFSET].compare_exchange_weak(data32, newdata32, std::memory_order_relaxed, std::memory_order_relaxed));
return 0;
}