Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sun, 23 Jan 2022 20:01:28 -0800
From: Keith Packard <keithp@...thp.com>
To: Sebastian Huber <sebastian.huber@...edded-brains.de>,
 libc-coord@...ts.openwall.com
Subject: Re: Constructors/destructors for thread-local objects?

Sebastian Huber <sebastian.huber@...edded-brains.de> writes:

> One approach to disentangle the dependencies introduced by struct _reent 
> is to get rid of this structure and replace the individual members of 
> the structure with thread-local objects. For example, instead of
>
> struct _reent {
>    int _errno;
>    __FILE *_stdin;
>    __FILE *_stdout;
>    __FILE *_stderr;
> };
>
> use
>
> _Thread_local int _errno;
> _Thread_local __FILE *_stdin;
> _Thread_local __FILE *_stdout;
> _Thread_local __FILE *_stderr;

This has already been done in picolibc; that was the principle reason
picolibc became a fork of newlib rather than simply a sequence of minor
fixes -- there's no way to preserve newlib ABI with this change. So, if
you're interested in this approach, I already have an existence proof
that it can work.

> Now, there is a problem with the clean up of resources when a thread is 
> deleted. There is currently no standard way for constructors and 
> destructors of thread-local objects in C.

Given that embedded systems (those likely to be running picolibc) don't
really have any notion of 'exit' anyways, I've wondered at times if it
would be reasonable to re-purpose the existing init/fini handlers to be
thread start/thread exit instead of 'process' start and termination. I
eventually decided that this wasn't the case as we still need global
system initialization to be invoked through the .init handlers. So, yes,
I agree that we could use such a mechanism for applications which have
TLS variables that need cleanup on thread exit.

picolibc defines a set of APIs to help operating systems enable TLS
support; adding a couple more to run the TLS initializers/finalizers
would be a nice extension to this concept.

> Do we need .tls_preinit_array?

I'd prefer to skip it; this requires another chunk of code in the thread
initialization sequence which can't be optimized away as the length of
the arrays aren't known until link time.

> It is unlikely that another C library will use this, but anyway, I would 
> like to use some names which could be used elsewhere as well.

Picolibc (and other embedded C libaries) could use the same mechanism.

In picolibc, there's a couple of TLS variables that would need .fini
handlers in the legacy stdio implementation of printf, and
gcvt/ecvt/fcvt. These are only used in a non-standard build of picolibc,
so for now they leak memory on multi-threaded systems on thread exit.

Do you have other places in newlib that need TLS data cleanup done on
thread exit? Because at this point, I would only be providing this
mechanism for application support, in it's normal configuration,
picolibc wouldn't need it.

As for systems with dlopen, I'm afraid I don't have a lot of practical
suggestions; embedded systems that I've built don't include dynamic
libraries of any kind. I know that TLS variables for shared libraries
are allocated on the fly; presumably then there is a way to also invoke
the initializers and finalizers for those chunks of memory during
allocation/deallocation?

-- 
-keith

Download attachment "signature.asc" of type "application/pgp-signature" (833 bytes)

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.