The non-threaded RTS has threads but not mutexes! We need mutexes!
The time has come...
The non-threaded RTS needs threads and mutexes.
The non-threaded RTS _already_ uses threads on all platforms except for wasm/js.
* Windows: threads are always available, whether we use them or not. We use them implicitly for control-c handling (the console event is run in a new OS thread implicitly by the OS), and for the timer (the timer queue API uses threads under the hood).
* Posix platforms: we no longer use a signal-based ticker (MR !15757), we use a P-thread based ticker implementation on all posix platforms (MR !15781)
* wasm/js: these platforms do not have threads, but they also do not have signals, and thus the RTS on these platforms do not support thread pre-emption or any of the other features that rely on the periodic timer: idle GC, deadlock detection, periodic eventlog flushing, sampling profiling.
So we already threads (except on the platforms that _really_ do not support threads). Using threads without also using mutexes is not a sustainable situation. It leads to madness like issue #26222 where there's a race between the timer thread and other threads only in the non-threaded RTS, because the mutex locking code that is already present is compiled out on the non-threaded RTS!
Using threads without mutexes is madness. If we can accept that we actually _are_ using threads (on all platforms where pre-emption is supported) then we must also accept that we can and must also uses mutexes.
The first step would be to introduce macros:
* `ACQUIRE_LOCK_ALWAYS`
* `TRY_ACQUIRE_LOCK_ALWAYS`
* `RELEASE_LOCK_ALWAYS`
The naming convention here follows the convention used for atomics, i.e. `RELAXED_LOAD` vs `RELAXED_LOAD_AWLAYS`. The non-always versions are non-atomic on the non-threaded RTS, while the always versions are always atomic. The theory being that the normal use for atomics is coordination between capabilities, and there's only one capability on the non-threaded RTS, but for the few cases where the sharing is between signal handlers or other threads, even in the non-threaded RTS then we have to use the always variants.
issue