On Wed, Mar 24, 2021, at 19:27, Byron Ellacott wrote: > Here's what I found in libc that would need task (thread) specific data: > > - libs/libc/misc/lib_umask.c has g_mask > - libs/libc/libgen/lib_dirname.c and libs/libc/libgen/lib_basename each > have a g_retchar > - libs/libc/syslog/lib_setlogmask.c has g_syslog_mask (and a comment > describing this issue) > - libs/libc/pwd/* uses either g_passwd and g_passwd_buffer or g_pwd and > g_buf > - libs/libc/grp/* uses a similar pair for group data > - libs/libc/unistd/lib_getopt.c we know of, it has four words of global > data > - libs/libc/time/lib_localtime.c uses g_tm and may need per-task timezone > settings > - libs/libc/netdb/lib_netdb.c specifies h_errno as a global > - libs/libc/netdb/lib_gethostbyname2.c and lib_gethostbyaddr.c use > g_hostent and g_hostbuffer > - libs/libc/stdlib/lib_srand.c uses a variety of globals depending on > build options > - libs/libc/string/lib_strtok.c uses g_saveptr
Thanks for this list, I will update the issue and make it into a task list. > > Statically allocating a TLS key for each module would consume around 11 > keys in each task. Dynamically allocated TLS keys cannot ever be released, > because these are globals handed over to user code with no indication when > they're no longer needed. It may be better to have an additional static > element in tls_info_s pointing to a heap-allocated structure containing the > libc globals. Functionally this is the same as a statically reserved TLS > key, but it's clearer what it's for. I think that is more or less the idea discussed in the PR. It will be done later on. Best, Matias > -- > Byron > > On Thu, Mar 25, 2021 at 12:51 AM Gregory Nutt <spudan...@gmail.com > <mailto:spudaneco%40gmail.com>> wrote: > > > On 3/24/2021 8:38 AM, Matias N. wrote: > > > So, if I follow correctly, we could maybe have one TLS pointer pointing > > to a struct of pointers, one per each group of globals (one of this groups, > > would be the set of variables used by getopt()), like: > > > > > > struct task_globals_s > > > { > > > struct getopt_globals_s *getopt_globals; > > > /* ...others */ > > > }; > > > > > > Then getopt globals would only be allocated once for each task, and only > > when getopt() is called. > > > > > > Something like that? > > > > Yes, that is a possibility. But that is already implemented just as you > > describe as POSIX thread-specific data. > > > > The TLS data structure is defined in include/nuttx/tls.h as following. > > it is just an array of pointer size things and the errno variable. > > > > struct tls_info_s > > { > > #if CONFIG_TLS_NELEM > 0 > > uintptr_t tl_elem[CONFIG_TLS_NELEM]; /* TLS elements */ > > #endif > > int tl_errno; /* Per-thread error number */ > > }; > > > > This structure lies at the "bottom" of stack of every thread in user space. > > > > The standard pthread_getspecific() is then implemented as: > > > > FAR void *pthread_getspecific(pthread_key_t key) > > { > > return (FAR void *)tls_get_value((int)key); > > } > > > > Where > > > > uintptr_t tls_get_value(int tlsindex) > > { > > FAR struct tls_info_s *info; > > uintptr_t ret = 0; > > > > DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); > > if (tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM) > > { > > /* Get the TLS info structure from the current threads stack */ > > > > info = up_tls_info(); > > DEBUGASSERT(info != NULL); > > > > /* Get the element value from the TLS info. */ > > > > ret = info->tl_elem[tlsindex]; > > } > > > > return ret; > > } > > > > The POSIX interface supports a pthread_key_create() to manage the indexing. > > > > > > > > >