v-zhangxiaomeng5 opened a new pull request, #20803:
URL: https://github.com/apache/nuttx/pull/20803

   A GCC toolchain configured with --disable-tls, the common case for bare 
metal targets, compiles a thread_local or __thread variable into a call to 
__emutls_get_address().  The libgcc of such a toolchain is built with the 
single thread model, so its implementation keeps one copy of each variable for 
the whole program and every thread reads and writes that same copy.
   
   Add an implementation that gives one copy per thread.  A pthread key holds 
the copy of a variable and frees it when the thread exits.  A pthread key, 
however, belongs to one task group, while the __emutls_object that the compiler 
emits for a variable is a single global object shared by every task group of a 
flat build, so the key is reached through two levels:
   
   * obj->loc.offset holds a task local storage index, allocated once for the 
variable.
   * The task local storage holds the pthread key of the task group, created on 
first use.
   * The pthread key holds the copy of the variable of the calling thread.
   
   The build redirects the calls with the --wrap option of the linker instead 
of defining the same names, because the symbols of libgcc have external linkage 
and are part of the link of some configurations whatever the order of the 
archives is.  With
   CONFIG_DEBUG_LINK_WHOLE_ARCHIVE the emutls.o of libgcc is pulled in 
unconditionally, and a second definition of __emutls_get_address() would then 
collide with it.
   
   The file is built only for a GNU toolchain that does not use the native 
thread local storage of NuttX, and only where both the task local storage and 
the pthread keys are available.
   
   Assisted-by: Claude Code:claude-opus-5-5
   
   *Note: Please adhere to [Contributing 
Guidelines](https://github.com/apache/nuttx/blob/master/CONTRIBUTING.md).*
   
   ## Summary
   
   A GCC toolchain configured with --disable-tls compiles a thread_local or 
__thread variable into a call to __emutls_get_address(). The libgcc of such a 
toolchain is built with the single thread model, so it keeps one copy of each 
variable for the whole program and every thread reads and writes that same 
copy, which breaks the meaning of the keyword.
   
   This adds libs/libc/tls/tls_emutls.c, which gives one copy per thread. A 
pthread key holds the copy and frees it when the thread exits. Because a 
pthread key belongs to one task group while the __emutls_object the compiler 
emits is a single global object shared by every task group of a flat build, the 
key is reached through two levels: obj->loc.offset holds a task local storage 
index allocated once for the variable, and the task local storage holds the 
pthread key of the task group, created on first use. 
   
   __emutls_register_common() is provided as well, with the same largest-wins 
merge as libgcc.
   
   ## Impact
   
   A thread_local variable now has one copy per thread on a toolchain without 
native TLS.
   
   Known limitation: each variable costs one task local storage slot and one 
pthread key per task group, so the count is bounded by those two symbols, and a 
failed task_tls_alloc() is fatal because the caller the compiler emits cannot 
report an error.
   
   ## Testing
   
   Built on Ubuntu 22.04.5 (x86_64) with Arm GNU Toolchain 13.2.Rel1 
(--disable-tls, the case this targets) and arm-none-eabi-gcc 10.3.1 
(--enable-tls), NuttX master and nuttx-apps master.
   
   lm3s6965-ek: libc.a contains tls_emutls.o exporting T 
__wrap___emutls_get_address and T __wrap___emutls_register_common, and both 
--wrap options appear in LDFLAGS and in build.ninja.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to