wrflock_release.cpp
2.9 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
67
68
69
70
71
72
#include <errno.h>
#include <limits.h>
#include "futex.h"
#include "wrflock.h"
#include <stdio.h>
int wrflock_wrelease (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|CURRSTATE_WRITE_MASK_32|RDNXTLOOP_FLAG_MASK_32));
if (newdata32 & RDACQUIRE_VALUE_MASK_32) {
newdata32|=CURRSTATE_READ_MASK_32;
} else if (newdata32 & FRACQUIRE_VALUE_MASK_32) {
newdata32|=CURRSTATE_FREE_MASK_32;
} else {
newdata32|=NEXTSTATE_READFREE_MASK_32;
}
} while (!lock->data32[WRFLOCK_STATE_OFFSET].compare_exchange_weak(data32, newdata32, std::memory_order_release, std::memory_order_relaxed));
if ((!(newdata32&WRFLOCK_RWAITYIELD_MASK_32) && (newdata32&(CURRSTATE_READ_MASK_32|RDNXTLOOP_FLAG_MASK_32))) || (!(newdata32&WRFLOCK_FWAITYIELD_MASK_32) && newdata32&CURRSTATE_FREE_MASK_32))
return futex_wake_bitset((int *) &lock->data32[WRFLOCK_STATE_OFFSET], INT_MAX, FUTEX_BITSET_MATCH_ANY, (data32 & WRFLOCK_PRIVATE_MASK_32)!=0);
return 0;
}
int wrflock_rrelease (wrflock_t *lock) {
uint64_t newdata64;
uint64_t data64=lock->data64.load(std::memory_order_relaxed);
do {
if (!(data64 & RDACQUIRE_COUNTER_MASK_64)) {
errno=(EOVERFLOW);
return -1;
}
newdata64=data64 - ((uint64_t)1 << RDACQUIRE_COUNTER_SHIFT_64);
if (!(newdata64 & RDACQUIRE_COUNTER_MASK_64)) {
newdata64=newdata64 & (~(RDACQUIRE_VALUE_MASK_64));
if (newdata64 & FRACQUIRE_VALUE_MASK_64)
newdata64=(newdata64 ^ (CURRSTATE_READ_MASK_64 | CURRSTATE_FREE_MASK_64));
else
newdata64=(newdata64 ^ (CURRSTATE_READ_MASK_64 | NEXTSTATE_READFREE_MASK_64));
}
} while (!lock->data64.compare_exchange_weak(data64, newdata64, std::memory_order_release, std::memory_order_relaxed));
if (!(newdata64&WRFLOCK_FWAITYIELD_MASK_64) && newdata64&CURRSTATE_FREE_MASK_64)
return futex_wake_bitset((int *) &lock->data32[WRFLOCK_STATE_OFFSET], INT_MAX, FUTEX_BITSET_MATCH_ANY, (data64 & WRFLOCK_PRIVATE_MASK_64)!=0);
return 0;
}
int wrflock_frelease (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|CURRSTATE_FREE_MASK_32));
if (newdata32 & WRACQUIRE_VALUE_MASK_32) {
newdata32|=CURRSTATE_WRITE_MASK_32;
} else {
newdata32|=NEXTSTATE_WRITE_MASK_32;
}
} while (!lock->data32[WRFLOCK_STATE_OFFSET].compare_exchange_weak(data32, newdata32, std::memory_order_release, std::memory_order_relaxed));
if (!(newdata32&WRFLOCK_WWAITYIELD_MASK_32) && newdata32&CURRSTATE_WRITE_MASK_32)
return futex_wake_bitset((int *) &lock->data32[WRFLOCK_STATE_OFFSET], INT_MAX, FUTEX_BITSET_MATCH_ANY, (data32 & WRFLOCK_PRIVATE_MASK_32)!=0);
return 0;
}