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

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
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 FutexWaitList FutexEmulation::wait_list_;
Jarin 2015/07/10 12:11:39 Static initializers are not allowed by Chrome. You
binji 2015/07/14 19:24:36 Done.
19
20
21 FutexWaitList::FutexWaitList() : head_(NULL), tail_(NULL) {}
22
23
24 void FutexWaitList::AddNode(FutexWaitListNode* node) {
25 DCHECK(node->prev_ == NULL && node->next_ == NULL);
26 if (tail_) {
27 tail_->next_ = node;
28 } else {
29 head_ = node;
30 }
31
32 node->prev_ = tail_;
33 node->next_ = NULL;
34 tail_ = node;
35 }
36
37
38 void FutexWaitList::RemoveNode(FutexWaitListNode* node) {
39 if (node->prev_)
Jarin 2015/07/10 12:11:39 braces, please.
binji 2015/07/14 19:24:36 Done.
40 node->prev_->next_ = node->next_;
41 else
42 head_ = node->next_;
43
44 if (node->next_)
45 node->next_->prev_ = node->prev_;
46 else
47 tail_ = node->prev_;
48
49 node->prev_ = node->next_ = NULL;
50 }
51
52
53 FutexEmulation::Result FutexEmulation::Wait(Isolate* isolate,
54 Handle<JSArrayBuffer> array_buffer,
55 size_t addr, int32_t value) {
56 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
57
58 void* backing_store = array_buffer->backing_store();
59 int32_t* p =
60 reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
61
62 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
63
64 if (*p != value) {
65 return Result::kNotEqual;
66 }
67
68 FutexWaitListNode* node = isolate->futex_wait_list_node();
69
70 node->backing_store_ = backing_store;
71 node->wait_addr_ = addr;
72 node->waiting_ = true;
73
74 wait_list_.AddNode(node);
75
76 while (node->waiting_) {
77 node->cond_.Wait(mutex_.Pointer());
78 }
79
80 wait_list_.RemoveNode(node);
81
82 return Result::kOk;
83 }
84
85
86 FutexEmulation::Result FutexEmulation::Wait(
87 Isolate* isolate, Handle<JSArrayBuffer> array_buffer, size_t addr,
88 int32_t value, const base::TimeDelta& rel_timeout) {
89 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
90
91 void* backing_store = array_buffer->backing_store();
92 int32_t* p =
93 reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
94
95 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
96
97 if (*p != value) {
98 return Result::kNotEqual;
99 }
100
101 FutexWaitListNode* node = isolate->futex_wait_list_node();
102
103 node->backing_store_ = backing_store;
104 node->wait_addr_ = addr;
105 node->waiting_ = true;
106
107 base::TimeDelta rel_time_left = rel_timeout;
108
109 wait_list_.AddNode(node);
110
111 Result result = Result::kOk;
112
113 while (true) {
114 base::Time start_time = base::Time::NowFromSystemTime();
115 if (!node->cond_.WaitFor(mutex_.Pointer(), rel_time_left)) {
116 result = Result::kTimedOut;
117 break;
118 }
119
120 base::Time end_time = base::Time::NowFromSystemTime();
121
122 if (!node->waiting_) {
123 result = Result::kOk;
124 break;
125 }
126
127 // Spurious wakeup.
128 base::TimeDelta waited_for = end_time - start_time;
129 rel_time_left -= waited_for;
130 }
131
132 wait_list_.RemoveNode(node);
133
134 return result;
135 }
136
137
138 int FutexEmulation::Wake(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
139 size_t addr, int num_waiters_to_wake) {
140 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
141
142 int waiters_woken = 0;
143 void* backing_store = array_buffer->backing_store();
144
145 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
146 FutexWaitListNode* node = wait_list_.head_;
147 while (node && num_waiters_to_wake > 0) {
148 if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
149 node->waiting_ = false;
150 node->cond_.NotifyOne();
151 --num_waiters_to_wake;
152 waiters_woken++;
153 }
154
155 node = node->next_;
156 }
157
158 return waiters_woken;
159 }
160
161
162 int FutexEmulation::WakeOrRequeue(Isolate* isolate,
163 Handle<JSArrayBuffer> array_buffer,
164 size_t addr, int num_waiters_to_wake,
165 int32_t value, size_t addr2) {
166 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
167 DCHECK(addr2 < NumberToSize(isolate, array_buffer->byte_length()));
168
169 void* backing_store = array_buffer->backing_store();
170 int32_t* p =
171 reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
172
173 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
174 if (*p != value) {
175 return static_cast<int>(Result::kNotEqual);
176 }
177
178 // Wake |num_waiters_to_wake|
179 int waiters_woken = 0;
180 FutexWaitListNode* node = wait_list_.head_;
181 while (node) {
182 if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
183 if (num_waiters_to_wake > 0) {
184 node->waiting_ = false;
185 node->cond_.NotifyOne();
186 --num_waiters_to_wake;
187 waiters_woken++;
188 } else {
189 node->wait_addr_ = addr2;
190 }
191 }
192
193 node = node->next_;
194 }
195
196 return waiters_woken;
197 }
198
199 int FutexEmulation::NumWaitersForTesting(Isolate* isolate,
200 Handle<JSArrayBuffer> array_buffer,
201 size_t addr) {
202 DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
203 void* backing_store = array_buffer->backing_store();
204
205 base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
206
207 int waiters = 0;
208 FutexWaitListNode* node = wait_list_.head_;
209 while (node) {
210 if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
211 waiters++;
212 }
213
214 node = node->next_;
215 }
216
217 return waiters;
218 }
219
220 } // namespace internal
221 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698