From 42c4f32a44c76d1f4e2b744bf80f495dc36caa87 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Tue, 24 Oct 2000 07:36:55 +0000 Subject: Update. 2000-10-24 Ulrich Drepper Complete revamp of the reference counter handling. * include/link.h (struct link_map): Add l_idx field. * elf/dl-close.c: Handle decrementing of reference counters more correctly. If necessary decrement reference counters of dependencies of dependencies. * elf/dl-lookup.c (add_dependency): Only increment reference counter of the object itself and not also its dependencies. * elf/dl-open.c: Increment reference counters here. * elf/dl-deps.c: Remove reference counter handling here. * elf/dl-load.c: Likewise. * elf/rtld.c: Adjust for _dl_map_deps not handling reference counters. * elf/loadtest.c: Print loaded objects at the beginning. --- ChangeLog | 16 ++++++++++++++++ elf/dl-close.c | 56 ++++++++++++++++++++++++++++++++++++++++++-------------- elf/dl-deps.c | 21 ++------------------- elf/dl-load.c | 15 ++++----------- elf/dl-lookup.c | 6 +----- elf/dl-open.c | 11 +++++++++-- elf/loadtest.c | 8 +++++++- elf/rtld.c | 16 ++++++++++------ 8 files changed, 91 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 79c3c0ded2..4c0a9057cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2000-10-24 Ulrich Drepper + + Complete revamp of the reference counter handling. + * include/link.h (struct link_map): Add l_idx field. + * elf/dl-close.c: Handle decrementing of reference counters more + correctly. If necessary decrement reference counters of dependencies + of dependencies. + * elf/dl-lookup.c (add_dependency): Only increment reference counter + of the object itself and not also its dependencies. + * elf/dl-open.c: Increment reference counters here. + * elf/dl-deps.c: Remove reference counter handling here. + * elf/dl-load.c: Likewise. + * elf/rtld.c: Adjust for _dl_map_deps not handling reference counters. + + * elf/loadtest.c: Print loaded objects at the beginning. + 2000-10-24 Andreas Jaeger * sysdeps/mips/dl-machine.h: Partly revert patch from 2000-10-18. diff --git a/elf/dl-close.c b/elf/dl-close.c index 4c861a1d06..21305402c0 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -49,6 +49,7 @@ _dl_close (void *_map) unsigned int nsearchlist; unsigned int nrellist; unsigned int i; + unsigned int *new_opencount; /* First see whether we can remove the object at all. */ if (map->l_flags_1 & DF_1_NODELETE) @@ -61,9 +62,6 @@ _dl_close (void *_map) /* Acquire the lock. */ __libc_lock_lock (_dl_load_lock); - list = map->l_searchlist.r_list; - nsearchlist = map->l_searchlist.r_nlist; - /* Decrement the reference count. */ if (map->l_opencount > 1 || map->l_type != lt_loaded) { @@ -81,14 +79,46 @@ _dl_close (void *_map) "\n", NULL); } - for (i = 0; i < nsearchlist; ++i) - if (! (list[i]->l_flags_1 & DF_1_NODELETE)) - --list[i]->l_opencount; + /* One decrement the object itself, not the dependencies. */ + --map->l_opencount; __libc_lock_unlock (_dl_load_lock); return; } + list = map->l_searchlist.r_list; + nsearchlist = map->l_searchlist.r_nlist; + + /* Compute the new l_opencount values. */ + new_opencount = (unsigned int *) alloca (nsearchlist + * sizeof (unsigned int)); + for (i = 0; i < nsearchlist; ++i) + { + list[i]->l_idx = i; + new_opencount[i] = list[i]->l_opencount; + } + --new_opencount[0]; + for (i = 1; i < nsearchlist; ++i) + if (! (list[i]->l_flags_1 & DF_1_NODELETE) + /* Decrement counter. */ + && --new_opencount[i] == 0 + /* Test whether this object was also loaded directly. */ + && list[i]->l_searchlist.r_list != NULL) + { + /* In this case we have the decrement all the dependencies of + this object. They are all in MAP's dependency list. */ + unsigned int j; + struct link_map **dep_list = list[i]->l_searchlist.r_list; + + for (j = 1; j < list[i]->l_searchlist.r_nlist; ++j) + if (! (dep_list[j]->l_flags_1 & DF_1_NODELETE)) + { + assert (dep_list[j]->l_idx < nsearchlist); + --new_opencount[dep_list[j]->l_idx]; + } + } + assert (new_opencount[0] == 0); + rellist = map->l_reldeps; nrellist = map->l_reldepsact; @@ -96,7 +126,7 @@ _dl_close (void *_map) for (i = 0; i < nsearchlist; ++i) { struct link_map *imap = map->l_initfini[i]; - if (imap->l_opencount == 1 && imap->l_type == lt_loaded + if (new_opencount[i] == 0 && imap->l_type == lt_loaded && (imap->l_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY]) && ! (imap->l_flags_1 & DF_1_NODELETE) /* Skip any half-cooked objects that were never initialized. */ @@ -126,19 +156,17 @@ _dl_close (void *_map) (*(void (*) (void)) ((void *) imap->l_addr + imap->l_info[DT_FINI]->d_un.d_ptr)) (); } + + /* Store the new l_opencount value. */ + imap->l_opencount = new_opencount[i]; + /* Just a sanity check. */ + assert (imap->l_type == lt_loaded || imap->l_opencount > 0); } /* Notify the debugger we are about to remove some loaded objects. */ _r_debug.r_state = RT_DELETE; _dl_debug_state (); - /* The search list contains a counted reference to each object it - points to, the 0th elt being MAP itself. Decrement the reference - counts on all the objects MAP depends on. */ - for (i = 0; i < nsearchlist; ++i) - if (! (list[i]->l_flags_1 & DF_1_NODELETE)) - --list[i]->l_opencount; - /* Check each element of the search list to see if all references to it are gone. */ for (i = 0; i < nsearchlist; ++i) diff --git a/elf/dl-deps.c b/elf/dl-deps.c index c4582926b8..c3feb98270 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -243,18 +243,7 @@ _dl_map_object_deps (struct link_map *map, dtail = newp; ++nduplist; - if (dep->l_reserved) - { - /* This object is already in the search list we are - building. Don't add a duplicate pointer. - Release the reference just added by - _dl_map_object. */ - if (dep->l_initfini != NULL) - for (i = 1; dep->l_initfini[i] != NULL; ++i) - --dep->l_initfini[i]->l_opencount; - --dep->l_opencount; - } - else + if (! dep->l_reserved) { /* Append DEP to the unique list. */ newp->done = 0; @@ -363,13 +352,7 @@ _dl_map_object_deps (struct link_map *map, /* This object is already in the search list we are building. Don't add a duplicate pointer. - Release the reference just added by - _dl_map_object. */ - if (args.aux->l_initfini != NULL) - for (i = 1; args.aux->l_initfini[i] != NULL; ++i) - --args.aux->l_initfini[i]->l_opencount; - --args.aux->l_opencount; - + Just added by _dl_map_object. */ for (late = newp; late->unique; late = late->unique) if (late->unique->map == args.aux) break; diff --git a/elf/dl-load.c b/elf/dl-load.c index bb3a2e3187..80fbf65c6b 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -785,10 +785,6 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, free (realname); add_name_to_object (l, name); - if (l->l_initfini != NULL) - for (i = 1; l->l_initfini[i] != NULL; ++i) - ++l->l_initfini[i]->l_opencount; - ++l->l_opencount; return l; } @@ -821,7 +817,6 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, l = _dl_new_object (realname, name, l_type, loader); if (__builtin_expect (! l, 0)) LOSE (ENOMEM, N_("cannot create shared object descriptor")); - l->l_opencount = 1; /* Extract the remaining details we need from the ELF header and then read in the program header table. */ @@ -1467,7 +1462,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, /* If the requested name matches the soname of a loaded object, use that object. Elide this check for names that have not yet been opened. */ - if (l->l_opencount <= 0) + /* XXX Is this test still correct after the reference counter + handling rewrite? */ + if (l->l_opencount == 0) continue; if (!_dl_name_match_p (name, l)) { @@ -1487,11 +1484,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded, l->l_soname_added = 1; } - /* We have a match -- bump the reference count and return it. */ - if (l->l_initfini != NULL) - for (i = 1; l->l_initfini[i] != NULL; ++i) - ++l->l_initfini[i]->l_opencount; - ++l->l_opencount; + /* We have a match. */ return l; } diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index d9476817c3..1284e2b3dc 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -160,11 +160,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map) if (__builtin_expect (act < undef_map->l_reldepsmax, 1)) undef_map->l_reldeps[undef_map->l_reldepsact++] = map; - /* And increment the counter in the referenced object - and its dependencies. */ - if (map->l_initfini != NULL) - for (j = 1; map->l_initfini[j] != NULL; ++j) - ++map->l_initfini[j]->l_opencount; + /* And increment the counter in the referenced object. */ ++map->l_opencount; /* Display information if we are debugging. */ diff --git a/elf/dl-open.c b/elf/dl-open.c index 5c078d9be8..b278e2043e 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -238,7 +238,8 @@ dl_open_worker (void *a) return; } - if (new->l_searchlist.r_list) + /* It was already open. */ + if (new->l_searchlist.r_list != NULL) { /* Let the user know about the opencount. */ if (__builtin_expect (_dl_debug_files, 0)) @@ -259,13 +260,19 @@ dl_open_worker (void *a) if ((mode & RTLD_GLOBAL) && new->l_global == 0) (void) add_to_global (new); - /* It was already open. */ + /* Increment just the reference counter of the object. */ + ++new->l_opencount; + return; } /* 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) diff --git a/elf/loadtest.c b/elf/loadtest.c index 4a3c4c08be..25b27005f1 100644 --- a/elf/loadtest.c +++ b/elf/loadtest.c @@ -83,17 +83,23 @@ main (int argc, char *argv[]) int debug = argc > 1 && argv[1][0] != '\0'; int count = TEST_ROUNDS; int result = 0; + struct link_map *map; mtrace (); /* Just a seed. */ srandom (TEST_ROUNDS); + if (debug) + { + puts ("in the beginning"); + OUT; + } + while (count--) { int nr = random () % NTESTS; int index = tests[nr].index; - struct link_map *map; printf ("%4d: %4d: ", count + 1, nr); fflush (stdout); diff --git a/elf/rtld.c b/elf/rtld.c index ea5d7b5a3d..c44506acc4 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -550,7 +550,6 @@ of this helper program; chances are you did not intend to run this program.\n\ _dl_loaded->l_phdr = phdr; _dl_loaded->l_phnum = phent; _dl_loaded->l_entry = *user_entry; - _dl_loaded->l_opencount = 1; /* At this point we are in a bit of trouble. We would have to fill in the values for l_dev and l_ino. But in general we @@ -707,7 +706,7 @@ of this helper program; chances are you did not intend to run this program.\n\ { struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1, lt_library, 0, 0); - if (new_map->l_opencount == 1) + if (++new_map->l_opencount == 1) /* It is no duplicate. */ ++npreloads; } @@ -775,7 +774,7 @@ of this helper program; chances are you did not intend to run this program.\n\ { struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1, lt_library, 0, 0); - if (new_map->l_opencount == 1) + if (++new_map->l_opencount == 1) /* It is no duplicate. */ ++npreloads; } @@ -786,7 +785,7 @@ of this helper program; chances are you did not intend to run this program.\n\ char *p = strndupa (problem, file_size - (problem - file)); struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1, lt_library, 0, 0); - if (new_map->l_opencount == 1) + if (++new_map->l_opencount == 1) /* It is no duplicate. */ ++npreloads; } @@ -823,9 +822,14 @@ of this helper program; chances are you did not intend to run this program.\n\ HP_TIMING_DIFF (diff, start, stop); HP_TIMING_ACCUM_NT (load_time, diff); - /* Mark all objects as being in the global scope. */ + /* Mark all objects as being in the global scope and set the open + counter. */ for (i = _dl_loaded->l_searchlist.r_nlist; i > 0; ) - _dl_loaded->l_searchlist.r_list[--i]->l_global = 1; + { + --i; + _dl_loaded->l_searchlist.r_list[i]->l_global = 1; + ++_dl_loaded->l_searchlist.r_list[i]->l_opencount; + } #ifndef MAP_ANON /* We are done mapping things, so close the zero-fill descriptor. */ -- cgit 1.4.1