LCOV - code coverage report
Current view: top level - src - futex-emulation.h (source / functions) Hit Total Coverage
Test: app.info Lines: 4 4 100.0 %
Date: 2019-04-17 Functions: 0 0 -

          Line data    Source code
       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             : #ifndef V8_FUTEX_EMULATION_H_
       6             : #define V8_FUTEX_EMULATION_H_
       7             : 
       8             : #include <stdint.h>
       9             : 
      10             : #include "src/allocation.h"
      11             : #include "src/base/atomicops.h"
      12             : #include "src/base/lazy-instance.h"
      13             : #include "src/base/macros.h"
      14             : #include "src/base/platform/condition-variable.h"
      15             : #include "src/base/platform/mutex.h"
      16             : 
      17             : // Support for emulating futexes, a low-level synchronization primitive. They
      18             : // are natively supported by Linux, but must be emulated for other platforms.
      19             : // This library emulates them on all platforms using mutexes and condition
      20             : // variables for consistency.
      21             : //
      22             : // This is used by the Futex API defined in the SharedArrayBuffer draft spec,
      23             : // found here: https://github.com/tc39/ecmascript_sharedmem
      24             : 
      25             : namespace v8 {
      26             : 
      27             : namespace base {
      28             : class TimeDelta;
      29             : }  // base
      30             : 
      31             : namespace internal {
      32             : 
      33             : template <typename T>
      34             : class Handle;
      35             : class Isolate;
      36             : class JSArrayBuffer;
      37             : 
      38             : class AtomicsWaitWakeHandle {
      39             :  public:
      40         920 :   explicit AtomicsWaitWakeHandle(Isolate* isolate) : isolate_(isolate) {}
      41             : 
      42             :   void Wake();
      43             :   inline bool has_stopped() const { return stopped_; }
      44             : 
      45             :  private:
      46             :   Isolate* isolate_;
      47             :   bool stopped_ = false;
      48             : };
      49             : 
      50       62407 : class FutexWaitListNode {
      51             :  public:
      52             :   FutexWaitListNode()
      53             :       : prev_(nullptr),
      54             :         next_(nullptr),
      55             :         backing_store_(nullptr),
      56             :         wait_addr_(0),
      57             :         waiting_(false),
      58       62420 :         interrupted_(false) {}
      59             : 
      60             :   void NotifyWake();
      61             : 
      62             :  private:
      63             :   friend class FutexEmulation;
      64             :   friend class FutexWaitList;
      65             :   friend class ResetWaitingOnScopeExit;
      66             : 
      67             :   base::ConditionVariable cond_;
      68             :   // prev_ and next_ are protected by FutexEmulation::mutex_.
      69             :   FutexWaitListNode* prev_;
      70             :   FutexWaitListNode* next_;
      71             :   void* backing_store_;
      72             :   size_t wait_addr_;
      73             :   // waiting_ and interrupted_ are protected by FutexEmulation::mutex_
      74             :   // if this node is currently contained in FutexEmulation::wait_list_
      75             :   // or an AtomicsWaitWakeHandle has access to it.
      76             :   bool waiting_;
      77             :   bool interrupted_;
      78             : 
      79             :   DISALLOW_COPY_AND_ASSIGN(FutexWaitListNode);
      80             : };
      81             : 
      82             : 
      83             : class FutexWaitList {
      84             :  public:
      85             :   FutexWaitList();
      86             : 
      87             :   void AddNode(FutexWaitListNode* node);
      88             :   void RemoveNode(FutexWaitListNode* node);
      89             : 
      90             :  private:
      91             :   friend class FutexEmulation;
      92             : 
      93             :   FutexWaitListNode* head_;
      94             :   FutexWaitListNode* tail_;
      95             : 
      96             :   DISALLOW_COPY_AND_ASSIGN(FutexWaitList);
      97             : };
      98             : 
      99             : class ResetWaitingOnScopeExit {
     100             :  public:
     101             :   explicit ResetWaitingOnScopeExit(FutexWaitListNode* node) : node_(node) {}
     102         911 :   ~ResetWaitingOnScopeExit() { node_->waiting_ = false; }
     103             : 
     104             :  private:
     105             :   FutexWaitListNode* node_;
     106             : 
     107             :   DISALLOW_COPY_AND_ASSIGN(ResetWaitingOnScopeExit);
     108             : };
     109             : 
     110             : class FutexEmulation : public AllStatic {
     111             :  public:
     112             :   // Pass to Wake() to wake all waiters.
     113             :   static const uint32_t kWakeAll = UINT32_MAX;
     114             : 
     115             :   // Check that array_buffer[addr] == value, and return "not-equal" if not. If
     116             :   // they are equal, block execution on |isolate|'s thread until woken via
     117             :   // |Wake|, or when the time given in |rel_timeout_ms| elapses. Note that
     118             :   // |rel_timeout_ms| can be Infinity.
     119             :   // If woken, return "ok", otherwise return "timed-out". The initial check and
     120             :   // the decision to wait happen atomically.
     121             :   static Object WaitJs(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
     122             :                        size_t addr, int32_t value, double rel_timeout_ms);
     123             : 
     124             :   // Same as WaitJs above except it returns 0 (ok), 1 (not equal) and 2 (timed
     125             :   // out) as expected by Wasm.
     126             :   static Object Wait32(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
     127             :                        size_t addr, int32_t value, double rel_timeout_ms);
     128             : 
     129             :   // Same as Wait32 above except it checks for an int64_t value in the
     130             :   // array_buffer.
     131             :   static Object Wait64(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
     132             :                        size_t addr, int64_t value, double rel_timeout_ms);
     133             : 
     134             :   // Wake |num_waiters_to_wake| threads that are waiting on the given |addr|.
     135             :   // |num_waiters_to_wake| can be kWakeAll, in which case all waiters are
     136             :   // woken. The rest of the waiters will continue to wait. The return value is
     137             :   // the number of woken waiters.
     138             :   static Object Wake(Handle<JSArrayBuffer> array_buffer, size_t addr,
     139             :                      uint32_t num_waiters_to_wake);
     140             : 
     141             :   // Return the number of threads waiting on |addr|. Should only be used for
     142             :   // testing.
     143             :   static Object NumWaitersForTesting(Handle<JSArrayBuffer> array_buffer,
     144             :                                      size_t addr);
     145             : 
     146             :  private:
     147             :   friend class FutexWaitListNode;
     148             :   friend class AtomicsWaitWakeHandle;
     149             : 
     150             :   template <typename T>
     151             :   static Object Wait(Isolate* isolate, Handle<JSArrayBuffer> array_buffer,
     152             :                      size_t addr, T value, double rel_timeout_ms);
     153             : 
     154             :   // `mutex_` protects the composition of `wait_list_` (i.e. no elements may be
     155             :   // added or removed without holding this mutex), as well as the `waiting_`
     156             :   // and `interrupted_` fields for each individual list node that is currently
     157             :   // part of the list. It must be the mutex used together with the `cond_`
     158             :   // condition variable of such nodes.
     159             :   static base::LazyMutex mutex_;
     160             :   static base::LazyInstance<FutexWaitList>::type wait_list_;
     161             : };
     162             : }  // namespace internal
     163             : }  // namespace v8
     164             : 
     165             : #endif  // V8_FUTEX_EMULATION_H_

Generated by: LCOV version 1.10