This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch master updated. glibc-2.24-20-g6c444ad


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  6c444ad6e953dbdf9c7be065308a0a7779d32bb2 (commit)
       via  a2ff21f825adb8821eeb6145197fa8b9a8a60a58 (commit)
      from  5bc17330eb7667b96fee8baf3729c3310fa28b40 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6c444ad6e953dbdf9c7be065308a0a7779d32bb2

commit 6c444ad6e953dbdf9c7be065308a0a7779d32bb2
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed Aug 3 16:16:57 2016 +0200

    elf: Do not use memalign for TCB/TLS blocks allocation [BZ #17730]
    
    Instead, call malloc and explicitly align the pointer.
    
    There is no external location to store the original (unaligned)
    pointer, and this commit increases the allocation size to store
    the pointer at a fixed location relative to the TCB pointer.
    
    The manual alignment means that some space goes unused which
    was previously made available for subsequent allocations.
    However, in the TLS_DTV_AT_TP case, the manual alignment code
    avoids aligning the pre-TCB to the TLS block alignment.  (Even
    while using memalign, the allocation had some unused padding
    in front.)
    
    This concludes the removal of memalign calls from the TLS code,
    and the new tst-tls3-malloc test verifies that only core malloc
    routines are used.

diff --git a/ChangeLog b/ChangeLog
index 5bc45b5..3ffa64c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,21 @@
 2016-08-03  Florian Weimer  <fweimer@redhat.com>
 
 	[BZ #17730]
+	Avoid using memalign for TCB allocations.
+	* elf/dl-tls.c (tcb_to_pointer_to_free_location): New.
+	(_dl_allocate_tls_storage): Use malloc and manual alignment.
+	Avoid alignment gap in the TLS_DTV_AT_TP case.
+	(_dl_deallocate_tls): Use tcb_to_pointer_to_free_location to
+	determine the pointer to free.
+	* nptl/tst-tls3-malloc.c: New test.
+	* nptl/Makefile (tests): Add it.
+	(tst-tls3-malloc): Link with libdl, libpthread.
+	(LDFLAGS-tst-tls3-malloc): Set.
+	(tst-tls3-malloc.out): Depend on DSO used in test.
+
+2016-08-03  Florian Weimer  <fweimer@redhat.com>
+
+	[BZ #17730]
 	Avoid using memalign for TLS allocations.
 	* sysdeps/generic/dl-dtv.h (struct dtv_pointer): New.  Replaces
 	is_static member with to_free member.
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index be6a3c7..17567ad 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -347,6 +347,22 @@ _dl_get_tls_static_info (size_t *sizep, size_t *alignp)
   *alignp = GL(dl_tls_static_align);
 }
 
+/* Derive the location of the pointer to the start of the original
+   allocation (before alignment) from the pointer to the TCB.  */
+static inline void **
+tcb_to_pointer_to_free_location (void *tcb)
+{
+#if TLS_TCB_AT_TP
+  /* The TCB follows the TLS blocks, and the pointer to the front
+     follows the TCB.  */
+  void **original_pointer_location = tcb + TLS_TCB_SIZE;
+#elif TLS_DTV_AT_TP
+  /* The TCB comes first, preceded by the pre-TCB, and the pointer is
+     before that.  */
+  void **original_pointer_location = tcb - TLS_PRE_TCB_SIZE - sizeof (void *);
+#endif
+  return original_pointer_location;
+}
 
 void *
 internal_function
@@ -359,39 +375,50 @@ _dl_allocate_tls_storage (void)
   /* Memory layout is:
      [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ]
 			  ^ This should be returned.  */
-  size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1)
-	  & ~(GL(dl_tls_static_align) - 1);
+  size += TLS_PRE_TCB_SIZE;
 #endif
 
-  /* Allocate a correctly aligned chunk of memory.  */
-  result = __libc_memalign (GL(dl_tls_static_align), size);
-  if (__builtin_expect (result != NULL, 1))
-    {
-      /* Allocate the DTV.  */
-      void *allocated = result;
+  /* Perform the allocation.  Reserve space for the required alignment
+     and the pointer to the original allocation.  */
+  size_t alignment = GL(dl_tls_static_align);
+  void *allocated = malloc (size + alignment + sizeof (void *));
+  if (__glibc_unlikely (allocated == NULL))
+    return NULL;
 
+  /* Perform alignment and allocate the DTV.  */
 #if TLS_TCB_AT_TP
-      /* The TCB follows the TLS blocks.  */
-      result = (char *) result + size - TLS_TCB_SIZE;
-
-      /* Clear the TCB data structure.  We can't ask the caller (i.e.
-	 libpthread) to do it, because we will initialize the DTV et al.  */
-      memset (result, '\0', TLS_TCB_SIZE);
+  /* The TCB follows the TLS blocks, which determine the alignment.
+     (TCB alignment requirements have been taken into account when
+     calculating GL(dl_tls_static_align).)  */
+  void *aligned = (void *) roundup ((uintptr_t) allocated, alignment);
+  result = aligned + size - TLS_TCB_SIZE;
+
+  /* Clear the TCB data structure.  We can't ask the caller (i.e.
+     libpthread) to do it, because we will initialize the DTV et al.  */
+  memset (result, '\0', TLS_TCB_SIZE);
 #elif TLS_DTV_AT_TP
-      result = (char *) result + size - GL(dl_tls_static_size);
-
-      /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it.
-	 We can't ask the caller (i.e. libpthread) to do it, because we will
-	 initialize the DTV et al.  */
-      memset ((char *) result - TLS_PRE_TCB_SIZE, '\0',
-	      TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
+  /* Pre-TCB and TCB come before the TLS blocks.  The layout computed
+     in _dl_determine_tlsoffset assumes that the TCB is aligned to the
+     TLS block alignment, and not just the TLS blocks after it.  This
+     can leave an unused alignment gap between the TCB and the TLS
+     blocks.  */
+  result = (void *) roundup
+    (sizeof (void *) + TLS_PRE_TCB_SIZE + (uintptr_t) allocated,
+     alignment);
+
+  /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before
+     it.  We can't ask the caller (i.e. libpthread) to do it, because
+     we will initialize the DTV et al.  */
+  memset (result - TLS_PRE_TCB_SIZE, '\0', TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
 #endif
 
-      result = allocate_dtv (result);
-      if (result == NULL)
-	free (allocated);
-    }
+  /* Record the value of the original pointer for later
+     deallocation.  */
+  *tcb_to_pointer_to_free_location (result) = allocated;
 
+  result = allocate_dtv (result);
+  if (result == NULL)
+    free (allocated);
   return result;
 }
 
@@ -558,17 +585,7 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
     free (dtv - 1);
 
   if (dealloc_tcb)
-    {
-#if TLS_TCB_AT_TP
-      /* The TCB follows the TLS blocks.  Back up to free the whole block.  */
-      tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE;
-#elif TLS_DTV_AT_TP
-      /* Back up the TLS_PRE_TCB_SIZE bytes.  */
-      tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1)
-	     & ~(GL(dl_tls_static_align) - 1);
-#endif
-      free (tcb);
-    }
+    free (*tcb_to_pointer_to_free_location (tcb));
 }
 rtld_hidden_def (_dl_deallocate_tls)
 
