aboutsummaryrefslogtreecommitdiff
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);