@@ -528,3 +528,49 @@ threads needs to support both of these proposals.
528
528
529
529
[ passive_segments ] : https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md#design
530
530
[ datacount_section ] : https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md#datacount-section
531
+
532
+ Thread Local Storage
533
+ --------------------
534
+
535
+ Currently, thread-local storage is only supported in the main WASM module
536
+ and cannot be accessed outside of it. This corresponds to the ELF local
537
+ exec TLS model.
538
+
539
+ Additionally, thread local storage depends on bulk memory instructions, and
540
+ therefore support depends on the bulk memory proposal.
541
+
542
+ All thread local variables will be merged into one passive segment called
543
+ ` .tdata ` . This section contains the starting values for all TLS variables.
544
+ The thread local block of every thread will be initialized with this segment.
545
+
546
+ In a threaded build, the linker will create:
547
+
548
+ * an immutable global variable of type ` i32 ` called ` __tls_size ` .
549
+ Its value is the total size of the thread local block for the module,
550
+ i.e. the sum of the sizes of all thread local variables plus padding.
551
+ This value will be ` 0 ` if there are no thread-local variables.
552
+ * a mutable global ` i32 ` called ` __tls_base ` , with a ` i32.const 0 ` initializer.
553
+ * a global function called ` __wasm_init_tls ` with signature ` (i32) -> () ` .
554
+
555
+ To initialize thread-local storage, a thread should do the equivalent of the
556
+ following pseudo-code upon startup:
557
+
558
+ (if (global.get __tls_size) (then
559
+ (call __wasm_init_tls (call malloc (global.get __tls_size)))))
560
+
561
+ ` __wasm_init_tls ` takes a pointer argument containing the memory block to use
562
+ as the thread local storage block of the current thread. It should do nothing if
563
+ there are no thread-local variables. Otherwise, the memory block will be
564
+ initialized with the passive segment ` .tdata ` via the ` memory.init ` instruction.
565
+ It will then set ` __tls_base ` to the address of the memory block passed to
566
+ ` __wasm_init_tls ` .
567
+
568
+ The relocations for thread local variables shall resolve into offsets relative to
569
+ the start of the TLS block. As such, adding the value of ` __tls_base ` yields the
570
+ actual address of the variable. For example, a variable called ` tls_var ` would
571
+ have its address computed as follows:
572
+
573
+ (i32.add (global.get __tls_base) (i32.const tls_var))
574
+
575
+ The variable can then be used as normal. Upon thread exit, the runtime should free
576
+ the memory allocated for the TLS block.
0 commit comments