1014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved. 2014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// found in the LICENSE file. 4014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/futex-emulation.h" 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include <limits> 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/macros.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/base/platform/time.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/conversions.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles-inl.h" 13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h" 14014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/list-inl.h" 1562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace v8 { 18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace internal { 19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbase::LazyMutex FutexEmulation::mutex_ = LAZY_MUTEX_INITIALIZER; 21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbase::LazyInstance<FutexWaitList>::type FutexEmulation::wait_list_ = 22014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LAZY_INSTANCE_INITIALIZER; 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FutexWaitListNode::NotifyWake() { 26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Lock the FutexEmulation mutex before notifying. We know that the mutex 27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // will have been unlocked if we are currently waiting on the condition 28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // variable. 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The mutex may also not be locked if the other thread is currently handling 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // interrupts, or if FutexEmulation::Wait was just called and the mutex 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // hasn't been locked yet. In either of those cases, we set the interrupted 33014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // flag to true, which will be tested after the mutex is re-locked. 34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::LockGuard<base::Mutex> lock_guard(FutexEmulation::mutex_.Pointer()); 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (waiting_) { 36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch cond_.NotifyOne(); 37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch interrupted_ = true; 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 40014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFutexWaitList::FutexWaitList() : head_(nullptr), tail_(nullptr) {} 43014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 44014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FutexWaitList::AddNode(FutexWaitListNode* node) { 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(node->prev_ == nullptr && node->next_ == nullptr); 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (tail_) { 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch tail_->next_ = node; 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch head_ = node; 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 52014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 53014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->prev_ = tail_; 54014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->next_ = nullptr; 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch tail_ = node; 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid FutexWaitList::RemoveNode(FutexWaitListNode* node) { 60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (node->prev_) { 61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->prev_->next_ = node->next_; 62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch head_ = node->next_; 64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (node->next_) { 67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->next_->prev_ = node->prev_; 68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch tail_ = node->prev_; 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->prev_ = node->next_ = nullptr; 73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject* FutexEmulation::Wait(Isolate* isolate, 77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSArrayBuffer> array_buffer, size_t addr, 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t value, double rel_timeout_ms) { 79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(addr < NumberToSize(array_buffer->byte_length())); 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* backing_store = array_buffer->backing_store(); 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t* p = 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<int32_t*>(static_cast<int8_t*>(backing_store) + addr); 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer()); 86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (*p != value) { 88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return isolate->heap()->not_equal(); 89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FutexWaitListNode* node = isolate->futex_wait_list_node(); 92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->backing_store_ = backing_store; 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->wait_addr_ = addr; 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->waiting_ = true; 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool use_timeout = rel_timeout_ms != V8_INFINITY; 98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeDelta rel_timeout; 100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (use_timeout) { 101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Convert to nanoseconds. 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch double rel_timeout_ns = rel_timeout_ms * 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::Time::kNanosecondsPerMicrosecond * 104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::Time::kMicrosecondsPerMillisecond; 105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (rel_timeout_ns > 106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<double>(std::numeric_limits<int64_t>::max())) { 107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2**63 nanoseconds is 292 years. Let's just treat anything greater as 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // infinite. 109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch use_timeout = false; 110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch rel_timeout = base::TimeDelta::FromNanoseconds( 112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int64_t>(rel_timeout_ns)); 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeTicks start_time = base::TimeTicks::Now(); 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeTicks timeout_time = start_time + rel_timeout; 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeTicks current_time = start_time; 119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch wait_list_.Pointer()->AddNode(node); 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* result; 123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch while (true) { 125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool interrupted = node->interrupted_; 126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->interrupted_ = false; 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Unlock the mutex here to prevent deadlock from lock ordering between 129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // mutex_ and mutexes locked by HandleInterrupts. 130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mutex_.Pointer()->Unlock(); 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Because the mutex is unlocked, we have to be careful about not dropping 133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // an interrupt. The notification can happen in three different places: 134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 1) Before Wait is called: the notification will be dropped, but 135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // interrupted_ will be set to 1. This will be checked below. 136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2) After interrupted has been checked here, but before mutex_ is 137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // acquired: interrupted is checked again below, with mutex_ locked. 138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Because the wakeup signal also acquires mutex_, we know it will not 139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // be able to notify until mutex_ is released below, when waiting on the 140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // condition variable. 141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 3) After the mutex is released in the call to WaitFor(): this 142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // notification will wake up the condition variable. node->waiting() will 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // be false, so we'll loop and then check interrupts. 144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (interrupted) { 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Object* interrupt_object = isolate->stack_guard()->HandleInterrupts(); 14613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch if (interrupt_object->IsException(isolate)) { 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = interrupt_object; 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mutex_.Pointer()->Lock(); 149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mutex_.Pointer()->Lock(); 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (node->interrupted_) { 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // An interrupt occured while the mutex_ was unlocked. Don't wait yet. 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch continue; 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!node->waiting_) { 161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch result = isolate->heap()->ok(); 162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // No interrupts, now wait. 166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (use_timeout) { 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch current_time = base::TimeTicks::Now(); 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (current_time >= timeout_time) { 169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch result = isolate->heap()->timed_out(); 170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch break; 171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::TimeDelta time_until_timeout = timeout_time - current_time; 174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(time_until_timeout.InMicroseconds() >= 0); 175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool wait_for_result = 176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->cond_.WaitFor(mutex_.Pointer(), time_until_timeout); 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch USE(wait_for_result); 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->cond_.Wait(mutex_.Pointer()); 180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Spurious wakeup, interrupt or timeout. 183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 184014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch wait_list_.Pointer()->RemoveNode(node); 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->waiting_ = false; 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return result; 189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject* FutexEmulation::Wake(Isolate* isolate, 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSArrayBuffer> array_buffer, size_t addr, 19362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch uint32_t num_waiters_to_wake) { 194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(addr < NumberToSize(array_buffer->byte_length())); 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int waiters_woken = 0; 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* backing_store = array_buffer->backing_store(); 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer()); 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FutexWaitListNode* node = wait_list_.Pointer()->head_; 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch while (node && num_waiters_to_wake > 0) { 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (backing_store == node->backing_store_ && addr == node->wait_addr_) { 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->waiting_ = false; 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->cond_.NotifyOne(); 20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch if (num_waiters_to_wake != kWakeAll) { 20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch --num_waiters_to_wake; 20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch } 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch waiters_woken++; 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node = node->next_; 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Smi::FromInt(waiters_woken); 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochObject* FutexEmulation::NumWaitersForTesting(Isolate* isolate, 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<JSArrayBuffer> array_buffer, 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t addr) { 221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(addr < NumberToSize(array_buffer->byte_length())); 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* backing_store = array_buffer->backing_store(); 223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch base::LockGuard<base::Mutex> lock_guard(mutex_.Pointer()); 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int waiters = 0; 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FutexWaitListNode* node = wait_list_.Pointer()->head_; 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch while (node) { 229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (backing_store == node->backing_store_ && addr == node->wait_addr_ && 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node->waiting_) { 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch waiters++; 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 233014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch node = node->next_; 235014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return Smi::FromInt(waiters); 238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 242