OLD | NEW |
(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 #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/lazy-instance.h" |
| 12 #include "src/base/macros.h" |
| 13 #include "src/base/platform/condition-variable.h" |
| 14 #include "src/base/platform/mutex.h" |
| 15 #include "src/handles.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 |
| 24 // https://docs.google.com/document/d/1NDGA_gZJ7M7w1Bh8S0AoDyEqwDdRh4uSoTPSNn77P
Fk |
| 25 |
| 26 namespace v8 { |
| 27 |
| 28 namespace base { |
| 29 class TimeDelta; |
| 30 } // base |
| 31 |
| 32 namespace internal { |
| 33 |
| 34 class Isolate; |
| 35 |
| 36 class FutexWaitListNode { |
| 37 public: |
| 38 FutexWaitListNode() |
| 39 : prev_(nullptr), |
| 40 next_(nullptr), |
| 41 backing_store_(nullptr), |
| 42 wait_addr_(0), |
| 43 waiting_(false) {} |
| 44 |
| 45 private: |
| 46 friend class FutexEmulation; |
| 47 friend class FutexWaitList; |
| 48 |
| 49 base::ConditionVariable cond_; |
| 50 FutexWaitListNode* prev_; |
| 51 FutexWaitListNode* next_; |
| 52 void* backing_store_; |
| 53 size_t wait_addr_; |
| 54 bool waiting_; |
| 55 |
| 56 DISALLOW_COPY_AND_ASSIGN(FutexWaitListNode); |
| 57 }; |
| 58 |
| 59 |
| 60 class FutexWaitList { |
| 61 public: |
| 62 FutexWaitList(); |
| 63 |
| 64 void AddNode(FutexWaitListNode* node); |
| 65 void RemoveNode(FutexWaitListNode* node); |
| 66 |
| 67 private: |
| 68 friend class FutexEmulation; |
| 69 |
| 70 FutexWaitListNode* head_; |
| 71 FutexWaitListNode* tail_; |
| 72 |
| 73 DISALLOW_COPY_AND_ASSIGN(FutexWaitList); |
| 74 }; |
| 75 |
| 76 |
| 77 class FutexEmulation : public AllStatic { |
| 78 public: |
| 79 // These must match the values in src/harmony-atomics.js |
| 80 enum class Result { |
| 81 kOk = 0, |
| 82 kNotEqual = -1, |
| 83 kTimedOut = -2, |
| 84 }; |
| 85 |
| 86 // Check that array_buffer[addr] == value, and return kNotEqual if not. If |
| 87 // they are equal, block execution on |isolate|'s thread until woken via |
| 88 // |Wake|, then return kOk. The initial check and the decision to wait happen |
| 89 // atomically. |
| 90 static Result Wait(Isolate* isolate, Handle<JSArrayBuffer> array_buffer, |
| 91 size_t addr, int32_t value); |
| 92 |
| 93 // Check that array_buffer[addr] == value, and return kNotEqual if not. If |
| 94 // they are equal, block execution on |isolate|'s thread until woken via |
| 95 // |Wake|, or when the time given in |rel_timeout| elapses. If woken, return |
| 96 // kOk, otherwise return kTimedOut. The initial check and the decision to |
| 97 // wait happen atomically. |
| 98 static Result Wait(Isolate* isolate, Handle<JSArrayBuffer> array_buffer, |
| 99 size_t addr, int32_t value, |
| 100 const base::TimeDelta& rel_timeout); |
| 101 |
| 102 // Wake |num_waiters_to_wake| threads that are waiting on the given |addr|. |
| 103 // The rest of the waiters will continue to wait. The return value is the |
| 104 // number of woken waiters. |
| 105 static int Wake(Isolate* isolate, Handle<JSArrayBuffer> array_buffer, |
| 106 size_t addr, int num_waiters_to_wake); |
| 107 |
| 108 // Check that array_buffer[addr] == value, and return kNotEqual if not. If |
| 109 // they are equal, wake |num_waiters_to_wake| threads that are waiting on the |
| 110 // given |addr|. The rest of the waiters will continue to wait, but will now |
| 111 // be waiting on |addr2| instead of |addr|. The return value is the number of |
| 112 // woken waiters or kNotEqual as described above. |
| 113 static int WakeOrRequeue(Isolate* isolate, Handle<JSArrayBuffer> array_buffer, |
| 114 size_t addr, int num_waiters_to_wake, int32_t value, |
| 115 size_t addr2); |
| 116 |
| 117 // Return the number of threads waiting on |addr|. Should only be used for |
| 118 // testing. |
| 119 static int NumWaitersForTesting(Isolate* isolate, |
| 120 Handle<JSArrayBuffer> array_buffer, |
| 121 size_t addr); |
| 122 |
| 123 private: |
| 124 static base::LazyMutex mutex_; |
| 125 static base::LazyInstance<FutexWaitList>::type wait_list_; |
| 126 }; |
| 127 } |
| 128 } // namespace v8::internal |
| 129 |
| 130 #endif // V8_FUTEX_EMULATION_H_ |
OLD | NEW |