DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d38398e5144e)

VCS Links

AtomicsObject

FutexState

FutexThread

WaitResult

WakeReason

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 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 FutexThread
{
    friend class AutoLockFutexAPI;

public:
    static MOZ_MUST_USE bool initialize();
    static void destroy();

    static void lock();
    static void unlock();

    FutexThread();
    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 this is associated with.
    //
    // 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 thread to which the FutexThread 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.
    ThreadLocalData<bool> canWait_;
};

JSObject*
InitAtomicsClass(JSContext* cx, HandleObject obj);

}  /* namespace js */

#endif /* builtin_AtomicsObject_h */