Difference between revisions of "WebAssembly/Threads"
From Lazarus wiki
Jump to navigationJump to search (→Atomic instructions: - there's now a new compiler option to enable WASM threads: -CTwasmthreads, it should be used to compile the RTL, instead of -dFPC_WASM_THREADS) |
(→Atomic instructions: - atomic functions are available in the WebAssembly unit) |
||
Line 22: | Line 22: | ||
Note that these require proper alignment (4 bytes) of the target, otherwise they trap (i.e. terminate the program with a stack trace). | Note that these require proper alignment (4 bytes) of the target, otherwise they trap (i.e. terminate the program with a stack trace). | ||
+ | |||
+ | In addition to that, there are many more atomic functions available in the WebAssembly unit: | ||
+ | |||
+ | const | ||
+ | { Special values for the TimeoutNanoseconds parameter of AtomicWait } | ||
+ | awtInfiniteTimeout = -1; | ||
+ | { AtomicWait result values } | ||
+ | awrOk = 0; { woken by another agent in the cluster } | ||
+ | awrNotEqual = 1; { the loaded value did not match the expected value } | ||
+ | awrTimedOut = 2; { not woken before timeout expired } | ||
+ | |||
+ | procedure AtomicFence; inline; | ||
+ | |||
+ | function AtomicLoad(constref Mem: Int8): Int8; inline; | ||
+ | function AtomicLoad(constref Mem: UInt8): UInt8; inline; | ||
+ | function AtomicLoad(constref Mem: Int16): Int16; inline; | ||
+ | function AtomicLoad(constref Mem: UInt16): UInt16; inline; | ||
+ | function AtomicLoad(constref Mem: Int32): Int32; inline; | ||
+ | function AtomicLoad(constref Mem: UInt32): UInt32; inline; | ||
+ | function AtomicLoad(constref Mem: Int64): Int64; inline; | ||
+ | function AtomicLoad(constref Mem: UInt64): UInt64; inline; | ||
+ | |||
+ | procedure AtomicStore(out Mem: Int8; Data: Int8); inline; | ||
+ | procedure AtomicStore(out Mem: UInt8; Data: UInt8); inline; | ||
+ | procedure AtomicStore(out Mem: Int16; Data: Int16); inline; | ||
+ | procedure AtomicStore(out Mem: UInt16; Data: UInt16); inline; | ||
+ | procedure AtomicStore(out Mem: Int32; Data: Int32); inline; | ||
+ | procedure AtomicStore(out Mem: UInt32; Data: UInt32); inline; | ||
+ | procedure AtomicStore(out Mem: Int64; Data: Int64); inline; | ||
+ | procedure AtomicStore(out Mem: UInt64; Data: UInt64); inline; | ||
+ | |||
+ | function AtomicAdd(var Mem: Int8; Data: Int8): Int8; inline; | ||
+ | function AtomicAdd(var Mem: UInt8; Data: UInt8): UInt8; inline; | ||
+ | function AtomicAdd(var Mem: Int16; Data: Int16): Int16; inline; | ||
+ | function AtomicAdd(var Mem: UInt16; Data: UInt16): UInt16; inline; | ||
+ | function AtomicAdd(var Mem: Int32; Data: Int32): Int32; inline; | ||
+ | function AtomicAdd(var Mem: UInt32; Data: UInt32): UInt32; inline; | ||
+ | function AtomicAdd(var Mem: Int64; Data: Int64): Int64; inline; | ||
+ | function AtomicAdd(var Mem: UInt64; Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicSub(var Mem: Int8; Data: Int8): Int8; inline; | ||
+ | function AtomicSub(var Mem: UInt8; Data: UInt8): UInt8; inline; | ||
+ | function AtomicSub(var Mem: Int16; Data: Int16): Int16; inline; | ||
+ | function AtomicSub(var Mem: UInt16; Data: UInt16): UInt16; inline; | ||
+ | function AtomicSub(var Mem: Int32; Data: Int32): Int32; inline; | ||
+ | function AtomicSub(var Mem: UInt32; Data: UInt32): UInt32; inline; | ||
+ | function AtomicSub(var Mem: Int64; Data: Int64): Int64; inline; | ||
+ | function AtomicSub(var Mem: UInt64; Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicAnd(var Mem: Int8; Data: Int8): Int8; inline; | ||
+ | function AtomicAnd(var Mem: UInt8; Data: UInt8): UInt8; inline; | ||
+ | function AtomicAnd(var Mem: Int16; Data: Int16): Int16; inline; | ||
+ | function AtomicAnd(var Mem: UInt16; Data: UInt16): UInt16; inline; | ||
+ | function AtomicAnd(var Mem: Int32; Data: Int32): Int32; inline; | ||
+ | function AtomicAnd(var Mem: UInt32; Data: UInt32): UInt32; inline; | ||
+ | function AtomicAnd(var Mem: Int64; Data: Int64): Int64; inline; | ||
+ | function AtomicAnd(var Mem: UInt64; Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicOr(var Mem: Int8; Data: Int8): Int8; inline; | ||
+ | function AtomicOr(var Mem: UInt8; Data: UInt8): UInt8; inline; | ||
+ | function AtomicOr(var Mem: Int16; Data: Int16): Int16; inline; | ||
+ | function AtomicOr(var Mem: UInt16; Data: UInt16): UInt16; inline; | ||
+ | function AtomicOr(var Mem: Int32; Data: Int32): Int32; inline; | ||
+ | function AtomicOr(var Mem: UInt32; Data: UInt32): UInt32; inline; | ||
+ | function AtomicOr(var Mem: Int64; Data: Int64): Int64; inline; | ||
+ | function AtomicOr(var Mem: UInt64; Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicXor(var Mem: Int8; Data: Int8): Int8; inline; | ||
+ | function AtomicXor(var Mem: UInt8; Data: UInt8): UInt8; inline; | ||
+ | function AtomicXor(var Mem: Int16; Data: Int16): Int16; inline; | ||
+ | function AtomicXor(var Mem: UInt16; Data: UInt16): UInt16; inline; | ||
+ | function AtomicXor(var Mem: Int32; Data: Int32): Int32; inline; | ||
+ | function AtomicXor(var Mem: UInt32; Data: UInt32): UInt32; inline; | ||
+ | function AtomicXor(var Mem: Int64; Data: Int64): Int64; inline; | ||
+ | function AtomicXor(var Mem: UInt64; Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicExchange(var Mem: Int8; Data: Int8): Int8; inline; | ||
+ | function AtomicExchange(var Mem: UInt8; Data: UInt8): UInt8; inline; | ||
+ | function AtomicExchange(var Mem: Int16; Data: Int16): Int16; inline; | ||
+ | function AtomicExchange(var Mem: UInt16; Data: UInt16): UInt16; inline; | ||
+ | function AtomicExchange(var Mem: Int32; Data: Int32): Int32; inline; | ||
+ | function AtomicExchange(var Mem: UInt32; Data: UInt32): UInt32; inline; | ||
+ | function AtomicExchange(var Mem: Int64; Data: Int64): Int64; inline; | ||
+ | function AtomicExchange(var Mem: UInt64; Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicCompareExchange(var Mem: Int8; Compare, Data: Int8): Int8; inline; | ||
+ | function AtomicCompareExchange(var Mem: UInt8; Compare, Data: UInt8): UInt8; inline; | ||
+ | function AtomicCompareExchange(var Mem: Int16; Compare, Data: Int16): Int16; inline; | ||
+ | function AtomicCompareExchange(var Mem: UInt16; Compare, Data: UInt16): UInt16; inline; | ||
+ | function AtomicCompareExchange(var Mem: Int32; Compare, Data: Int32): Int32; inline; | ||
+ | function AtomicCompareExchange(var Mem: UInt32; Compare, Data: UInt32): UInt32; inline; | ||
+ | function AtomicCompareExchange(var Mem: Int64; Compare, Data: Int64): Int64; inline; | ||
+ | function AtomicCompareExchange(var Mem: UInt64; Compare, Data: UInt64): UInt64; inline; | ||
+ | |||
+ | function AtomicWait(constref Mem: Int32; Compare: Int32; TimeoutNanoseconds: Int64): Int32; inline; | ||
+ | function AtomicWait(constref Mem: UInt32; Compare: UInt32; TimeoutNanoseconds: Int64): Int32; inline; | ||
+ | function AtomicWait(constref Mem: Int64; Compare: Int64; TimeoutNanoseconds: Int64): Int32; inline; | ||
+ | function AtomicWait(constref Mem: UInt64; Compare: UInt64; TimeoutNanoseconds: Int64): Int32; inline; | ||
+ | |||
+ | function AtomicNotify(constref Mem: Int32; Count: UInt32): UInt32; inline; | ||
+ | function AtomicNotify(constref Mem: UInt32; Count: UInt32): UInt32; inline; | ||
+ | function AtomicNotify(constref Mem: Int64; Count: UInt32): UInt32; inline; | ||
+ | function AtomicNotify(constref Mem: UInt64; Count: UInt32): UInt32; inline; | ||
== Thread support == | == Thread support == |
Revision as of 00:35, 28 May 2022
Thread support
This page contains some collected informations on the features needed for thread support in WebAssembly (in the browser).
Thread support consists of 2 parts:
- Atomic instructions.
- Actually starting a thread.
Atomic instructions
When the Free Pascal RTL is compiled with -CTwasmthreads, the following RTL functions will use the new atomic instructions and thus should be thread safe in a multithreaded environment:
InterlockedDecrement InterlockedIncrement InterlockedExchange InterlockedCompareExchange InterlockedExchangeAdd
Note that these require proper alignment (4 bytes) of the target, otherwise they trap (i.e. terminate the program with a stack trace).
In addition to that, there are many more atomic functions available in the WebAssembly unit:
const { Special values for the TimeoutNanoseconds parameter of AtomicWait } awtInfiniteTimeout = -1; { AtomicWait result values } awrOk = 0; { woken by another agent in the cluster } awrNotEqual = 1; { the loaded value did not match the expected value } awrTimedOut = 2; { not woken before timeout expired } procedure AtomicFence; inline; function AtomicLoad(constref Mem: Int8): Int8; inline; function AtomicLoad(constref Mem: UInt8): UInt8; inline; function AtomicLoad(constref Mem: Int16): Int16; inline; function AtomicLoad(constref Mem: UInt16): UInt16; inline; function AtomicLoad(constref Mem: Int32): Int32; inline; function AtomicLoad(constref Mem: UInt32): UInt32; inline; function AtomicLoad(constref Mem: Int64): Int64; inline; function AtomicLoad(constref Mem: UInt64): UInt64; inline; procedure AtomicStore(out Mem: Int8; Data: Int8); inline; procedure AtomicStore(out Mem: UInt8; Data: UInt8); inline; procedure AtomicStore(out Mem: Int16; Data: Int16); inline; procedure AtomicStore(out Mem: UInt16; Data: UInt16); inline; procedure AtomicStore(out Mem: Int32; Data: Int32); inline; procedure AtomicStore(out Mem: UInt32; Data: UInt32); inline; procedure AtomicStore(out Mem: Int64; Data: Int64); inline; procedure AtomicStore(out Mem: UInt64; Data: UInt64); inline; function AtomicAdd(var Mem: Int8; Data: Int8): Int8; inline; function AtomicAdd(var Mem: UInt8; Data: UInt8): UInt8; inline; function AtomicAdd(var Mem: Int16; Data: Int16): Int16; inline; function AtomicAdd(var Mem: UInt16; Data: UInt16): UInt16; inline; function AtomicAdd(var Mem: Int32; Data: Int32): Int32; inline; function AtomicAdd(var Mem: UInt32; Data: UInt32): UInt32; inline; function AtomicAdd(var Mem: Int64; Data: Int64): Int64; inline; function AtomicAdd(var Mem: UInt64; Data: UInt64): UInt64; inline; function AtomicSub(var Mem: Int8; Data: Int8): Int8; inline; function AtomicSub(var Mem: UInt8; Data: UInt8): UInt8; inline; function AtomicSub(var Mem: Int16; Data: Int16): Int16; inline; function AtomicSub(var Mem: UInt16; Data: UInt16): UInt16; inline; function AtomicSub(var Mem: Int32; Data: Int32): Int32; inline; function AtomicSub(var Mem: UInt32; Data: UInt32): UInt32; inline; function AtomicSub(var Mem: Int64; Data: Int64): Int64; inline; function AtomicSub(var Mem: UInt64; Data: UInt64): UInt64; inline; function AtomicAnd(var Mem: Int8; Data: Int8): Int8; inline; function AtomicAnd(var Mem: UInt8; Data: UInt8): UInt8; inline; function AtomicAnd(var Mem: Int16; Data: Int16): Int16; inline; function AtomicAnd(var Mem: UInt16; Data: UInt16): UInt16; inline; function AtomicAnd(var Mem: Int32; Data: Int32): Int32; inline; function AtomicAnd(var Mem: UInt32; Data: UInt32): UInt32; inline; function AtomicAnd(var Mem: Int64; Data: Int64): Int64; inline; function AtomicAnd(var Mem: UInt64; Data: UInt64): UInt64; inline; function AtomicOr(var Mem: Int8; Data: Int8): Int8; inline; function AtomicOr(var Mem: UInt8; Data: UInt8): UInt8; inline; function AtomicOr(var Mem: Int16; Data: Int16): Int16; inline; function AtomicOr(var Mem: UInt16; Data: UInt16): UInt16; inline; function AtomicOr(var Mem: Int32; Data: Int32): Int32; inline; function AtomicOr(var Mem: UInt32; Data: UInt32): UInt32; inline; function AtomicOr(var Mem: Int64; Data: Int64): Int64; inline; function AtomicOr(var Mem: UInt64; Data: UInt64): UInt64; inline; function AtomicXor(var Mem: Int8; Data: Int8): Int8; inline; function AtomicXor(var Mem: UInt8; Data: UInt8): UInt8; inline; function AtomicXor(var Mem: Int16; Data: Int16): Int16; inline; function AtomicXor(var Mem: UInt16; Data: UInt16): UInt16; inline; function AtomicXor(var Mem: Int32; Data: Int32): Int32; inline; function AtomicXor(var Mem: UInt32; Data: UInt32): UInt32; inline; function AtomicXor(var Mem: Int64; Data: Int64): Int64; inline; function AtomicXor(var Mem: UInt64; Data: UInt64): UInt64; inline; function AtomicExchange(var Mem: Int8; Data: Int8): Int8; inline; function AtomicExchange(var Mem: UInt8; Data: UInt8): UInt8; inline; function AtomicExchange(var Mem: Int16; Data: Int16): Int16; inline; function AtomicExchange(var Mem: UInt16; Data: UInt16): UInt16; inline; function AtomicExchange(var Mem: Int32; Data: Int32): Int32; inline; function AtomicExchange(var Mem: UInt32; Data: UInt32): UInt32; inline; function AtomicExchange(var Mem: Int64; Data: Int64): Int64; inline; function AtomicExchange(var Mem: UInt64; Data: UInt64): UInt64; inline; function AtomicCompareExchange(var Mem: Int8; Compare, Data: Int8): Int8; inline; function AtomicCompareExchange(var Mem: UInt8; Compare, Data: UInt8): UInt8; inline; function AtomicCompareExchange(var Mem: Int16; Compare, Data: Int16): Int16; inline; function AtomicCompareExchange(var Mem: UInt16; Compare, Data: UInt16): UInt16; inline; function AtomicCompareExchange(var Mem: Int32; Compare, Data: Int32): Int32; inline; function AtomicCompareExchange(var Mem: UInt32; Compare, Data: UInt32): UInt32; inline; function AtomicCompareExchange(var Mem: Int64; Compare, Data: Int64): Int64; inline; function AtomicCompareExchange(var Mem: UInt64; Compare, Data: UInt64): UInt64; inline; function AtomicWait(constref Mem: Int32; Compare: Int32; TimeoutNanoseconds: Int64): Int32; inline; function AtomicWait(constref Mem: UInt32; Compare: UInt32; TimeoutNanoseconds: Int64): Int32; inline; function AtomicWait(constref Mem: Int64; Compare: Int64; TimeoutNanoseconds: Int64): Int32; inline; function AtomicWait(constref Mem: UInt64; Compare: UInt64; TimeoutNanoseconds: Int64): Int32; inline; function AtomicNotify(constref Mem: Int32; Count: UInt32): UInt32; inline; function AtomicNotify(constref Mem: UInt32; Count: UInt32): UInt32; inline; function AtomicNotify(constref Mem: Int64; Count: UInt32): UInt32; inline; function AtomicNotify(constref Mem: UInt64; Count: UInt32): UInt32; inline;
Thread support
Webassembly relies on the hosting environment to actually start threads.
Some extra info: