wrflock_wait.cpp
3.83 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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <sched.h>
#include <errno.h>
#include "futex.h"
#include "wrflock.h"
#include <stdio.h>
int wrflock_wtimewait (struct wrflock_t *lock, const struct timespec *abstime)
{
uint32_t data32;
int err;
if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) {
errno=(EINVAL);
return -1;
}
while (1) {
data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
if (data32 & CURRSTATE_WRITE_MASK_32) {
std::atomic_thread_fence(std::memory_order_acquire);
return 0;
}
if (!(data32&WRFLOCK_WWAITYIELD_MASK_32)){
err=futex_wait_bitset((int*)(&lock->data32[WRFLOCK_STATE_OFFSET]), data32, abstime, FUTEX_BITSET_MATCH_ANY, (data32 & WRFLOCK_PRIVATE_MASK_32)!=0);
if (err<0 && (errno == ETIMEDOUT || errno == EINTR))
return err;
} else {
if (abstime){
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
if ((time.tv_sec>abstime->tv_sec) || (time.tv_sec==abstime->tv_sec && time.tv_nsec>=abstime->tv_nsec)) {
errno=ETIMEDOUT;
return -1;
}
}
sched_yield();
}
}
}
int wrflock_rtimewait (struct wrflock_t *lock, const struct timespec *abstime)
{
uint32_t data32;
int err;
if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) {
errno=(EINVAL);
return -1;
}
while (1) {
data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
if (data32 & CURRSTATE_READ_MASK_32){
std::atomic_thread_fence(std::memory_order_acquire);
return 0;
}
if (!(data32&WRFLOCK_RWAITYIELD_MASK_32)){
err=futex_wait_bitset((int*)(&lock->data32[WRFLOCK_STATE_OFFSET]), data32, abstime, FUTEX_BITSET_MATCH_ANY, (data32 & WRFLOCK_PRIVATE_MASK_32)!=0);
if (err<0 && (errno == ETIMEDOUT || errno == EINTR))
return err;
} else {
if (abstime){
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
if ((time.tv_sec>abstime->tv_sec) || (time.tv_sec==abstime->tv_sec && time.tv_nsec>=abstime->tv_nsec)){
errno=ETIMEDOUT;
return -1;
}
}
sched_yield();
}
}
}
int wrflock_ftimewait (struct wrflock_t *lock, const struct timespec *abstime)
{
uint32_t data32;
int err=0;
if (abstime && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)) {
errno=(EINVAL);
return -1;
}
while (1) {
data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_relaxed);
if (data32 & CURRSTATE_FREE_MASK_32) {
std::atomic_thread_fence(std::memory_order_acquire);
return 0;
}
if (!(data32&WRFLOCK_FWAITYIELD_MASK_32)) {
err=futex_wait_bitset((int*)(&lock->data32[WRFLOCK_STATE_OFFSET]), data32, abstime, FUTEX_BITSET_MATCH_ANY, (data32 & WRFLOCK_PRIVATE_MASK_32)!=0);
if (err<0 && (errno == ETIMEDOUT || errno == EINTR))
return err;
} else {
if (abstime){
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
if ((time.tv_sec>abstime->tv_sec) || (time.tv_sec==abstime->tv_sec && time.tv_nsec>=abstime->tv_nsec)) {
errno=ETIMEDOUT;
return -1;
}
}
sched_yield();
}
}
}
int wrflock_wwait (wrflock_t *lock){
return wrflock_wtimewait (lock, NULL);
}
int wrflock_rwait (wrflock_t *lock){
return wrflock_rtimewait (lock, NULL);
}
int wrflock_fwait (wrflock_t *lock){
return wrflock_ftimewait (lock, NULL);
}
int wrflock_wtrywait (wrflock_t *lock){
const uint32_t data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_acquire);
if (!(data32 & CURRSTATE_WRITE_MASK_32)){
errno=(EAGAIN);
return -1;
}
return 0;
}
int wrflock_rtrywait (wrflock_t *lock){
const uint32_t data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_acquire);
if (!(data32 & CURRSTATE_READ_MASK_32)){
errno=(EAGAIN);
return -1;
}
return 0;
}
int wrflock_ftrywait (wrflock_t *lock){
const uint32_t data32 = lock->data32[WRFLOCK_STATE_OFFSET].load(std::memory_order_acquire);
if (!(data32 & CURRSTATE_FREE_MASK_32)){
errno=(EAGAIN);
return -1;
}
return 0;
}