Crate ecmascript_atomics

Crate ecmascript_atomics 

Source
Expand description

§Racy atomic operations

This library provides atomic operations that match the ECMAScript specification’s memory model: this is effectively the same memory model as Java’s shared variables model. This model allows non-atomic reads and writes to perform data races, and also allows mixed-size atomic reads and writes. Both of these are undefined behaviour in the C++/Rust memory model, which is why these atomic operations are implemented using inline assembly.

The contents of the library are copied and adapted from Mozilla Firefox’s source code, basing mainly on GenerateAtomicOperations.py.

The fundamental constraints on the functions are:

  • That any Atomic operations performed on memory used in these functions must only be accessed using these functions or functions that have a compatible realisation. Importantly, it is strictly undefined behaviour to use normal Rust Atomics in conjunction with the racy atomic operations in this library.

  • That accesses may race without creating C++/Rust undefined behavior: atomic accesses (marked “SeqCst”) may race with non-atomic accesses (marked “Unordered”); overlapping but non-matching, and hence incompatible, atomic accesses may race; and non-atomic accesses may race. The effects of races need not be predictable, so garbage can be produced by a read or written by a write, but the effects must be benign: the program must continue to run, and only the memory in the union of addresses named in the racing accesses may be affected.

The compatibility constraint means that if the memory is accessed elsewhere then it must make compatible decisions about how to implement atomic operations with the functions below.

The safe-for-races constraint means that by and large, it is hard or impossible to implement these primitives in C++/Rust. See “Implementation notes” below.

The “SeqCst” suffix on operations means “sequentially consistent” and means such a function’s operation must have “sequentially consistent” memory ordering. This corresponds with the Rust Atomics’ “SeqCst” ordering.

Note that an “Unordered” access does not provide the atomicity of a “relaxed atomic” access: it can read or write garbage if there’s a race.

§Implementation notes.

It’s not a requirement that these functions be inlined.

In principle these functions will not be written in Rust, thus making races defined behavior if all racy accesses from Rust go via these functions.

The appropriate implementations will be platform-specific and there are some obvious implementation strategies to choose from, sometimes a combination is appropriate:

  • generating the code at run-time with a JIT;
  • hand-written assembler (maybe inline); or
  • using special compiler intrinsics or directives.

Trusting the compiler not to generate code that blows up on a race definitely won’t work in the presence of TSan, or even of optimizing compilers in seemingly-“innocuous” conditions. (See https://www.usenix.org/legacy/event/hotpar11/tech/final_files/Boehm.pdf for details.)

Structs§

Racy
An opaque pointer to memory implementing the ECMAScript atomic memory model.
RacyMemory
Opaque handle to a slab of memory with the ECMAScript Atomics memory model. The slab must be created using the enter method and must be turned back into Rust memory using the exit method (note; this must be strictly synchronised with all possible users of the racy atomic memory).
RacyPtr
Opaque pointer to memory in the ECMAScript racy atomics memory model.
RacySlice
Opaque handle to a slice of memory with the ECMAScript Atomics memory model.

Enums§

Ordering
ECMAScript atomic memory orderings

Traits§

RacyStorage
Public trait for allowing users of the library to name the types that can be natively stored in racy memory. These are effectively the unsigned integers from 1 to 8 bytes in size.

Functions§

atomic_pause
Emits a machine instruction to signal the processor that it is running in a busy-wait spin-loop (“spin lock”).
fence
A sequentially consistent atomic fence.