mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-28 00:21:52 +03:00
Update.
2000-10-24 Ulrich Drepper <drepper@redhat.com> 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.
This commit is contained in:
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
|||||||
|
2000-10-24 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
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 <aj@suse.de>
|
2000-10-24 Andreas Jaeger <aj@suse.de>
|
||||||
|
|
||||||
* sysdeps/mips/dl-machine.h: Partly revert patch from 2000-10-18.
|
* sysdeps/mips/dl-machine.h: Partly revert patch from 2000-10-18.
|
||||||
|
@ -49,6 +49,7 @@ _dl_close (void *_map)
|
|||||||
unsigned int nsearchlist;
|
unsigned int nsearchlist;
|
||||||
unsigned int nrellist;
|
unsigned int nrellist;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned int *new_opencount;
|
||||||
|
|
||||||
/* First see whether we can remove the object at all. */
|
/* First see whether we can remove the object at all. */
|
||||||
if (map->l_flags_1 & DF_1_NODELETE)
|
if (map->l_flags_1 & DF_1_NODELETE)
|
||||||
@ -61,9 +62,6 @@ _dl_close (void *_map)
|
|||||||
/* Acquire the lock. */
|
/* Acquire the lock. */
|
||||||
__libc_lock_lock (_dl_load_lock);
|
__libc_lock_lock (_dl_load_lock);
|
||||||
|
|
||||||
list = map->l_searchlist.r_list;
|
|
||||||
nsearchlist = map->l_searchlist.r_nlist;
|
|
||||||
|
|
||||||
/* Decrement the reference count. */
|
/* Decrement the reference count. */
|
||||||
if (map->l_opencount > 1 || map->l_type != lt_loaded)
|
if (map->l_opencount > 1 || map->l_type != lt_loaded)
|
||||||
{
|
{
|
||||||
@ -81,14 +79,46 @@ _dl_close (void *_map)
|
|||||||
"\n", NULL);
|
"\n", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < nsearchlist; ++i)
|
/* One decrement the object itself, not the dependencies. */
|
||||||
if (! (list[i]->l_flags_1 & DF_1_NODELETE))
|
--map->l_opencount;
|
||||||
--list[i]->l_opencount;
|
|
||||||
|
|
||||||
__libc_lock_unlock (_dl_load_lock);
|
__libc_lock_unlock (_dl_load_lock);
|
||||||
return;
|
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;
|
rellist = map->l_reldeps;
|
||||||
nrellist = map->l_reldepsact;
|
nrellist = map->l_reldepsact;
|
||||||
|
|
||||||
@ -96,7 +126,7 @@ _dl_close (void *_map)
|
|||||||
for (i = 0; i < nsearchlist; ++i)
|
for (i = 0; i < nsearchlist; ++i)
|
||||||
{
|
{
|
||||||
struct link_map *imap = map->l_initfini[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_info[DT_FINI] || imap->l_info[DT_FINI_ARRAY])
|
||||||
&& ! (imap->l_flags_1 & DF_1_NODELETE)
|
&& ! (imap->l_flags_1 & DF_1_NODELETE)
|
||||||
/* Skip any half-cooked objects that were never initialized. */
|
/* Skip any half-cooked objects that were never initialized. */
|
||||||
@ -126,19 +156,17 @@ _dl_close (void *_map)
|
|||||||
(*(void (*) (void)) ((void *) imap->l_addr
|
(*(void (*) (void)) ((void *) imap->l_addr
|
||||||
+ imap->l_info[DT_FINI]->d_un.d_ptr)) ();
|
+ 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. */
|
/* Notify the debugger we are about to remove some loaded objects. */
|
||||||
_r_debug.r_state = RT_DELETE;
|
_r_debug.r_state = RT_DELETE;
|
||||||
_dl_debug_state ();
|
_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
|
/* Check each element of the search list to see if all references to
|
||||||
it are gone. */
|
it are gone. */
|
||||||
for (i = 0; i < nsearchlist; ++i)
|
for (i = 0; i < nsearchlist; ++i)
|
||||||
|
@ -243,18 +243,7 @@ _dl_map_object_deps (struct link_map *map,
|
|||||||
dtail = newp;
|
dtail = newp;
|
||||||
++nduplist;
|
++nduplist;
|
||||||
|
|
||||||
if (dep->l_reserved)
|
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
|
|
||||||
{
|
{
|
||||||
/* Append DEP to the unique list. */
|
/* Append DEP to the unique list. */
|
||||||
newp->done = 0;
|
newp->done = 0;
|
||||||
@ -363,13 +352,7 @@ _dl_map_object_deps (struct link_map *map,
|
|||||||
|
|
||||||
/* This object is already in the search list we
|
/* This object is already in the search list we
|
||||||
are building. Don't add a duplicate pointer.
|
are building. Don't add a duplicate pointer.
|
||||||
Release the reference just added by
|
Just added by _dl_map_object. */
|
||||||
_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;
|
|
||||||
|
|
||||||
for (late = newp; late->unique; late = late->unique)
|
for (late = newp; late->unique; late = late->unique)
|
||||||
if (late->unique->map == args.aux)
|
if (late->unique->map == args.aux)
|
||||||
break;
|
break;
|
||||||
|
@ -785,10 +785,6 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
|
|||||||
free (realname);
|
free (realname);
|
||||||
add_name_to_object (l, name);
|
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;
|
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);
|
l = _dl_new_object (realname, name, l_type, loader);
|
||||||
if (__builtin_expect (! l, 0))
|
if (__builtin_expect (! l, 0))
|
||||||
LOSE (ENOMEM, N_("cannot create shared object descriptor"));
|
LOSE (ENOMEM, N_("cannot create shared object descriptor"));
|
||||||
l->l_opencount = 1;
|
|
||||||
|
|
||||||
/* Extract the remaining details we need from the ELF header
|
/* Extract the remaining details we need from the ELF header
|
||||||
and then read in the program header table. */
|
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,
|
/* If the requested name matches the soname of a loaded object,
|
||||||
use that object. Elide this check for names that have not
|
use that object. Elide this check for names that have not
|
||||||
yet been opened. */
|
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;
|
continue;
|
||||||
if (!_dl_name_match_p (name, l))
|
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;
|
l->l_soname_added = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have a match -- bump the reference count and return it. */
|
/* We have a match. */
|
||||||
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;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,11 +160,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map)
|
|||||||
if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
|
if (__builtin_expect (act < undef_map->l_reldepsmax, 1))
|
||||||
undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
|
undef_map->l_reldeps[undef_map->l_reldepsact++] = map;
|
||||||
|
|
||||||
/* And increment the counter in the referenced object
|
/* 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;
|
|
||||||
++map->l_opencount;
|
++map->l_opencount;
|
||||||
|
|
||||||
/* Display information if we are debugging. */
|
/* Display information if we are debugging. */
|
||||||
|
@ -238,7 +238,8 @@ dl_open_worker (void *a)
|
|||||||
return;
|
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. */
|
/* Let the user know about the opencount. */
|
||||||
if (__builtin_expect (_dl_debug_files, 0))
|
if (__builtin_expect (_dl_debug_files, 0))
|
||||||
@ -259,13 +260,19 @@ dl_open_worker (void *a)
|
|||||||
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
|
||||||
(void) add_to_global (new);
|
(void) add_to_global (new);
|
||||||
|
|
||||||
/* It was already open. */
|
/* Increment just the reference counter of the object. */
|
||||||
|
++new->l_opencount;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load that object's dependencies. */
|
/* Load that object's dependencies. */
|
||||||
_dl_map_object_deps (new, NULL, 0, 0);
|
_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. */
|
/* So far, so good. Now check the versions. */
|
||||||
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
|
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
|
||||||
if (new->l_searchlist.r_list[i]->l_versions == NULL)
|
if (new->l_searchlist.r_list[i]->l_versions == NULL)
|
||||||
|
@ -83,17 +83,23 @@ main (int argc, char *argv[])
|
|||||||
int debug = argc > 1 && argv[1][0] != '\0';
|
int debug = argc > 1 && argv[1][0] != '\0';
|
||||||
int count = TEST_ROUNDS;
|
int count = TEST_ROUNDS;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
struct link_map *map;
|
||||||
|
|
||||||
mtrace ();
|
mtrace ();
|
||||||
|
|
||||||
/* Just a seed. */
|
/* Just a seed. */
|
||||||
srandom (TEST_ROUNDS);
|
srandom (TEST_ROUNDS);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
puts ("in the beginning");
|
||||||
|
OUT;
|
||||||
|
}
|
||||||
|
|
||||||
while (count--)
|
while (count--)
|
||||||
{
|
{
|
||||||
int nr = random () % NTESTS;
|
int nr = random () % NTESTS;
|
||||||
int index = tests[nr].index;
|
int index = tests[nr].index;
|
||||||
struct link_map *map;
|
|
||||||
|
|
||||||
printf ("%4d: %4d: ", count + 1, nr);
|
printf ("%4d: %4d: ", count + 1, nr);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
|
16
elf/rtld.c
16
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_phdr = phdr;
|
||||||
_dl_loaded->l_phnum = phent;
|
_dl_loaded->l_phnum = phent;
|
||||||
_dl_loaded->l_entry = *user_entry;
|
_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
|
/* 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
|
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,
|
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
|
||||||
lt_library, 0, 0);
|
lt_library, 0, 0);
|
||||||
if (new_map->l_opencount == 1)
|
if (++new_map->l_opencount == 1)
|
||||||
/* It is no duplicate. */
|
/* It is no duplicate. */
|
||||||
++npreloads;
|
++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,
|
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
|
||||||
lt_library, 0, 0);
|
lt_library, 0, 0);
|
||||||
if (new_map->l_opencount == 1)
|
if (++new_map->l_opencount == 1)
|
||||||
/* It is no duplicate. */
|
/* It is no duplicate. */
|
||||||
++npreloads;
|
++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));
|
char *p = strndupa (problem, file_size - (problem - file));
|
||||||
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
|
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
|
||||||
lt_library, 0, 0);
|
lt_library, 0, 0);
|
||||||
if (new_map->l_opencount == 1)
|
if (++new_map->l_opencount == 1)
|
||||||
/* It is no duplicate. */
|
/* It is no duplicate. */
|
||||||
++npreloads;
|
++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_DIFF (diff, start, stop);
|
||||||
HP_TIMING_ACCUM_NT (load_time, diff);
|
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; )
|
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
|
#ifndef MAP_ANON
|
||||||
/* We are done mapping things, so close the zero-fill descriptor. */
|
/* We are done mapping things, so close the zero-fill descriptor. */
|
||||||
|
Reference in New Issue
Block a user