TLS Supporting in Open64
From Open64 Wiki
Contents |
Overview
- Goal
Provide GCC-compatible TLS implementation.
Cooperate with GNU toolchain and glibc, mix-linking with GCC.
- About the TLS:
See "ELF Handling for Thread-Local Storage" http://people.redhat.com/drepper/tls.pdf
__thread int c;
static __thread int fs;
extern __thread int e;
void foo(void)
{
static __thread int ps;
}
- TLS model:
GCC support 4 kinds of tls model:
global-dynamic:
It's called 'General Dynamic TLS Model' in [1]. This is the most generic TLS Model. A function call '__tls_get_addr' in libc is needed to obtain the address of the TLS variable.
local-dynamic:
It's called 'Local Dynamic TLS Model' in [1]. Similar to global-dynamic, have less instructions.
initial-exec:
It's called 'Initial Exec TLS Model' in [1]. No function call is needed.
local-exec
It's called 'Local Exec TLS Model' in [1]. Similar to initial-exec with less instructions.
- TLS size
No documentation. This implementation does not support this feature.
Implementation
- TARG_INFO and ST
Add definations of TP (thread pointer, r13 on Itanium) to TARG_INFO
Add ST_IS_THREAD_LOCAL to ST_FLAG_EXT and related stuffs.
- GCC FE:
Semantic-checking is done by GCC FE.
All TLS data will be marked as DECL_THREAD_LOCAL.
- WGEN/WFE:
All DECL_VAR with DECL_THREAD_LOCAL will be set the ST_IS_THREAD_LOCAL flag.
- Data layout in BE:
All TLS data will be allocated to LBSS(uninitlized) or LDATA(initialized)
- Optimization Phases (IPA/LNO/WOPT)
Treat the ST_IS_THREAD_PRIVATE and ST_IS_THREAD_LOCAL the same.
- WN_LOWER:
ST with ST_IS_THREAD_PRIVATE is lowered during lowering OpemMP.
ALL reference (OPR_LDA and OPR_LDID) to TLS data in the OPR_PARAM of OPR_CALL will be promoted to up level if the tls-model is global-dynamic/local-dynamic. This is to avoid conflicts in output registers. It's implemented in lower_expr in wn_lower.cxx. It's done during the LOWER_TO_CG phase.
- WHIRL2OPs:
All access to TLS will be translated into corresponding OPs. Only need to process OPR_LDID, OPR_STID, OPR_LDA. They are done in one function: Exp_Ldst() in osprey/be/cg/ia64/exp_loadstore.cxx
global-dynamic:
mov loc0=gp
addl t1=@ltoff(@dtpmod(ST#)), gp
addl t2=@ltoff(@dtprel(ST#)), gp
;;
ld8 out0=[t1]
ld8 out1=[t2]
br.call rp=__tls_get_addr#
;;
mov gp=loc0
local-dynamic:
mov loc0=gp
addl t1=@ltoff(@dtpmod(ST#)), gp
addl out1=@dtprel(ST#), r0
;;
ld8 out0=[t1]
br.call rp=__tls_get_addr#
;;
mov gp=loc0
initial-exec:
addl t1=@ltoff(@tprel(ST#)), gp
;;
ld8 t2=[t1]
;;
add loc0=t1, tp
local-exec:
mov r2=tp
;;
addl loc0=@tprel(ST#), r2
- CGEMIT:
Emit the .tdata and .tbss sections
Emit the TLS related relocation instructions
Testing
TBD
X8664/IA32 issues
Only WHIRL2OPs and CGEMIT is platform-specified.
OpenMP Thread Provate and TLS issues
We both support the per-thread storage in libopenmp and TLS-enabled system.
- FE (gfec/gfecc/wgen)
The FE will mark the TLS with ST_IS_THREAD_LOCAL.
The FE can mark threadprivate in openmp either ST_IS_THREAD_PRIVATE or ST_IS_THREAD_LOCAL.
If it's former, it will be supported by libopenmp. If it's later, it will be supported by ELF TLS.
We can add an option to control which will be taken.
- Optimization Phases(IPA/LNO/WOPT)
The ST_IS_THREAD_PRIVATE and ST_IS_THREAD_LOCAL will be the same in those components.
- WN_LOWER (LOWER_MP and LOWER_TO_CG)
The ST_IS_THREAD_PRIVATE will be lowered to libopenmp callings during lowering OpenMP.
There is no more processing on ST_IS_THREAD_PRIVATE after LOWER_MP.
The ST_IS_THREAD_LOCAL will be remain until WHIRL2OPs.
- CG (WHIRL2OPs and CGEMIT)
Convert LDID/STID/LDA of ST_IS_THREAD_LOCAL to OPs depending on different TLS model.
Reference
[1] Redhat Inc, ELF Handling For Thread-Local Storage, http://people.redhat.com/drepper/tls.pdf
[2] GCC Manual, Thread-Local Storage, http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Thread_002dLocal.html#Thread_002dLocal
[3] MIPS TLS, http://www.linux-mips.org/wiki/NPTL