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