about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--elf/dl-open.c15
-rw-r--r--linuxthreads/ChangeLog5
-rw-r--r--linuxthreads/manager.c31
-rw-r--r--malloc/malloc.c36
5 files changed, 55 insertions, 38 deletions
diff --git a/ChangeLog b/ChangeLog
index 241e38bbd4..297ab49ece 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2000-12-28  Wolfram Gloger  <wg@malloc.de>
+
+	* malloc/malloc.c (MALLOC_COPY): Handle case if source and
+	destination overlap.  Assume dest is always below source if
+	overlapping.
+
 2000-12-30  Ulrich Drepper  <drepper@redhat.com>
 
 	* elf/dl-close.c (_dl_close): We can ignore the NODELETE flag if the
diff --git a/elf/dl-open.c b/elf/dl-open.c
index d1ccfd4ada..0170d1c0fb 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -269,10 +269,6 @@ dl_open_worker (void *a)
   /* Load that object's dependencies.  */
   _dl_map_object_deps (new, NULL, 0, 0);
 
-  /* Increment the open count for all dependencies.  */
-  for (i = 0; i < new->l_searchlist.r_nlist; ++i)
-    ++new->l_searchlist.r_list[i]->l_opencount;
-
   /* So far, so good.  Now check the versions.  */
   for (i = 0; i < new->l_searchlist.r_nlist; ++i)
     if (new->l_searchlist.r_list[i]->l_versions == NULL)
@@ -321,6 +317,10 @@ dl_open_worker (void *a)
       l = l->l_prev;
     }
 
+  /* Increment the open count for all dependencies.  */
+  for (i = 0; i < new->l_searchlist.r_nlist; ++i)
+    ++new->l_searchlist.r_list[i]->l_opencount;
+
   /* Run the initializer functions of new objects.  */
   _dl_init (new, __libc_argc, __libc_argv, __environ);
 
@@ -399,11 +399,10 @@ _dl_open (const char *file, int mode, const void *caller)
 	{
 	  int i;
 
-	  /* Increment open counters for all objects which did not get
-	     correctly loaded.  */
+	  /* Increment open counters for all objects since this has
+	     not happened yet.  */
 	  for (i = 0; i < args.map->l_searchlist.r_nlist; ++i)
-	    if (args.map->l_searchlist.r_list[i]->l_opencount == 0)
-	      args.map->l_searchlist.r_list[i]->l_opencount = 1;
+	    ++args.map->l_searchlist.r_list[i]->l_opencount;
 
 	  _dl_close (args.map);
 	}
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 176099431b..2bb9371912 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,8 @@
+2000-11-15  Wolfram Gloger  <wg@malloc.de>
+
+	* manager.c (pthread_free): [!FLOATING_STACKS]: Only remap the
+	stack to PROT_NONE, don't unmap it, avoiding collisions with malloc.
+
 2000-12-27  Andreas Jaeger  <aj@suse.de>
 
 	* Examples/ex13.c: Make local functions static.
diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c
index 37f426759f..8442629c08 100644
--- a/linuxthreads/manager.c
+++ b/linuxthreads/manager.c
@@ -418,7 +418,7 @@ static int pthread_allocate_stack(const pthread_attr_t *attr,
 
       new_thread_bottom = (char *) map_addr + guardsize;
       new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1;
-# else
+# else /* !FLOATING_STACKS */
       if (attr != NULL)
 	{
 	  guardsize = page_roundup (attr->__guardsize, granularity);
@@ -696,23 +696,24 @@ static void pthread_free(pthread_descr th)
     {
       size_t guardsize = th->p_guardsize;
       /* Free the stack and thread descriptor area */
-#ifdef NEED_SEPARATE_REGISTER_STACK
       char *guardaddr = th->p_guardaddr;
-      /* We unmap exactly what we mapped, in case there was something
-	 else in the same region.  Guardaddr is always set, eve if
-	 guardsize is 0.  This allows us to compute everything else.  */
+      /* Guardaddr is always set, even if guardsize is 0.  This allows
+	 us to compute everything else.  */
       size_t stacksize = (char *)(th+1) - guardaddr - guardsize;
-      /* Unmap the register stack, which is below guardaddr.  */
-      munmap((caddr_t)(guardaddr-stacksize),
-	     2 * stacksize + th->p_guardsize);
+#ifdef NEED_SEPARATE_REGISTER_STACK
+      /* Take account of the register stack, which is below guardaddr.  */
+      guardaddr -= stacksize;
+      stacksize *= 2;
+#endif
+#if FLOATING_STACKS
+      /* Can unmap safely.  */
+      munmap(guardaddr, stacksize + guardsize);
 #else
-      char *guardaddr = th->p_guardaddr;
-      /* We unmap exactly what we mapped, in case there was something
-	 else in the same region.  Guardaddr is always set, eve if
-	 guardsize is 0.  This allows us to compute everything else.  */
-      size_t stacksize = (char *)(th+1) - guardaddr - guardsize;
-
-      munmap (guardaddr, stacksize + guardsize);
+      /* Only remap to PROT_NONE, so that the region is reserved in
+         case we map the stack again later.  Avoid collision with
+         other mmap()s, in particular by malloc().  */
+      mmap(guardaddr, stacksize + guardsize, PROT_NONE,
+	   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
 #endif
     }
 }
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 187c8147a0..1ac3b5da45 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -423,11 +423,12 @@ Void_t* memmove();
 #endif
 #endif
 
-#if USE_MEMCPY
-
 /* The following macros are only invoked with (2n+1)-multiples of
    INTERNAL_SIZE_T units, with a positive integer n. This is exploited
-   for fast inline execution when n is small. */
+   for fast inline execution when n is small.  If the regions to be
+   copied do overlap, the destination lies always _below_ the source.  */
+
+#if USE_MEMCPY
 
 #define MALLOC_ZERO(charp, nbytes)                                            \
 do {                                                                          \
@@ -446,7 +447,9 @@ do {                                                                          \
   } else memset((charp), 0, mzsz);                                            \
 } while(0)
 
-#define MALLOC_COPY(dest,src,nbytes)                                          \
+/* If the regions overlap, dest is always _below_ src.  */
+
+#define MALLOC_COPY(dest,src,nbytes,overlap)                                  \
 do {                                                                          \
   INTERNAL_SIZE_T mcsz = (nbytes);                                            \
   if(mcsz <= 9*sizeof(mcsz)) {                                                \
@@ -461,12 +464,12 @@ do {                                                                          \
                                      *mcdst++ = *mcsrc++;                     \
                                      *mcdst++ = *mcsrc++;                     \
                                      *mcdst   = *mcsrc  ;                     \
-  } else memcpy(dest, src, mcsz);                                             \
+  } else if(overlap)                                                          \
+    memmove(dest, src, mcsz);                                                 \
+  else                                                                        \
+    memcpy(dest, src, mcsz);                                                  \
 } while(0)
 
-#define MALLOC_MEMMOVE(dest,src,nbytes)                                       \
-  memmove(dest, src, mcsz)
-
 #else /* !USE_MEMCPY */
 
 /* Use Duff's device for good zeroing/copying performance. */
@@ -488,7 +491,9 @@ do {                                                                          \
   }                                                                           \
 } while(0)
 
-#define MALLOC_COPY(dest,src,nbytes)                                          \
+/* If the regions overlap, dest is always _below_ src.  */
+
+#define MALLOC_COPY(dest,src,nbytes,overlap)                                  \
 do {                                                                          \
   INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \
   INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \
@@ -3255,7 +3260,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
     /* Must alloc, copy, free. */
     newmem = mALLOc(bytes);
     if (newmem == 0) return 0; /* propagate failure */
-    MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
+    MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ, 0);
     munmap_chunk(oldp);
     return newmem;
   }
@@ -3370,7 +3375,8 @@ arena* ar_ptr; mchunkptr oldp; INTERNAL_SIZE_T oldsize, nb;
             unlink(prev, bck, fwd);
             newp = prev;
             newsize += prevsize + nextsize;
-            MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize);
+            MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize,
+                        1);
             top(ar_ptr) = chunk_at_offset(newp, nb);
             set_head(top(ar_ptr), (newsize - nb) | PREV_INUSE);
             set_head_size(newp, nb);
@@ -3385,7 +3391,7 @@ arena* ar_ptr; mchunkptr oldp; INTERNAL_SIZE_T oldsize, nb;
           unlink(prev, bck, fwd);
           newp = prev;
           newsize += nextsize + prevsize;
-          MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize);
+          MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize, 1);
           goto split;
         }
       }
@@ -3396,7 +3402,7 @@ arena* ar_ptr; mchunkptr oldp; INTERNAL_SIZE_T oldsize, nb;
         unlink(prev, bck, fwd);
         newp = prev;
         newsize += prevsize;
-        MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize);
+        MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize, 1);
         goto split;
       }
     }
@@ -3436,7 +3442,7 @@ arena* ar_ptr; mchunkptr oldp; INTERNAL_SIZE_T oldsize, nb;
     }
 
     /* Otherwise copy, free, and exit */
-    MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize);
+    MALLOC_COPY(BOUNDED_N(chunk2mem(newp), oldsize), oldmem, oldsize, 0);
     chunk_free(ar_ptr, oldp);
     return newp;
   }
@@ -4605,7 +4611,7 @@ realloc_check(oldmem, bytes, caller)
         newp = (top_check() >= 0) ? chunk_alloc(&main_arena, nb) : NULL;
         if (newp) {
           MALLOC_COPY(BOUNDED_N(chunk2mem(newp), nb),
-		      oldmem, oldsize - 2*SIZE_SZ);
+		      oldmem, oldsize - 2*SIZE_SZ, 0);
           munmap_chunk(oldp);
         }
       }