Go to main content

SPARC Assembly Language Reference Manual

Exit Print View

Updated: April 2020
 
 

5.4 Thread Local Storage (TLS) Code Models

The local executable code model uses the fastest code sequence, but it can only be used for code within an executable accessing a variable within that executable.

The initial executable code model allows code in the executable to access TLS variables in the shared objects to which the executable has been statically linked. IE code is somewhat slower than LE code.

The local dynamic code model allows code in a shared object to access TLS variables of its own. LD code is usually somewhat slower than IE code.

The general dynamic code model allows code from anywhere to access TLS variables anywhere. So, the executable could access a TLS variable in a dynamically linked shared object, for example. GD code is the slowest.

Note that on Oracle Solaris, the %g7 register is used by the OS to point to thread data, and the TLS variables are sometimes accessed through this register. The program must not modify %g7 because the results are unpredictable.

5.4.1 Local Executable Code Model

The following is an example of the code for the local executable TLS code model:

add:
        sethi   %tle_hix22(sum),%o3
        xor     %o3,%tle_lox10(sum),%o2
        ld      [%g7+%o2],%o1
        add     %o1,%o0,%g4
        retl
        st      %g4,[%g7+%o2]

It takes two instructions to form the address of sum. The operators act as follows:

  • %tle_hix22(sum)R_SPARC_TLS_LE_HIX22 relocation
  • %tle_lox10(sum)R_SPARC_TLS_LE_LOX10

5.4.2 Initial Executable Code Model

The following is an example of the code for the initial executable TLS code model:

add:
        rd      %pc,%o1
        sethi   %pc22(_GLOBAL_OFFSET_TABLE_-(.L900000106-.)),%g1
        add     %g1,%pc10(_GLOBAL_OFFSET_TABLE_-(.L900000106-.)),%g1
        add     %g1,%o1,%o1
        sethi   %tie_hi22(sum),%o3
        add     %o3,%tie_lo10(sum),%o2
        ldx     [%o1+%o2],%g5,%tie_ldx(sum)
        add     %g7,%g5,%g3,%tie_add(sum)
        ld      [%g3],%g4
        add     %g4,%o0,%g2
        retl
        st      %g2,[%g3]

Here it takes four instructions to form a pointer to the GOT into register %o1, followed by two instruction to form the offset of the address of sum in the GOT.

The operators act as follows:

  • %tie_hi22(sum)R_SPARC_TLS_IE_HI22 relocation
  • %tie_lo10(sum)R_SPARC_TLS_IE_LO10
  • %tie_ldx(sum)R_SPARC_TLS_IE_LDX
  • %tie_add(sum)R_SPARC_TLS_IE_ADD

5.4.3 Local Dynamic TLS Code Model

The following is an example of the local dynamic TLS code model:

add:
        save    %sp,-176,%sp
.L900000107:
        rd      %pc,%i3
        sethi   %pc22(_GLOBAL_OFFSET_TABLE_-(.L900000107-.)),%g1
        add     %g1,%pc10(_GLOBAL_OFFSET_TABLE_-(.L900000107-.)),%g1
        add     %g1,%i3,%i3
        sethi   %tldm_hi22(sum),%i2
        add     %i2,%tldm_lo10(sum),%i1
        add     %i3,%i1,%o0,%tldm_add(sum)
        call    __tls_get_addr,%tldm_call(sum)
        nop
        sethi   %tldo_hix22(sum),%l7
        xor     %l7,%tldo_lox10(sum),%l6
        add     %o0,%l6,%l4,%tldo_add(sum)
        ld      [%l4],%l5
        add     %l5,%i0,%l3
        st      %l3,[%l4]
        ret
        restore %g0,%g0,%g0

Notice that we could not have a leaf routine because of the call instruction.

There are four instructions to form a pointer to the GOT into register %i3. Then it takes two more instructions to form the offset of the address of sum in the GOT, and another instruction to add those to the address of the GOT to form the address of the GOT slot for sum. This address is passed to function __tls_get_addr that returns the address for local module's TLS data in register %o0. Three more instructions form the offset of sum in the module data and to add that to the module data address. Note that the module data address can be reused to access multiple TLS variables.

The operators act as follows:

  • %tldm_hi22(sum)R_SPARC_TLS_LDM_HI22 relocation
  • %tldm_lo10(sum)R_SPARC_TLS_LDM_LO10
  • %tldm_add(sum)R_SPARC_TLS_LDM_ADD
  • %tldm_call(sum)R_SPARC_TLS_LDM_CALL
  • %tldo_hix22(sum)R_SPARC_TLS_LDO_HIX22 relocation
  • %tldo_lox10(sum)R_SPARC_TLS_LDO_LOX10
  • %tldo_add(sum)R_SPARC_TLS_LDO_ADD

5.4.4 General Dynamic TLS Code Model

The following is an example of the general dynamic TLS code model:

add:
        save    %sp,-176,%sp
.L900000107:
        rd      %pc,%i3
        sethi   %pc22(_GLOBAL_OFFSET_TABLE_-(.L900000107-.)),%g1
        add     %g1,%pc10(_GLOBAL_OFFSET_TABLE_-(.L900000107-.)),%g1
        add     %g1,%i3,%i3
        sethi   %tgd_hi22(sum),%i2
        add     %i2,%tgd_lo10(sum),%i1
        add     %i3,%i1,%o0,%tgd_add(sum)
        call    __tls_get_addr,%tgd_call(sum)
        nop
        ld      [%o0],%l7
        add     %l7,%i0,%l6
        st      %l6,[%o0]
        ret
        restore %g0,%g0,%g0

Notice that we could not have a leaf routine because of the call instruction.

There are four instructions to form a pointer to the GOT into register %i3, followed by two more instruction to form the offset of the address of sum in the GOT, and another instruction to add those to the address of the GOT to form the address of the GOT slot for sum. This address is passed to function __tls_get_addr that returns the address for sum in register %o0.

The operators act as follows:

  • %tgd_hi22(sum)R_SPARC_TLS_GD_HI22 relocation
  • %tgd_lo10(sum)R_SPARC_TLS_GD_LO10
  • %tgd_add(sum)R_SPARC_TLS_GD_ADD
  • %tgd_call(sum)R_SPARC_TLS_GD_CALL