diff --git a/nptl/Makefile b/nptl/Makefile
index 0d8aade..2ddcd2b 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -321,8 +321,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
 	 tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
 	 tst-oncex3 tst-oncex4
 ifeq ($(build-shared),yes)
-tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \
-	 tst-stackguard1
+tests += tst-atfork2 tst-tls3 tst-tls3-malloc tst-tls4 tst-tls5 tst-_res1 \
+	 tst-fini1 tst-stackguard1
 tests-nolibpthread += tst-fini1
 ifeq ($(have-z-execstack),yes)
 tests += tst-execstack
@@ -529,6 +529,10 @@ LDFLAGS-tst-tls3 = -rdynamic
 $(objpfx)tst-tls3.out: $(objpfx)tst-tls3mod.so
 $(objpfx)tst-tls3mod.so: $(shared-thread-library)
 
+$(objpfx)tst-tls3-malloc: $(libdl) $(shared-thread-library)
+LDFLAGS-tst-tls3-malloc = -rdynamic
+$(objpfx)tst-tls3-malloc.out: $(objpfx)tst-tls3mod.so
+
 $(objpfx)tst-tls4: $(libdl) $(shared-thread-library)
 $(objpfx)tst-tls4.out: $(objpfx)tst-tls4moda.so $(objpfx)tst-tls4modb.so
 
