[libc] Reset thread-specific key value before invoking destructor (#226134)

POSIX specifies that before calling a thread-specific key destructor,
the value of the key must be set to NULL (so pthread_getspecific returns
NULL from inside the destructor), and that the destructor pass must
repeat up to PTHREAD_DESTRUCTOR_ITERATIONS times if destructors
re-associate non-NULL values with keys.

This patch sets the key payload to nullptr prior to calling the
destructor, and loops over the key array up to the destructor iteration
limit as long as non-NULL values remain.

Along with that:
- introduce common-threads-macros.h to share the destructor iteration
count (4) between C (TSS_DTOR_ITERATIONS) and POSIX
(PTHREAD_DESTRUCTOR_ITERATIONS), and use it internally
- expose TSS_DTOR_ITERATIONS in threads.h
- expose and implement _SC_THREAD_DESTRUCTOR_ITERATIONS in sysconf

Note that I am not fixing the issue where a deleted key's destructor can
still run on thread exit if it was already cached in thread-local
storage. Fixing that properly will require tracking key generations or
validity across threads, so I'm leaving that for separate work
(#226122).

Fixes #194029.

Assisted-by: Gemini
GitOrigin-RevId: 667cfbec38942e08bd67fa51cc05e63686dd01b9
17 files changed