summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--csu/gmon-start.c6
-rw-r--r--elf/dl-close.c65
3 files changed, 76 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 99727733eb..bcc868fff8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2002-02-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/dl-close.c (_dl_close): Implement freeing entries in the
+	slotinfo array.
+	(free_mem): Free memory for the slotinfo array if possible.
+
 2002-02-12  Andreas Schwab  <schwab@suse.de>
 
 	* csu/gmon-start.c (__gmon_start__): Remove '&' from ENTRY_POINT.
diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index 1aaeefcf7f..9ee722aa0f 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -1,5 +1,5 @@
 /* Code to enable profiling at program startup.
-   Copyright (C) 1995, 1996, 1997, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1995,1996,1997,2000,2001,2002 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
@@ -63,7 +63,11 @@ __gmon_start__ (void)
 #endif
 
   /* Start keeping profiling records.  */
+#ifdef ENTRY_POINT_DECL
   __monstartup ((u_long) ENTRY_POINT, (u_long) &etext);
+#else
+  __monstartup ((u_long) &ENTRY_POINT, (u_long) &etext);
+#endif
 
   /* Call _mcleanup before exiting; it will write out gmon.out from the
      collected data.  */
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 65de9e7809..5c7e5dad38 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -46,6 +46,9 @@ _dl_close (void *_map)
   struct link_map *map = _map;
   unsigned int i;
   unsigned int *new_opencount;
+#ifdef USE_TLS
+  bool any_tls = false;
+#endif
 
   /* First see whether we can remove the object at all.  */
   if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
@@ -206,6 +209,28 @@ _dl_close (void *_map)
 	      --GL(dl_main_searchlist)->r_nlist;
 	    }
 
+#ifdef USE_TLS
+	  /* Remove the object from the dtv slotinfo array if it uses
+	     TLS.  */
+	  if (__builtin_expect (imap->l_tls_blocksize > 0, 0))
+	    {
+	      /* Locate the entry in the slotinfo array.  */
+	      size_t idx = imap->l_tls_modid;
+	      struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+
+	      while (idx >= listp->len)
+		{
+		  idx -= listp->len;
+		  listp = listp->next;
+		}
+
+	      listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
+	      listp->slotinfo[idx].map = NULL;
+
+	      any_tls = true;
+	    }
+#endif
+
 	  /* We can unmap all the maps at once.  We determined the
 	     start address and length when we loaded the object and
 	     the `munmap' call does the rest.  */
@@ -279,6 +304,12 @@ _dl_close (void *_map)
 	}
     }
 
+#ifdef USE_TLS
+  /* If we removed any object which uses TLS bumnp the generation
+     counter.  */
+  ++GL(dl_tls_generation);
+#endif
+
   /* Notify the debugger those objects are finalized and gone.  */
   _r_debug.r_state = RT_CONSISTENT;
   _dl_debug_state ();
@@ -302,6 +333,30 @@ _dl_close (void *_map)
 }
 
 
+static bool
+free_slotinfo (struct dtv_slotinfo_list *elemp)
+{
+  size_t cnt;
+
+  if (elemp->next != NULL && !free_slotinfo (elemp->next))
+    /* We cannot free the entry.  */
+    return false;
+
+  /* The least we could do is remove next element (if there was any).  */
+  elemp->next = NULL;
+
+  for (cnt = 0; cnt < elemp->len; ++cnt)
+    if (elemp->slotinfo[cnt].map != NULL)
+      /* Still used.  */
+      return false;
+
+  /* We can remove the list element.  */
+  free (elemp);
+
+  return true;
+}
+
+
 static void
 free_mem (void)
 {
@@ -320,5 +375,15 @@ free_mem (void)
       /* Now free the old map.  */
       free (old);
     }
+
+#ifdef USE_TLS
+  /* Free the memory allocated for the dtv slotinfo array.  We can do
+     this only if all modules which used this memory are unloaded.
+     Also, the first element of the list does not have to be
+     deallocated.  It was allocated in the dynamic linker (i.e., with
+     a different malloc).  */
+  if (free_slotinfo (GL(dl_tls_dtv_slotinfo_list)->next))
+    GL(dl_tls_dtv_slotinfo_list)->next = NULL;
+#endif
 }
 text_set_element (__libc_subfreeres, free_mem);