diff --git a/nptl/tst-tls3-malloc.c b/nptl/tst-tls3-malloc.c
new file mode 100644
index 0000000..5eab3cd
--- /dev/null
+++ b/nptl/tst-tls3-malloc.c
@@ -0,0 +1,176 @@
+/* Test TLS allocation with an interposed malloc.
+   Copyright (C) 2016 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
+   <http://www.gnu.org/licenses/>.  */
+
+/* Reuse the test.  */
+#include "tst-tls3.c"
+
+#include <sys/mman.h>
+
+/* Interpose a minimal malloc implementation.  This implementation
+   deliberately interposes just a restricted set of symbols, to detect
+   if the TLS code bypasses the interposed malloc.  */
+
+/* Lock to guard malloc internals.  */
+static pthread_mutex_t malloc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Information about an allocation chunk.  */
+struct malloc_chunk
+{
+  /* Start of the allocation.  */
+  void *start;
+  /* Size of the allocation.  */
+  size_t size;
+};
+
+enum { malloc_chunk_count = 1000 };
+static struct malloc_chunk chunks[malloc_chunk_count];
+
+/* Lock the malloc lock.  */
+static void
+xlock (void)
+{
+  int ret = pthread_mutex_lock (&malloc_lock);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_mutex_lock: %m\n");
+      _exit (1);
+    }
+}
+
+/* Unlock the malloc lock.  */
+static void
+xunlock (void)
+{
+  int ret = pthread_mutex_unlock (&malloc_lock);
+  if (ret != 0)
+    {
+      errno = ret;
+      printf ("error: pthread_mutex_unlock: %m\n");
+      _exit (1);
+    }
+}
+
+/* Internal malloc without locking and registration.  */
+static void *
+malloc_internal (size_t size)
+{
+  void *result = mmap (NULL, size, PROT_READ | PROT_WRITE,
+                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+  if (result == MAP_FAILED)
+    {
+      printf ("error: mmap: %m\n");
+      _exit (1);
+    }
+  return result;
+}
+
+void *
+malloc (size_t size)
+{
+  if (size == 0)
+    size = 1;
+  xlock ();
+  void *result = malloc_internal (size);
+  for (int i = 0; i < malloc_chunk_count; ++i)
+    if (chunks[i].start == NULL)
+      {
+        chunks[i].start = result;
+        chunks[i].size = size;
+        xunlock ();
+        return result;
+      }
+  xunlock ();
+  printf ("error: no place to store chunk pointer\n");
+  _exit (1);
+}
+
+void *
+calloc (size_t a, size_t b)
+{
+  if (b != 0 && a > SIZE_MAX / b)
+    return NULL;
+  /* malloc uses mmap, which provides zeroed memory.  */
+  return malloc (a * b);
+}
+
+static void
+xunmap (void *ptr, size_t size)
+{
+  int ret = munmap (ptr, size);
+  if (ret < 0)
+    {
+      printf ("error: munmap (%p, %zu) failed: %m\n", ptr, size);
+      _exit (1);
+    }
+}
+
+void
+free (void *ptr)
+{
+  if (ptr == NULL)
+    return;
+
+  xlock ();
+  for (int i = 0; i < malloc_chunk_count; ++i)
+    if (chunks[i].start == ptr)
+      {
+        xunmap (ptr, chunks[i].size);
+        chunks[i] = (struct malloc_chunk) {};
+        xunlock ();
+        return;
+      }
+  xunlock ();
+  printf ("error: tried to free non-allocated pointer %p\n", ptr);
+  _exit (1);
+}
+
+void *
+realloc (void *old, size_t size)
+{
+  if (old != NULL)
+    {
+      xlock ();
+      for (int i = 0; i < malloc_chunk_count; ++i)
+        if (chunks[i].start == old)
+          {
+            size_t old_size = chunks[i].size;
+            void *result;
+            if (old_size < size)
+              {
+                result = malloc_internal (size);
+                /* Reuse the slot for the new allocation.  */
+                memcpy (result, old, old_size);
+                xunmap (old, old_size);
+                chunks[i].start = result;
+                chunks[i].size = size;
+              }
+            else
+              /* Old size is not smaller, so reuse the old
+                 allocation.  */
+              result = old;
+            xunlock ();
+            return result;
+          }
+      xunlock ();
+      printf ("error: tried to realloc non-allocated pointer %p\n", old);
+      _exit (1);
+    }
+  else
+    return malloc (size);
+}

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=a2ff21f825adb8821eeb6145197fa8b9a8a60a58

commit a2ff21f825adb8821eeb6145197fa8b9a8a60a58
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed Aug 3 16:15:38 2016 +0200

    elf: Avoid using memalign for TLS allocations [BZ #17730]
    
    Instead of a flag which indicates the pointer can be freed, dtv_t
    now includes the pointer which should be freed.  Due to padding,
    the size of dtv_t does not increase.
    
    To avoid using memalign, the new allocate_dtv_entry function
    allocates a sufficiently large buffer so that a sub-buffer
    can be found in it which starts with an aligned pointer.  Both
    the aligned and original pointers are kept, the latter for calling
    free later.

diff --git a/ChangeLog b/ChangeLog
index f222c13..5bc45b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
 2016-08-03  Florian Weimer  <fweimer@redhat.com>
 
+	[BZ #17730]
+	Avoid using memalign for TLS allocations.
+	* sysdeps/generic/dl-dtv.h (struct dtv_pointer): New.  Replaces
+	is_static member with to_free member.
+	(union dtv): Use struct dtv_pointer.
+	* csu/libc-tls.c (__libc_setup_tls): Set to_free member of struct
+	dtv_pointer instead of is_static.
+	* elf/dl-tls.c (_dl_allocate_tls_init): Likewise.
+	(_dl_deallocate_tls): Free to_free member of struct dtv_pointer
+	instead of val.
+	(allocate_dtv_entry): New function.
+	(allocate_and_init): Return struct dtv_pointer.  Call
+	allocate_dtv_entry instead of __libc_memalign.
+	(_dl_update_slotinfo): Free to_free member of struct dtv_pointer
+	instead of val.
+	(tls_get_addr_tail): Set to_free member of struct dtv_pointer
+	instead of is_static.  Adjust call to allocate_and_init.
+	* nptl/allocatestack.c (get_cached_stack): Free to_free member of
+	struct dtv_pointer instead of val.
+
+2016-08-03  Florian Weimer  <fweimer@redhat.com>
+
 	* malloc/malloc.c (INTERNAL_SIZE_T, SIZE_SZ, MALLOC_ALIGNMENT)
 	(MALLOC_ALIGN_MASK): Move ...
 	* malloc/malloc-internal.h: ... to here.
diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index d6425e0..235ac79 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -175,7 +175,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
 #else
 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 #endif
-  _dl_static_dtv[2].pointer.is_static = true;
+  _dl_static_dtv[2].pointer.to_free = NULL;
   /* sbrk gives us zero'd memory, so we don't need to clear the remainder.  */
   memcpy (_dl_static_dtv[2].pointer.val, initimage, filesz);
 
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index ed13fd9..be6a3c7 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -494,7 +494,7 @@ _dl_allocate_tls_init (void *result)
 	  maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
 
 	  dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
-	  dtv[map->l_tls_modid].pointer.is_static = false;
+	  dtv[map->l_tls_modid].pointer.to_free = NULL;
 
 	  if (map->l_tls_offset == NO_TLS_OFFSET
 	      || map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET)
@@ -551,9 +551,7 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
 
   /* We need to free the memory allocated for non-static TLS.  */
   for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
-    if (! dtv[1 + cnt].pointer.is_static
-	&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
-      free (dtv[1 + cnt].pointer.val);
+    free (dtv[1 + cnt].pointer.to_free);
 
   /* The array starts with dtv[-1].  */
   if (dtv != GL(dl_initial_dtv))
@@ -594,21 +592,49 @@ rtld_hidden_def (_dl_deallocate_tls)
 #  define GET_ADDR_OFFSET ti->ti_offset
 # endif
 
+/* Allocate one DTV entry.  */
+static struct dtv_pointer
+allocate_dtv_entry (size_t alignment, size_t size)
+{
+  if (powerof2 (alignment) && alignment <= _Alignof (max_align_t))
+    {
+      /* The alignment is supported by malloc.  */
+      void *ptr = malloc (size);
+      return (struct dtv_pointer) { ptr, ptr };
+    }
 
-static void *
+  /* Emulate memalign to by manually aligning a pointer returned by
+     malloc.  First compute the size with an overflow check.  */
+  size_t alloc_size = size + alignment;
+  if (alloc_size < size)
+    return (struct dtv_pointer) {};
+
+  /* Perform the allocation.  This is the pointer we need to free
+     later.  */
+  void *start = malloc (alloc_size);
+  if (start == NULL)
+    return (struct dtv_pointer) {};
+
+  /* Find the aligned position within the larger allocation.  */
+  void *aligned = (void *) roundup ((uintptr_t) start, alignment);
+
+  return (struct dtv_pointer) { .val = aligned, .to_free = start };
+}
+
+static struct dtv_pointer
 allocate_and_init (struct link_map *map)
 {
-  void *newp;
-
-  newp = __libc_memalign (map->l_tls_align, map->l_tls_blocksize);
-  if (newp == NULL)
+  struct dtv_pointer result = allocate_dtv_entry
+    (map->l_tls_align, map->l_tls_blocksize);
+  if (result.val == NULL)
     oom ();
 
   /* Initialize the memory.  */
-  memset (__mempcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size),
+  memset (__mempcpy (result.val, map->l_tls_initimage,
+		     map->l_tls_initimage_size),
 	  '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
 
-  return newp;
+  return result;
 }
 
 
@@ -678,12 +704,9 @@ _dl_update_slotinfo (unsigned long int req_modid)
 		    {
 		      /* If this modid was used at some point the memory
 			 might still be allocated.  */
-		      if (! dtv[total + cnt].pointer.is_static
-			  && (dtv[total + cnt].pointer.val
-			      != TLS_DTV_UNALLOCATED))
-			free (dtv[total + cnt].pointer.val);
+		      free (dtv[total + cnt].pointer.to_free);
 		      dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
-		      dtv[total + cnt].pointer.is_static = false;
+		      dtv[total + cnt].pointer.to_free = NULL;
 		    }
 
 		  continue;
@@ -708,16 +731,9 @@ _dl_update_slotinfo (unsigned long int req_modid)
 		 dtv entry free it.  */
 	      /* XXX Ideally we will at some point create a memory
 		 pool.  */
-	      if (! dtv[modid].pointer.is_static
-		  && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
-		/* Note that free is called for NULL is well.  We
-		   deallocate even if it is this dtv entry we are
-		   supposed to load.  The reason is that we call
-		   memalign and not malloc.  */
-		free (dtv[modid].pointer.val);
-
+	      free (dtv[modid].pointer.to_free);
 	      dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
-	      dtv[modid].pointer.is_static = false;
+	      dtv[modid].pointer.to_free = NULL;
 
 	      if (modid == req_modid)
 		the_map = map;
@@ -780,7 +796,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
 #endif
 	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 
-	  dtv[GET_ADDR_MODULE].pointer.is_static = true;
+	  dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
 	  dtv[GET_ADDR_MODULE].pointer.val = p;
 
 	  return (char *) p + GET_ADDR_OFFSET;
@@ -788,10 +804,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
       else
 	__rtld_lock_unlock_recursive (GL(dl_load_lock));
     }
-  void *p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
-  assert (!dtv[GET_ADDR_MODULE].pointer.is_static);
+  struct dtv_pointer result = allocate_and_init (the_map);
+  dtv[GET_ADDR_MODULE].pointer = result;
+  assert (result.to_free != NULL);
 
-  return (char *) p + GET_ADDR_OFFSET;
+  return (char *) result.val + GET_ADDR_OFFSET;
 }
 
 
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 6b42b11..60b34dc 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -245,9 +245,7 @@ get_cached_stack (size_t *sizep, void **memp)
   /* Clear the DTV.  */
   dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
   for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
-    if (! dtv[1 + cnt].pointer.is_static
-	&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
-      free (dtv[1 + cnt].pointer.val);
+    free (dtv[1 + cnt].pointer.to_free);
   memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
 
   /* Re-initialize the TLS.  */
diff --git a/sysdeps/generic/dl-dtv.h b/sysdeps/generic/dl-dtv.h
index 36c5c58..39d8fe2 100644
--- a/sysdeps/generic/dl-dtv.h
+++ b/sysdeps/generic/dl-dtv.h
@@ -19,15 +19,17 @@
 #ifndef _DL_DTV_H
 #define _DL_DTV_H
 
+struct dtv_pointer
+{
+  void *val;                    /* Pointer to data, or TLS_DTV_UNALLOCATED.  */
+  void *to_free;                /* Unaligned pointer, for deallocation.  */
+};
+
 /* Type for the dtv.  */
 typedef union dtv
 {
   size_t counter;
-  struct
-  {
-    void *val;
-    bool is_static;
-  } pointer;
+  struct dtv_pointer pointer;
 } dtv_t;
 
 /* Value used for dtv entries for which the allocation is delayed.  */

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                |   37 ++++++++++
 csu/libc-tls.c           |    2 +-
 elf/dl-tls.c             |  164 ++++++++++++++++++++++++++-----------------
 nptl/Makefile            |    8 ++-
 nptl/allocatestack.c     |    4 +-
 nptl/tst-tls3-malloc.c   |  176 ++++++++++++++++++++++++++++++++++++++++++++++
 sysdeps/generic/dl-dtv.h |   12 ++--
 7 files changed, 327 insertions(+), 76 deletions(-)
 create mode 100644 nptl/tst-tls3-malloc.c


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]