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.
> >
> >
> >
> >
> 

Reply via email to