mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-28 00:21:52 +03:00
Revert "Patch 2/4 of the effort to make TLS access async-signal-safe."
This reverts commit1f33d36a8a
. Conflicts: elf/dl-misc.c Also reverts the follow commits that were bug fixes to new code introduced in the above commit:063b2acbce
b627fdd585
e81c64bba1
This commit is contained in:
19
ChangeLog
19
ChangeLog
@ -961,12 +961,6 @@
|
|||||||
|
|
||||||
* sysdeps/powerpc/fpu/libm-test-ulps: Update.
|
* sysdeps/powerpc/fpu/libm-test-ulps: Update.
|
||||||
|
|
||||||
2013-12-19 Paul Pluzhnikov <ppluzhnikov@google.com>
|
|
||||||
|
|
||||||
* elf/dl-misc.c (ptr_to_signal_safe_allocator_header): New function.
|
|
||||||
(__signal_safe_memalign, __signal_safe_free): Use it.
|
|
||||||
(__signal_safe_realloc): Likewise.
|
|
||||||
|
|
||||||
2013-12-19 Joseph Myers <joseph@codesourcery.com>
|
2013-12-19 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* manual/texinfo.tex: Update to version 2013-11-26.10 with
|
* manual/texinfo.tex: Update to version 2013-11-26.10 with
|
||||||
@ -1050,19 +1044,6 @@
|
|||||||
* manual/install.texi: Suppress menu for plain text output.
|
* manual/install.texi: Suppress menu for plain text output.
|
||||||
* INSTALL: Regenerated.
|
* INSTALL: Regenerated.
|
||||||
|
|
||||||
2013-12-18 Andrew Hunter <ahh@google.com>
|
|
||||||
|
|
||||||
* sysdeps/generic/ldsodefs.h (__signal_safe_memalign): New prototype.
|
|
||||||
(__signal_safe_malloc, __signal_safe_free): Likewise.
|
|
||||||
(__signal_safe_realloc, __signal_safe_calloc): Likewise.
|
|
||||||
* elf/dl-misc.c (__signal_safe_allocator_header): New struct.
|
|
||||||
(__signal_safe_memalign, __signal_safe_malloc): New function.
|
|
||||||
(__signal_safe_free, __signal_safe_realloc): Likewise.
|
|
||||||
(__signal_safe_calloc): Likewise.
|
|
||||||
* elf/dl-tls.c (allocate_dtv, _dl_clear_dtv): Call signal-safe
|
|
||||||
functions.
|
|
||||||
(_dl_deallocate_tls, _dl_update_slotinfo): Likewise.
|
|
||||||
|
|
||||||
2013-12-18 Andrew Hunter <ahh@google.com>
|
2013-12-18 Andrew Hunter <ahh@google.com>
|
||||||
|
|
||||||
* elf/Versions (ld): Add _dl_clear_dtv.
|
* elf/Versions (ld): Add _dl_clear_dtv.
|
||||||
|
142
elf/dl-misc.c
142
elf/dl-misc.c
@ -19,7 +19,6 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <ldsodefs.h>
|
#include <ldsodefs.h>
|
||||||
#include <libc-symbols.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -365,144 +364,3 @@ _dl_higher_prime_number (unsigned long int n)
|
|||||||
|
|
||||||
return *low;
|
return *low;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To support accessing TLS variables from signal handlers, we need an
|
|
||||||
async signal safe memory allocator. These routines are never
|
|
||||||
themselves invoked reentrantly (all calls to them are surrounded by
|
|
||||||
signal masks) but may be invoked concurrently from many threads.
|
|
||||||
The current implementation is not particularly performant nor space
|
|
||||||
efficient, but it will be used rarely (and only in binaries that use
|
|
||||||
dlopen.) The API matches that of malloc() and friends. */
|
|
||||||
|
|
||||||
struct __signal_safe_allocator_header
|
|
||||||
{
|
|
||||||
size_t size;
|
|
||||||
void *start;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline struct __signal_safe_allocator_header *
|
|
||||||
ptr_to_signal_safe_allocator_header (void *ptr)
|
|
||||||
{
|
|
||||||
return (struct __signal_safe_allocator_header *)
|
|
||||||
((char *) (ptr) - sizeof (struct __signal_safe_allocator_header));
|
|
||||||
}
|
|
||||||
|
|
||||||
void *weak_function
|
|
||||||
__signal_safe_memalign (size_t boundary, size_t size)
|
|
||||||
{
|
|
||||||
struct __signal_safe_allocator_header *header;
|
|
||||||
|
|
||||||
if (boundary < sizeof (*header))
|
|
||||||
boundary = sizeof (*header);
|
|
||||||
|
|
||||||
/* Boundary must be a power of two. */
|
|
||||||
if (!powerof2 (boundary))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
size_t pg = GLRO (dl_pagesize);
|
|
||||||
size_t padded_size;
|
|
||||||
if (boundary <= pg)
|
|
||||||
{
|
|
||||||
/* We'll get a pointer certainly aligned to boundary, so just
|
|
||||||
add one more boundary-sized chunk to hold the header. */
|
|
||||||
padded_size = roundup (size, boundary) + boundary;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If we want K pages aligned to a J-page boundary, K+J+1 pages
|
|
||||||
contains at least one such region that isn't directly at the start
|
|
||||||
(so we can place the header.) This is wasteful, but you're the one
|
|
||||||
who wanted 64K-aligned TLS. */
|
|
||||||
padded_size = roundup (size, pg) + boundary + pg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t actual_size = roundup (padded_size, pg);
|
|
||||||
void *actual = mmap (NULL, actual_size, PROT_READ | PROT_WRITE,
|
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
||||||
if (actual == MAP_FAILED)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (boundary <= pg)
|
|
||||||
{
|
|
||||||
header = actual + boundary - sizeof (*header);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
intptr_t actual_pg = ((intptr_t) actual) / pg;
|
|
||||||
intptr_t boundary_pg = boundary / pg;
|
|
||||||
intptr_t start_pg = actual_pg + boundary_pg;
|
|
||||||
start_pg -= start_pg % boundary_pg;
|
|
||||||
if (start_pg > (actual_pg + 1))
|
|
||||||
{
|
|
||||||
int ret = munmap (actual, (start_pg - actual_pg - 1) * pg);
|
|
||||||
assert (ret == 0);
|
|
||||||
actual = (void *) ((start_pg - 1) * pg);
|
|
||||||
}
|
|
||||||
char *start = (void *) (start_pg * pg);
|
|
||||||
header = ptr_to_signal_safe_allocator_header (start);
|
|
||||||
}
|
|
||||||
|
|
||||||
header->size = actual_size;
|
|
||||||
header->start = actual;
|
|
||||||
void *ptr = header;
|
|
||||||
ptr += sizeof (*header);
|
|
||||||
if (((intptr_t) ptr) % boundary != 0)
|
|
||||||
_dl_fatal_printf ("__signal_safe_memalign produced incorrect alignment\n");
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * weak_function
|
|
||||||
__signal_safe_malloc (size_t size)
|
|
||||||
{
|
|
||||||
return __signal_safe_memalign (1, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void weak_function
|
|
||||||
__signal_safe_free (void *ptr)
|
|
||||||
{
|
|
||||||
if (ptr == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct __signal_safe_allocator_header *header
|
|
||||||
= ptr_to_signal_safe_allocator_header (ptr);
|
|
||||||
int ret = munmap (header->start, header->size);
|
|
||||||
|
|
||||||
assert (ret == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void * weak_function
|
|
||||||
__signal_safe_realloc (void *ptr, size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
__signal_safe_free (ptr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (ptr == NULL)
|
|
||||||
return __signal_safe_malloc (size);
|
|
||||||
|
|
||||||
struct __signal_safe_allocator_header *header
|
|
||||||
= ptr_to_signal_safe_allocator_header (ptr);
|
|
||||||
size_t old_size = header->size;
|
|
||||||
if (old_size - sizeof (*header) >= size)
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
void *new_ptr = __signal_safe_malloc (size);
|
|
||||||
if (new_ptr == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memcpy (new_ptr, ptr, old_size);
|
|
||||||
__signal_safe_free (ptr);
|
|
||||||
|
|
||||||
return new_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * weak_function
|
|
||||||
__signal_safe_calloc (size_t nmemb, size_t size)
|
|
||||||
{
|
|
||||||
void *ptr = __signal_safe_malloc (nmemb * size);
|
|
||||||
if (ptr == NULL)
|
|
||||||
return NULL;
|
|
||||||
return memset (ptr, 0, nmemb * size);
|
|
||||||
}
|
|
||||||
|
34
elf/dl-tls.c
34
elf/dl-tls.c
@ -293,7 +293,7 @@ allocate_dtv (void *result)
|
|||||||
initial set of modules. This should avoid in most cases expansions
|
initial set of modules. This should avoid in most cases expansions
|
||||||
of the dtv. */
|
of the dtv. */
|
||||||
dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
|
dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
|
||||||
dtv = __signal_safe_calloc (dtv_length + 2, sizeof (dtv_t));
|
dtv = calloc (dtv_length + 2, sizeof (dtv_t));
|
||||||
if (dtv != NULL)
|
if (dtv != NULL)
|
||||||
{
|
{
|
||||||
/* This is the initial length of the dtv. */
|
/* This is the initial length of the dtv. */
|
||||||
@ -470,7 +470,7 @@ _dl_clear_dtv (dtv_t *dtv)
|
|||||||
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
|
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
|
||||||
if (! dtv[1 + cnt].pointer.is_static
|
if (! dtv[1 + cnt].pointer.is_static
|
||||||
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
|
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
|
||||||
__signal_safe_free (dtv[1 + cnt].pointer.val);
|
free (dtv[1 + cnt].pointer.val);
|
||||||
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
|
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,11 +491,11 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
|
|||||||
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
|
for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
|
||||||
if (! dtv[1 + cnt].pointer.is_static
|
if (! dtv[1 + cnt].pointer.is_static
|
||||||
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
|
&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
|
||||||
__signal_safe_free (dtv[1 + cnt].pointer.val);
|
free (dtv[1 + cnt].pointer.val);
|
||||||
|
|
||||||
/* The array starts with dtv[-1]. */
|
/* The array starts with dtv[-1]. */
|
||||||
if (dtv != GL(dl_initial_dtv))
|
if (dtv != GL(dl_initial_dtv))
|
||||||
__signal_safe_free (dtv - 1);
|
free (dtv - 1);
|
||||||
|
|
||||||
if (dealloc_tcb)
|
if (dealloc_tcb)
|
||||||
{
|
{
|
||||||
@ -537,7 +537,8 @@ static void *
|
|||||||
allocate_and_init (struct link_map *map)
|
allocate_and_init (struct link_map *map)
|
||||||
{
|
{
|
||||||
void *newp;
|
void *newp;
|
||||||
newp = __signal_safe_memalign (map->l_tls_align, map->l_tls_blocksize);
|
|
||||||
|
newp = __libc_memalign (map->l_tls_align, map->l_tls_blocksize);
|
||||||
if (newp == NULL)
|
if (newp == NULL)
|
||||||
oom ();
|
oom ();
|
||||||
|
|
||||||
@ -607,27 +608,25 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
|||||||
if (gen <= dtv[0].counter)
|
if (gen <= dtv[0].counter)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
size_t modid = total + cnt;
|
|
||||||
|
|
||||||
/* If there is no map this means the entry is empty. */
|
/* If there is no map this means the entry is empty. */
|
||||||
struct link_map *map = listp->slotinfo[cnt].map;
|
struct link_map *map = listp->slotinfo[cnt].map;
|
||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
{
|
{
|
||||||
/* If this modid was used at some point the memory
|
/* If this modid was used at some point the memory
|
||||||
might still be allocated. */
|
might still be allocated. */
|
||||||
if (dtv[-1].counter >= modid
|
if (! dtv[total + cnt].pointer.is_static
|
||||||
&& !dtv[modid].pointer.is_static
|
&& dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
|
||||||
&& dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
|
|
||||||
{
|
{
|
||||||
__signal_safe_free (dtv[modid].pointer.val);
|
free (dtv[total + cnt].pointer.val);
|
||||||
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
|
dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (modid == map->l_tls_modid);
|
|
||||||
/* Check whether the current dtv array is large enough. */
|
/* Check whether the current dtv array is large enough. */
|
||||||
|
size_t modid = map->l_tls_modid;
|
||||||
|
assert (total + cnt == modid);
|
||||||
if (dtv[-1].counter < modid)
|
if (dtv[-1].counter < modid)
|
||||||
{
|
{
|
||||||
/* Reallocate the dtv. */
|
/* Reallocate the dtv. */
|
||||||
@ -641,18 +640,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
|||||||
{
|
{
|
||||||
/* This is the initial dtv that was allocated
|
/* This is the initial dtv that was allocated
|
||||||
during rtld startup using the dl-minimal.c
|
during rtld startup using the dl-minimal.c
|
||||||
malloc instead of the real allocator. We can't
|
malloc instead of the real malloc. We can't
|
||||||
free it, we have to abandon the old storage. */
|
free it, we have to abandon the old storage. */
|
||||||
|
|
||||||
newp = __signal_safe_malloc (
|
newp = malloc ((2 + newsize) * sizeof (dtv_t));
|
||||||
(2 + newsize) * sizeof (dtv_t));
|
|
||||||
if (newp == NULL)
|
if (newp == NULL)
|
||||||
oom ();
|
oom ();
|
||||||
memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
|
memcpy (newp, &dtv[-1], (2 + oldsize) * sizeof (dtv_t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newp = __signal_safe_realloc (&dtv[-1],
|
newp = realloc (&dtv[-1],
|
||||||
(2 + newsize) * sizeof (dtv_t));
|
(2 + newsize) * sizeof (dtv_t));
|
||||||
if (newp == NULL)
|
if (newp == NULL)
|
||||||
oom ();
|
oom ();
|
||||||
@ -682,7 +680,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
|||||||
deallocate even if it is this dtv entry we are
|
deallocate even if it is this dtv entry we are
|
||||||
supposed to load. The reason is that we call
|
supposed to load. The reason is that we call
|
||||||
memalign and not malloc. */
|
memalign and not malloc. */
|
||||||
__signal_safe_free (dtv[modid].pointer.val);
|
free (dtv[modid].pointer.val);
|
||||||
|
|
||||||
/* This module is loaded dynamically- We defer memory
|
/* This module is loaded dynamically- We defer memory
|
||||||
allocation. */
|
allocation. */
|
||||||
|
@ -994,12 +994,6 @@ rtld_hidden_proto (_dl_allocate_tls_init)
|
|||||||
extern void _dl_clear_dtv (dtv_t *dtv) internal_function;
|
extern void _dl_clear_dtv (dtv_t *dtv) internal_function;
|
||||||
rtld_hidden_proto (_dl_clear_dtv)
|
rtld_hidden_proto (_dl_clear_dtv)
|
||||||
|
|
||||||
extern void *__signal_safe_memalign (size_t boundary, size_t size);
|
|
||||||
extern void *__signal_safe_malloc (size_t size);
|
|
||||||
extern void __signal_safe_free (void *ptr);
|
|
||||||
extern void *__signal_safe_realloc (void *ptr, size_t size);
|
|
||||||
extern void *__signal_safe_calloc (size_t nmemb, size_t size);
|
|
||||||
|
|
||||||
/* Deallocate memory allocated with _dl_allocate_tls. */
|
/* Deallocate memory allocated with _dl_allocate_tls. */
|
||||||
extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb) internal_function;
|
extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb) internal_function;
|
||||||
rtld_hidden_proto (_dl_deallocate_tls)
|
rtld_hidden_proto (_dl_deallocate_tls)
|
||||||
|
Reference in New Issue
Block a user