-
Notifications
You must be signed in to change notification settings - Fork 19
/
Sync.cpp
105 lines (89 loc) · 1.7 KB
/
Sync.cpp
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
#include "Ctu.h"
Waitable::Waitable() : presignaled(false), canceled(false) {
}
void Waitable::acquire() {
lock.lock();
}
void Waitable::release() {
lock.unlock();
}
void Waitable::wait(function<int()> cb) {
wait([cb](auto _) { return cb(); });
}
void Waitable::wait(function<int(bool)> cb) {
acquire();
if(!presignaled || (presignaled && cb(canceled) == 0))
waiters.push_back(cb);
presignaled = false;
canceled = false;
release();
}
void Waitable::signal(bool one) {
acquire();
if(waiters.size() == 0 && presignalable())
presignaled = true;
else {
auto realhit = false;
for(auto iter = waiters.begin(); iter != waiters.end();) {
auto res = (*iter)(canceled);
if(res != 0) {
iter = waiters.erase(iter);
} else {
iter++;
}
if(res != -1) {
realhit = true;
if(one)
break;
}
}
if(!realhit && presignalable())
presignaled = true;
}
release();
}
void Waitable::cancel() {
acquire();
canceled = true;
signal();
release();
}
Semaphore::Semaphore(Guest<uint32_t> _vptr) : vptr(_vptr) {
}
void Semaphore::increment() {
acquire();
vptr = *vptr + 1;
release();
}
void Semaphore::decrement() {
acquire();
vptr = *vptr - 1;
release();
}
uint32_t Semaphore::value() {
return *vptr;
}
Mutex::Mutex(Guest<uint32_t> _vptr) : vptr(_vptr) {
}
uint32_t Mutex::value() {
return *vptr;
}
void Mutex::value(uint32_t val) {
vptr = val;
}
ghandle Mutex::owner() {
return value() & 0xBFFFFFFF;
}
void Mutex::owner(ghandle val) {
value((value() & 0x40000000) | val);
}
bool Mutex::hasWaiters() {
return (value() >> 28) != 0;
}
void Mutex::hasWaiters(bool val) {
value((value() & 0xBFFFFFFF) | ((int) val << 30));
}
void Mutex::guestRelease() {
owner(0);
signal();
}