Skip to content

Commit c263fc6

Browse files
committed
Update TLS documentation
1 parent eee41b5 commit c263fc6

File tree

1 file changed

+49
-11
lines changed

1 file changed

+49
-11
lines changed

Sources/LLVM/Global.swift

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,63 @@ import cllvm
55
/// Enumerates the supported models of reference of thread-local variables.
66
///
77
/// These models are listed from the most general, but least optimized, to the
8-
/// fastest, but most restrictive.
8+
/// fastest, but most restrictive in general, as architectural differences
9+
/// play a role in determining the access patterns for thread-local storage.
910
///
10-
/// Documentation of these models quotes the [Oracle Linker and Libraries
11-
/// Guide](https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter8-20.html).
11+
/// In general, support for thread-local storage in statically-linked
12+
/// applications is limited: some platforms may not even define the behavior of
13+
/// TLS in such cases. This is usually not an issue as statically-linked code
14+
/// only ever has one TLS block, the offset of the variables within that block
15+
/// is known, and support for additional dynamic loading of code in
16+
/// statically-linked code is limited.
17+
///
18+
/// Computing the thread-specific address of a TLS variable is usually a dynamic
19+
/// process that relies on an ABI-defined function call (usually
20+
/// `__tls_get_addr`) to do the heavy lifting.
21+
///
22+
/// TLS access models fall into two classes: static and dynamic. Regardless of
23+
/// the actual model used, the dynamic linker must process all relocations
24+
/// for thread-local variables whenever the module is loaded. Some models,
25+
/// therefore, provide for a decrease in the overall number of relocations at
26+
/// a cost of restrictions on which modules can access variables.
1227
public enum ThreadLocalModel {
1328
/// The variable is not thread local and hence has no associated model.
1429
case notThreadLocal
1530
/// Allows reference of all thread-local variables, from either a shared
1631
/// object or a dynamic executable. This model also supports the deferred
1732
/// allocation of a block of thread-local storage when the block is first
18-
/// referenced from a specific thread.
33+
/// referenced from a specific thread. Note that the linker is free to
34+
/// optimize accesses using this model to one of the more specific models
35+
/// below which may ultimately defeat lazy allocation of the TLS storagee
36+
/// block.
37+
///
38+
/// The code generated for this model does nto assume that any information
39+
/// about the module or variable offsets is known at link-time. Instead, the
40+
/// exact value of these variables is computed by the dynamic linker at
41+
/// runtime and passeed to `__tls_get_addr` in an architecture-specific way.
42+
///
43+
/// If possible, this model should be avoided if one of the more specific
44+
/// models applies out of concern for code size and application startup
45+
/// performance.
1946
case generalDynamic
20-
/// This model is an optimization of the General Dynamic model. The compiler
47+
/// This model is an optimization of the `generalDynamic` model. The compiler
2148
/// might determine that a variable is bound locally, or protected, within the
22-
/// object being built. In this case, the compiler instructs the link-editor
23-
/// to statically bind the dynamic `tlsoffset` and use this model.
49+
/// object being built. In this case, the compiler instructs the linker
50+
/// to statically bind the dynamic offset of the variable and use this model.
2451
///
2552
/// This model provides a performance benefit over the General Dynamic model.
26-
/// Only one call to `tls_get_addr()` is required per function, to determine
27-
/// the address of `dtv0,m`. The dynamic thread-local storage offset, bound at
28-
/// link-edit time, is added to the `dtv0,m` address for each reference.
53+
/// Only one call to `__tls_get_addr` is required per function, to determine
54+
/// the starting address of the variable within the TLS block for its
55+
/// parent module. Additional accesses can add an offset to this address
56+
/// value for repeated accesses.
57+
///
58+
/// The optimization available over the `generalDynamic` model is defeated if
59+
/// a variable is only ever accessed once, as its access would incur the
60+
/// same `__tls_get_addr` call and the additional overhead of the offset
61+
/// calculation.
62+
///
63+
/// The linker cannot, in general, optimize from the general dynamic model
64+
/// to the local dynamic model.
2965
case localDynamic
3066
/// This model can only reference thread-local variables which are available
3167
/// as part of the initial static thread-local template. This template is
@@ -43,8 +79,10 @@ public enum ThreadLocalModel {
4379
/// objects should reference thread-local variables using a dynamic model of
4480
/// thread-local storage.
4581
case initialExec
82+
/// This model is an optimization of the `localDynamic` model.
83+
///
4684
/// This model can only reference thread-local variables which are part of the
47-
/// thread-local storage block of the dynamic executable. The link-editor
85+
/// thread-local storage block of the dynamic executable. The linker
4886
/// calculates the thread pointer-relative offsets statically, without the
4987
/// need for dynamic relocations, or the extra reference to the GOT. This
5088
/// model can not be used to reference variables outside of the dynamic

0 commit comments

Comments
 (0)