Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(405)

Side by Side Diff: src/futex-emulation.cc

Issue 1208933006: Atomics Futex API (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: feedback Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/futex-emulation.h ('k') | src/harmony-atomics.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/futex-emulation.h"
6
7 #include "src/base/macros.h"
8 #include "src/base/platform/time.h"
9 #include "src/conversions.h"
10 #include "src/handles-inl.h"
11 #include "src/isolate.h"
12 #include "src/list-inl.h"
13
14 namespace v8 {
15 namespace internal {
16
17 base::LazyMutex FutexEmulation::mutex_ = LAZY_MUTEX_INITIALIZER;
18 base::LazyInstance<FutexWaitList>::type FutexEmulation::wait_list_ =
19 LAZY_INSTANCE_INITIALIZER;
20
21
22 FutexWaitList::FutexWaitList() : head_(nullptr), tail_(nullptr) {}
23
24
25 void FutexWaitList::AddNode(FutexWaitListNode* node) {
26 DCHECK(node->prev_ == nullptr && node->next_ == nullptr);
27 if (tail_) {
28 tail_->next_ = node;
29 } else {
30 head_ = node;
31 }
32
33 node->prev_ = tail_;
34 node->next_ = nullptr;
35 tail_ = node;
36 }
37
38
39 void FutexWaitList::RemoveNode(FutexWaitListNode* node) {
40 if (node->prev_) {
41 node->prev_->next_ = node->next_;
42 } else {
43 head_ = node->next_;
44 }
45
46 if (node->next_) {
47 node->next_->prev_ = node->prev_;
48 } else {
49 tail_ = node->prev_;
50 }
51
52 node->prev_ = node->next_ = nullptr;
53 }
54
55
56 FutexEmulation::Result FutexEmulation::Wait(Isolate* isolate,
57 Handle<JSArrayBuffer> array_buffer,
58 size_t addr, int32_t value) {
59 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
60
61 void* backing_store = array_buffer->backing_store();
62 int32_t* p =
63 reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
64
65 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
66
67 if (*p != value) {
68 return Result::kNotEqual;
69 }
70
71 FutexWaitListNode* node = isolate->futex_wait_list_node();
72
73 node->backing_store_ = backing_store;
74 node->wait_addr_ = addr;
75 node->waiting_ = true;
76
77 wait_list_.Pointer()->AddNode(node);
78
79 while (node->waiting_) {
80 node->cond_.Wait(mutex_.Pointer());
Jarin 2015/07/15 07:42:21 Benedikt pointed out that we cannot block the main
81 }
82
83 wait_list_.Pointer()->RemoveNode(node);
84
85 return Result::kOk;
86 }
87
88
89 FutexEmulation::Result FutexEmulation::Wait(
90 Isolate* isolate, Handle<JSArrayBuffer> array_buffer, size_t addr,
91 int32_t value, const base::TimeDelta& rel_timeout) {
92 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
93
94 void* backing_store = array_buffer->backing_store();
95 int32_t* p =
96 reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
97
98 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
99
100 if (*p != value) {
101 return Result::kNotEqual;
102 }
103
104 FutexWaitListNode* node = isolate->futex_wait_list_node();
105
106 node->backing_store_ = backing_store;
107 node->wait_addr_ = addr;
108 node->waiting_ = true;
109
110 base::TimeDelta rel_time_left = rel_timeout;
111
112 wait_list_.Pointer()->AddNode(node);
113
114 Result result = Result::kOk;
115
116 while (true) {
117 base::Time start_time = base::Time::NowFromSystemTime();
118 if (!node->cond_.WaitFor(mutex_.Pointer(), rel_time_left)) {
119 result = Result::kTimedOut;
120 break;
121 }
122
123 base::Time end_time = base::Time::NowFromSystemTime();
124
125 if (!node->waiting_) {
126 result = Result::kOk;
127 break;
128 }
129
130 // Spurious wakeup.
131 base::TimeDelta waited_for = end_time - start_time;
132 rel_time_left -= waited_for;
133 }
134
135 wait_list_.Pointer()->RemoveNode(node);
136
137 return result;
138 }
139
140
141 int FutexEmulation::Wake(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
142 size_t addr, int num_waiters_to_wake) {
143 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
144
145 int waiters_woken = 0;
146 void* backing_store = array_buffer->backing_store();
147
148 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
149 FutexWaitListNode* node = wait_list_.Pointer()->head_;
150 while (node && num_waiters_to_wake > 0) {
151 if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
152 node->waiting_ = false;
153 node->cond_.NotifyOne();
154 --num_waiters_to_wake;
155 waiters_woken++;
156 }
157
158 node = node->next_;
159 }
160
161 return waiters_woken;
162 }
163
164
165 int FutexEmulation::WakeOrRequeue(Isolate* isolate,
166 Handle<JSArrayBuffer> array_buffer,
167 size_t addr, int num_waiters_to_wake,
168 int32_t value, size_t addr2) {
169 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
170 DCHECK(addr2 < NumberToSize(isolate, array_buffer->byte_length()));
171
172 void* backing_store = array_buffer->backing_store();
173 int32_t* p =
174 reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
175
176 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
177 if (*p != value) {
178 return static_cast<int>(Result::kNotEqual);
179 }
180
181 // Wake |num_waiters_to_wake|
182 int waiters_woken = 0;
183 FutexWaitListNode* node = wait_list_.Pointer()->head_;
184 while (node) {
185 if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
186 if (num_waiters_to_wake > 0) {
187 node->waiting_ = false;
188 node->cond_.NotifyOne();
189 --num_waiters_to_wake;
190 waiters_woken++;
191 } else {
192 node->wait_addr_ = addr2;
193 }
194 }
195
196 node = node->next_;
197 }
198
199 return waiters_woken;
200 }
201
202 int FutexEmulation::NumWaitersForTesting(Isolate* isolate,
203 Handle<JSArrayBuffer> array_buffer,
204 size_t addr) {
205 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
206 void* backing_store = array_buffer->backing_store();
207
208 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
209
210 int waiters = 0;
211 FutexWaitListNode* node = wait_list_.Pointer()->head_;
212 while (node) {
213 if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
214 waiters++;
215 }
216
217 node = node->next_;
218 }
219
220 return waiters;
221 }
222
223 } // namespace internal
224 } // namespace v8
OLDNEW
« no previous file with comments | « src/futex-emulation.h ('k') | src/harmony-atomics.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698