Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef builtin_AtomicsObject_h
8 : #define builtin_AtomicsObject_h
9 :
10 : #include "mozilla/Maybe.h"
11 : #include "mozilla/TimeStamp.h"
12 :
13 : #include "jsobj.h"
14 :
15 : #include "threading/ConditionVariable.h"
16 : #include "vm/MutexIDs.h"
17 :
18 : namespace js {
19 :
20 : class AtomicsObject : public JSObject
21 : {
22 : public:
23 : static const Class class_;
24 : static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
25 : static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
26 : };
27 :
28 : MOZ_MUST_USE bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp);
29 : MOZ_MUST_USE bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
30 : MOZ_MUST_USE bool atomics_load(JSContext* cx, unsigned argc, Value* vp);
31 : MOZ_MUST_USE bool atomics_store(JSContext* cx, unsigned argc, Value* vp);
32 : MOZ_MUST_USE bool atomics_add(JSContext* cx, unsigned argc, Value* vp);
33 : MOZ_MUST_USE bool atomics_sub(JSContext* cx, unsigned argc, Value* vp);
34 : MOZ_MUST_USE bool atomics_and(JSContext* cx, unsigned argc, Value* vp);
35 : MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
36 : MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
37 : MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
38 : MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
39 : MOZ_MUST_USE bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
40 :
41 : /* asm.js callouts */
42 : namespace wasm { class Instance; }
43 : int32_t atomics_add_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
44 : int32_t atomics_sub_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
45 : int32_t atomics_and_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
46 : int32_t atomics_or_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
47 : int32_t atomics_xor_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
48 : int32_t atomics_cmpxchg_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t oldval, int32_t newval);
49 : int32_t atomics_xchg_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
50 :
51 : class FutexThread
52 : {
53 : friend class AutoLockFutexAPI;
54 :
55 : public:
56 : static MOZ_MUST_USE bool initialize();
57 : static void destroy();
58 :
59 : static void lock();
60 : static void unlock();
61 :
62 : FutexThread();
63 : MOZ_MUST_USE bool initInstance();
64 : void destroyInstance();
65 :
66 : // Parameters to wake().
67 : enum WakeReason {
68 : WakeExplicit, // Being asked to wake up by another thread
69 : WakeForJSInterrupt // Interrupt requested
70 : };
71 :
72 : // Result code from wait().
73 : enum WaitResult {
74 : FutexOK,
75 : FutexTimedOut
76 : };
77 :
78 : // Block the calling thread and wait.
79 : //
80 : // The futex lock must be held around this call.
81 : //
82 : // The timeout is the number of milliseconds, with fractional
83 : // times allowed; specify mozilla::Nothing() for an indefinite
84 : // wait.
85 : //
86 : // wait() will not wake up spuriously. It will return true and
87 : // set *result to a return code appropriate for
88 : // Atomics.wait() on success, and return false on error.
89 : MOZ_MUST_USE bool wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
90 : mozilla::Maybe<mozilla::TimeDuration>& timeout, WaitResult* result);
91 :
92 : // Wake the thread this is associated with.
93 : //
94 : // The futex lock must be held around this call. (The sleeping
95 : // thread will not wake up until the caller of Atomics.wake()
96 : // releases the lock.)
97 : //
98 : // If the thread is not waiting then this method does nothing.
99 : //
100 : // If the thread is waiting in a call to wait() and the
101 : // reason is WakeExplicit then the wait() call will return
102 : // with Woken.
103 : //
104 : // If the thread is waiting in a call to wait() and the
105 : // reason is WakeForJSInterrupt then the wait() will return
106 : // with WaitingNotifiedForInterrupt; in the latter case the caller
107 : // of wait() must handle the interrupt.
108 : void wake(WakeReason reason);
109 :
110 : bool isWaiting();
111 :
112 : // If canWait() returns false (the default) then wait() is disabled
113 : // on the thread to which the FutexThread belongs.
114 0 : bool canWait() {
115 0 : return canWait_;
116 : }
117 :
118 1 : void setCanWait(bool flag) {
119 1 : canWait_ = flag;
120 1 : }
121 :
122 : private:
123 : enum FutexState {
124 : Idle, // We are not waiting or woken
125 : Waiting, // We are waiting, nothing has happened yet
126 : WaitingNotifiedForInterrupt, // We are waiting, but have been interrupted,
127 : // and have not yet started running the
128 : // interrupt handler
129 : WaitingInterrupted, // We are waiting, but have been interrupted
130 : // and are running the interrupt handler
131 : Woken // Woken by a script call to Atomics.wake
132 : };
133 :
134 : // Condition variable that this runtime will wait on.
135 : js::ConditionVariable* cond_;
136 :
137 : // Current futex state for this runtime. When not in a wait this
138 : // is Idle; when in a wait it is Waiting or the reason the futex
139 : // is about to wake up.
140 : FutexState state_;
141 :
142 : // Shared futex lock for all runtimes. We can perhaps do better,
143 : // but any lock will need to be per-domain (consider SharedWorker)
144 : // or coarser.
145 : static mozilla::Atomic<js::Mutex*> lock_;
146 :
147 : // A flag that controls whether waiting is allowed.
148 : ThreadLocalData<bool> canWait_;
149 : };
150 :
151 : JSObject*
152 : InitAtomicsClass(JSContext* cx, HandleObject obj);
153 :
154 : } /* namespace js */
155 :
156 : #endif /* builtin_AtomicsObject_h */
|