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

Unified Diff: src/futex-emulation.cc

Issue 1208933006: Atomics Futex API (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: error message 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 side-by-side diff with in-line comments
Download patch
Index: src/futex-emulation.cc
diff --git a/src/futex-emulation.cc b/src/futex-emulation.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8936695fba3d66695edae244e94933fe4addd714
--- /dev/null
+++ b/src/futex-emulation.cc
@@ -0,0 +1,221 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/futex-emulation.h"
+
+#include "src/base/macros.h"
+#include "src/base/platform/time.h"
+#include "src/conversions.h"
+#include "src/handles-inl.h"
+#include "src/isolate.h"
+#include "src/list-inl.h"
+
+namespace v8 {
+namespace internal {
+
+base::LazyMutex FutexEmulation::mutex_ = LAZY_MUTEX_INITIALIZER;
+FutexWaitList FutexEmulation::wait_list_;
+
+
+FutexWaitList::FutexWaitList() : head_(NULL), tail_(NULL) {}
+
+
+void FutexWaitList::AddNode(FutexWaitListNode* node) {
+ DCHECK(node->prev_ == NULL && node->next_ == NULL);
+ if (tail_) {
+ tail_->next_ = node;
+ } else {
+ head_ = node;
+ }
+
+ node->prev_ = tail_;
+ node->next_ = NULL;
+ tail_ = node;
+}
+
+
+void FutexWaitList::RemoveNode(FutexWaitListNode* node) {
+ if (node->prev_)
+ node->prev_->next_ = node->next_;
+ else
+ head_ = node->next_;
+
+ if (node->next_)
+ node->next_->prev_ = node->prev_;
+ else
+ tail_ = node->prev_;
+
+ node->prev_ = node->next_ = NULL;
+}
+
+
+FutexEmulation::Result FutexEmulation::Wait(Isolate* isolate,
+ Handle<JSArrayBuffer> array_buffer,
+ size_t addr, int32_t value) {
+ DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
+
+ void* backing_store = array_buffer->backing_store();
+ int32_t* p =
+ reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
+
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+
+ if (*p != value) {
+ return Result::kNotEqual;
+ }
+
+ FutexWaitListNode* node = isolate->futex_wait_list_node();
+
+ node->backing_store_ = backing_store;
+ node->wait_addr_ = addr;
+ node->waiting_ = true;
+
+ wait_list_.AddNode(node);
+
+ while (node->waiting_) {
+ node->cond_.Wait(mutex_.Pointer());
+ }
+
+ wait_list_.RemoveNode(node);
+
+ return Result::kOk;
+}
+
+
+FutexEmulation::Result FutexEmulation::Wait(
+ Isolate* isolate, Handle<JSArrayBuffer> array_buffer, size_t addr,
+ int32_t value, const base::TimeDelta& rel_timeout) {
+ DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
+
+ void* backing_store = array_buffer->backing_store();
+ int32_t* p =
+ reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
+
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+
+ if (*p != value) {
+ return Result::kNotEqual;
+ }
+
+ FutexWaitListNode* node = isolate->futex_wait_list_node();
+
+ node->backing_store_ = backing_store;
+ node->wait_addr_ = addr;
+ node->waiting_ = true;
+
+ base::TimeDelta rel_time_left = rel_timeout;
+
+ wait_list_.AddNode(node);
+
+ Result result = Result::kOk;
+
+ while (true) {
+ base::Time start_time = base::Time::NowFromSystemTime();
+ if (!node->cond_.WaitFor(mutex_.Pointer(), rel_time_left)) {
+ result = Result::kTimedOut;
+ break;
+ }
+
+ base::Time end_time = base::Time::NowFromSystemTime();
+
+ if (!node->waiting_) {
+ result = Result::kOk;
+ break;
+ }
+
+ // Spurious wakeup.
+ base::TimeDelta waited_for = end_time - start_time;
+ rel_time_left -= waited_for;
+ }
+
+ wait_list_.RemoveNode(node);
+
+ return result;
+}
+
+
+int FutexEmulation::Wake(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
+ size_t addr, int num_waiters_to_wake) {
+ DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
+
+ int waiters_woken = 0;
+ void* backing_store = array_buffer->backing_store();
+
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ FutexWaitListNode* node = wait_list_.head_;
+ while (node && num_waiters_to_wake > 0) {
+ if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
+ node->waiting_ = false;
+ node->cond_.NotifyOne();
+ --num_waiters_to_wake;
+ waiters_woken++;
+ }
+
+ node = node->next_;
+ }
+
+ return waiters_woken;
+}
+
+
+int FutexEmulation::WakeOrRequeue(Isolate* isolate,
+ Handle<JSArrayBuffer> array_buffer,
+ size_t addr, int num_waiters_to_wake,
+ int32_t value, size_t addr2) {
+ DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
+ DCHECK(addr2 < NumberToSize(isolate, array_buffer->byte_length()));
+
+ void* backing_store = array_buffer->backing_store();
+ int32_t* p =
+ reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr);
+
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+ if (*p != value) {
+ return static_cast<int>(Result::kNotEqual);
+ }
+
+ // Wake |num_waiters_to_wake|
+ int waiters_woken = 0;
+ FutexWaitListNode* node = wait_list_.head_;
+ while (node) {
+ if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
+ if (num_waiters_to_wake > 0) {
+ node->waiting_ = false;
+ node->cond_.NotifyOne();
+ --num_waiters_to_wake;
+ waiters_woken++;
+ } else {
+ node->wait_addr_ = addr2;
+ }
+ }
+
+ node = node->next_;
+ }
+
+ return waiters_woken;
+}
+
+int FutexEmulation::NumWaitersForTesting(Isolate* isolate,
+ Handle<JSArrayBuffer> array_buffer,
+ size_t addr) {
+ DCHECK(addr < NumberToSize(isolate, array_buffer->byte_length()));
+ void* backing_store = array_buffer->backing_store();
+
+ base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer());
+
+ int waiters = 0;
+ FutexWaitListNode* node = wait_list_.head_;
+ while (node) {
+ if (backing_store == node->backing_store_ && addr == node->wait_addr_) {
+ waiters++;
+ }
+
+ node = node->next_;
+ }
+
+ return waiters;
+}
+
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698