summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/AtomicsObject.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/AtomicsObject.h')
-rw-r--r--js/src/builtin/AtomicsObject.h156
1 files changed, 156 insertions, 0 deletions
diff --git a/js/src/builtin/AtomicsObject.h b/js/src/builtin/AtomicsObject.h
new file mode 100644
index 000000000..adb6fb986
--- /dev/null
+++ b/js/src/builtin/AtomicsObject.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef builtin_AtomicsObject_h
+#define builtin_AtomicsObject_h
+
+#include "mozilla/Maybe.h"
+#include "mozilla/TimeStamp.h"
+
+#include "jsobj.h"
+
+#include "threading/ConditionVariable.h"
+#include "vm/MutexIDs.h"
+
+namespace js {
+
+class AtomicsObject : public JSObject
+{
+ public:
+ static const Class class_;
+ static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
+ static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
+};
+
+MOZ_MUST_USE bool atomics_compareExchange(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_exchange(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_load(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_store(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_add(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_sub(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_and(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_or(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_xor(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_isLockFree(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_wait(JSContext* cx, unsigned argc, Value* vp);
+MOZ_MUST_USE bool atomics_wake(JSContext* cx, unsigned argc, Value* vp);
+
+/* asm.js callouts */
+namespace wasm { class Instance; }
+int32_t atomics_add_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
+int32_t atomics_sub_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
+int32_t atomics_and_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
+int32_t atomics_or_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
+int32_t atomics_xor_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
+int32_t atomics_cmpxchg_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t oldval, int32_t newval);
+int32_t atomics_xchg_asm_callout(wasm::Instance* i, int32_t vt, int32_t offset, int32_t value);
+
+class FutexRuntime
+{
+ friend class AutoLockFutexAPI;
+
+public:
+ static MOZ_MUST_USE bool initialize();
+ static void destroy();
+
+ static void lock();
+ static void unlock();
+
+ FutexRuntime();
+ MOZ_MUST_USE bool initInstance();
+ void destroyInstance();
+
+ // Parameters to wake().
+ enum WakeReason {
+ WakeExplicit, // Being asked to wake up by another thread
+ WakeForJSInterrupt // Interrupt requested
+ };
+
+ // Result code from wait().
+ enum WaitResult {
+ FutexOK,
+ FutexTimedOut
+ };
+
+ // Block the calling thread and wait.
+ //
+ // The futex lock must be held around this call.
+ //
+ // The timeout is the number of milliseconds, with fractional
+ // times allowed; specify mozilla::Nothing() for an indefinite
+ // wait.
+ //
+ // wait() will not wake up spuriously. It will return true and
+ // set *result to a return code appropriate for
+ // Atomics.wait() on success, and return false on error.
+ MOZ_MUST_USE bool wait(JSContext* cx, js::UniqueLock<js::Mutex>& locked,
+ mozilla::Maybe<mozilla::TimeDuration>& timeout, WaitResult* result);
+
+ // Wake the thread represented by this Runtime.
+ //
+ // The futex lock must be held around this call. (The sleeping
+ // thread will not wake up until the caller of Atomics.wake()
+ // releases the lock.)
+ //
+ // If the thread is not waiting then this method does nothing.
+ //
+ // If the thread is waiting in a call to wait() and the
+ // reason is WakeExplicit then the wait() call will return
+ // with Woken.
+ //
+ // If the thread is waiting in a call to wait() and the
+ // reason is WakeForJSInterrupt then the wait() will return
+ // with WaitingNotifiedForInterrupt; in the latter case the caller
+ // of wait() must handle the interrupt.
+ void wake(WakeReason reason);
+
+ bool isWaiting();
+
+ // If canWait() returns false (the default) then wait() is disabled
+ // on the runtime to which the FutexRuntime belongs.
+ bool canWait() {
+ return canWait_;
+ }
+
+ void setCanWait(bool flag) {
+ canWait_ = flag;
+ }
+
+ private:
+ enum FutexState {
+ Idle, // We are not waiting or woken
+ Waiting, // We are waiting, nothing has happened yet
+ WaitingNotifiedForInterrupt, // We are waiting, but have been interrupted,
+ // and have not yet started running the
+ // interrupt handler
+ WaitingInterrupted, // We are waiting, but have been interrupted
+ // and are running the interrupt handler
+ Woken // Woken by a script call to Atomics.wake
+ };
+
+ // Condition variable that this runtime will wait on.
+ js::ConditionVariable* cond_;
+
+ // Current futex state for this runtime. When not in a wait this
+ // is Idle; when in a wait it is Waiting or the reason the futex
+ // is about to wake up.
+ FutexState state_;
+
+ // Shared futex lock for all runtimes. We can perhaps do better,
+ // but any lock will need to be per-domain (consider SharedWorker)
+ // or coarser.
+ static mozilla::Atomic<js::Mutex*> lock_;
+
+ // A flag that controls whether waiting is allowed.
+ bool canWait_;
+};
+
+JSObject*
+InitAtomicsClass(JSContext* cx, HandleObject obj);
+
+} /* namespace js */
+
+#endif /* builtin_AtomicsObject_h */