@@ -21,6 +21,7 @@
#include <resolv/resolv-internal.h>
#include <rpc/rpc.h>
#include <string.h>
+#include <tls-internal.h>
/* Thread shutdown function. Note that this function must be called
for threads during shutdown for correctness reasons. Unlike
@@ -32,6 +33,7 @@ __libc_thread_freeres (void)
call_function_static_weak (__rpc_thread_destroy);
call_function_static_weak (__res_thread_freeres);
call_function_static_weak (__strerror_thread_freeres);
+ __glibc_tls_internal_free ();
/* This should come last because it shuts down malloc for this
thread and the other shutdown functions might well call free. */
@@ -237,6 +237,8 @@ get_cached_stack (size_t *sizep, void **memp)
/* No pending event. */
result->nextevent = NULL;
+ result->tls_state = (struct tls_internal_t) { 0 };
+
/* Clear the DTV. */
dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
@@ -34,6 +34,7 @@
#include <unwind.h>
#include <bits/types/res_state.h>
#include <kernel-features.h>
+#include <tls-internal-struct.h>
#ifndef TCB_ALIGNMENT
# define TCB_ALIGNMENT sizeof (double)
@@ -398,6 +399,9 @@ struct pthread
/* Indicates whether is a C11 thread created by thrd_creat. */
bool c11;
+ /* Used on strsignal. */
+ struct tls_internal_t tls_state;
+
/* This member must be last. */
char end_padding[];
@@ -20,106 +20,37 @@
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
-#include <libc-lock.h>
-
-static __libc_key_t key;
-
-/* If nonzero the key allocation failed and we should better use a
- static buffer than fail. */
-#define BUFFERSIZ 100
-static char local_buf[BUFFERSIZ];
-static char *static_buf;
-
-/* Destructor for the thread-specific data. */
-static void init (void);
-static void free_key_mem (void *mem);
-static char *getbuffer (void);
-
+#include <tls-internal.h>
+#include <array_length.h>
/* Return a string describing the meaning of the signal number SIGNUM. */
char *
strsignal (int signum)
{
- __libc_once_define (static, once);
- const char *desc;
-
- /* If we have not yet initialized the buffer do it now. */
- __libc_once (once, init);
-
- if (
-#ifdef SIGRTMIN
- (signum >= SIGRTMIN && signum <= SIGRTMAX) ||
-#endif
- signum < 0 || signum >= NSIG
- || (desc = __sys_siglist_internal[signum]) == NULL)
- {
- char *buffer = getbuffer ();
- int len;
-#ifdef SIGRTMIN
- if (signum >= SIGRTMIN && signum <= SIGRTMAX)
- len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"),
- signum - SIGRTMIN);
- else
-#endif
- len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"),
- signum);
- if (len >= BUFFERSIZ)
- buffer = NULL;
- else
- buffer[len] = '\0';
-
- return buffer;
- }
-
- return (char *) _(desc);
-}
-
-
-/* Initialize buffer. */
-static void
-init (void)
-{
- if (__libc_key_create (&key, free_key_mem))
- /* Creating the key failed. This means something really went
- wrong. In any case use a static buffer which is better than
- nothing. */
- static_buf = local_buf;
-}
-
+ const char *desc = NULL;
-/* Free the thread specific data, this is done if a thread terminates. */
-static void
-free_key_mem (void *mem)
-{
- free (mem);
- __libc_setspecific (key, NULL);
-}
+ if (signum >= 0 && signum <= NSIG
+ && signum < array_length (__sys_siglist_internal))
+ desc = __sys_siglist_internal[signum];
+ if (desc != NULL)
+ return (char *) _(desc);
-/* Return the buffer to be used. */
-static char *
-getbuffer (void)
-{
- char *result;
+ struct tls_internal_t *tls_internal = __glibc_tls_internal ();
+ free (tls_internal->strsignal_buf);
- if (static_buf != NULL)
- result = static_buf;
+ int r;
+#ifdef SIGRTMIN
+ if (signum >= SIGRTMIN && signum <= SIGRTMAX)
+ r = __asprintf (&tls_internal->strsignal_buf, _("Real-time signal %d"),
+ signum - SIGRTMIN);
else
- {
- /* We don't use the static buffer and so we have a key. Use it
- to get the thread-specific buffer. */
- result = __libc_getspecific (key);
- if (result == NULL)
- {
- /* No buffer allocated so far. */
- result = malloc (BUFFERSIZ);
- if (result == NULL)
- /* No more memory available. We use the static buffer. */
- result = local_buf;
- else
- __libc_setspecific (key, result);
- }
- }
+#endif
+ r = __asprintf (&tls_internal->strsignal_buf, _("Unknown signal %d"),
+ signum);
+
+ if (r == -1)
+ tls_internal->strsignal_buf = NULL;
- return result;
+ return tls_internal->strsignal_buf;
}
@@ -16,6 +16,7 @@
# <https://www.gnu.org/licenses/>.
ifeq ($(subdir),string)
+sysdep_routines += tls-internal
CFLAGS-wordcopy.c += -Wno-uninitialized
endif
new file mode 100644
@@ -0,0 +1,27 @@
+/* Per-thread state. Generic version.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TLS_INTERNAL_STRUCT_H
+#define _TLS_INTERNAL_STRUCT_H 1
+
+struct tls_internal_t
+{
+ char *strsignal_buf;
+};
+
+#endif
new file mode 100644
@@ -0,0 +1,21 @@
+/* Per-thread state. Generic version.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <tls-internal.h>
+
+__thread struct tls_internal_t __tls_internal;
new file mode 100644
@@ -0,0 +1,39 @@
+/* Per-thread state. Generic version.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TLS_INTERNAL_H
+#define _TLS_INTERNAL_H 1
+
+#include <stdlib.h>
+#include <tls-internal-struct.h>
+
+extern __thread struct tls_internal_t __tls_internal attribute_hidden;
+
+static inline struct tls_internal_t *
+__glibc_tls_internal (void)
+{
+ return &__tls_internal;
+}
+
+static inline void
+__glibc_tls_internal_free (void)
+{
+ free (__tls_internal.strsignal_buf);
+}
+
+#endif
new file mode 100644
@@ -0,0 +1 @@
+/* Empty. */
new file mode 100644
@@ -0,0 +1,37 @@
+/* Per-thread state. Linux version.
+ Copyright (C) 2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TLS_INTERNAL_H
+#define _TLS_INTERNAL_H 1
+
+#include <stdlib.h>
+#include <nptl/pthreadP.h>
+
+static inline struct tls_internal_t *
+__glibc_tls_internal (void)
+{
+ return &THREAD_SELF->tls_state;
+}
+
+static inline void
+__glibc_tls_internal_free (void)
+{
+ free (THREAD_SELF->tls_state.strsignal_buf);
+}
+
+#endif