Using thread local storage
Thread-local variables can be declared and defined with the TL and UL storage-mapping classes.
Thread-local variables can be declared and defined with the TL and UL storage-mapping classes. The thread-local variables are referenced using code sequences defined by the AIX implementation.
A thread-local variable has a region handle and a region offset. In general, the __tls_get_addr() function is called to compute the address of a thread-local variable for the calling thread, given the variables region handle and offset.
Other access methods can be used in more restricted circumstances. The local-exec access method is used by the main program to reference variables also defined in the main program. The initial-exec access method is used to reference thread-local variables defined in the main program or any shared object loaded along with the main program. The local-dynamic access method is used by a module to reference thread-local variables defined in the same module.
Access to thread-local storage makes use of routines in the pthread library that have nonstandard calling conventions. These routines are __tls_get_addr() and __tls_get_mod(). The routine used in 32-bit programs is __get_tpointer(). In 64-bit programs, the current thread pointer is always contained in gpr13.
.comm bar[UL]
.csect foo[TL]
.long 1
Access method | 32-bit code | 64-bit code(if different) | Comment |
---|---|---|---|
General-dynamic access method | .tc foo[TC],foo[TL] | Variable offset | |
.tc .foo[TC],foo[TL]@m | Region handle | ||
lwz 4,foo[TC](2) | ld 4,foo[TC](2) | ||
lwz 3,.foo[TC](2) | ld 3,.foo[TC](2) | ||
bla .__tls_get_addr | Modifies r0,r3,r4,r5,r11,lr,cr0 | ||
#r3 = &foo | |||
Local-dynamic access method | .tc foo[TC],foo[TL]@ld | Variable offset, ld relocation specifier | |
.tc mh[TC],mh[TC]@ml | Module handle for the caller | ||
lwz 3,mh[TC](2) | ld 3,mh[TC](2) | ||
bla .__tls_get_mod | Modifies r0,r3,r4,r5,r11,lr,cr0 | ||
#r3 = &TLS for module | |||
lwz 4,foo[TC](2) | ld 4,foo[TC](2) | ||
add 5,3,4 | Compute &foo | ||
.rename mh[TC], "_$TLSML" | Symbol for the module handle must have the name "_$TLSML" | ||
Initial-exec access method | .tc foo[TC],foo[TL]@ie | Variable offset, ie relocation specifier | |
bla __get_tpointer() | # r13 contains tpointer | __get_tpointer modifies r3 | |
lwz 4,foo[TC](2) | ld 4,foo[TC](2) | ||
add 5,3,4 | add 5,4,13 | Compute &foo | |
Local-exec access method | .tc foo[TC],foo[TL]@le | Variable offset, le relocation specifier | |
bla __get_tpointer() | # r13 contains tpointer | __get_tpointer modifies r3 | |
lwz 4,foo[TC](2) | ld 4,foo[TC](2) | Compute &foo | |
add 5,3,4 | add 5,4,13 |
Access method | 32-bit code | Comment |
---|---|---|
Local-dynamic access method | .tc mh[TC],mh[TC]@ml | Module handle for the caller |
.rename mh[TC], "_$TLSML" | Symbol for the module handle must have the name "_$TLSML" | |
lwz 3,mh[TC](2) | ||
bla .__tls_get_mod | ||
la 4,foo[TL]@ld(3) | r4 = &foo | |
Local-exec access method | bla .__get_tpointer | Modifies r3 |
la 4,foo[TL]@ld(3) | r4 = &foo | |
# OR | ||
lwz 5,foo[TL]@le(13) | r5 = foo |
Access method | 64-bit code | Comment |
---|---|---|
Local-dynamic access method | .tc mh[TC],mh[TC]@ml | Module handle for the caller |
.rename mh[TC], "_$TLSML" | Symbol for the module handle must have the name "_$TLSML" | |
ld 3,mh[TC](2) | ||
bla .__tls_get_mod | ||
la 4,foo[TL]@ld(3) | r4 = &foo | |
Local-exec access method | la 4,foo[TL]@le(13) | r4 = &foo |
# OR | ||
lwz 5,foo[TL]@le(13) | r5 = foo |