diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2008-11-05 12:32:42 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2008-11-05 12:32:42 +0000 |
| commit | be65c35a7eee6c68d1ef2e1734e039c15a654e5e (patch) | |
| tree | de0aafc8d7a89341529c42961d934db37f0f2027 /libexec | |
| parent | d558f5be79e0de6a7d89d7fac4648de2dddb0a54 (diff) | |
Notes
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/rtld-elf/rtld.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index bbf4bb9c93a4..9b4b01304ddb 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -106,8 +106,8 @@ static int load_needed_objects(Obj_Entry *); static int load_preload_objects(void); static Obj_Entry *load_object(const char *, const Obj_Entry *); static Obj_Entry *obj_from_addr(const void *); -static void objlist_call_fini(Objlist *); -static void objlist_call_init(Objlist *); +static void objlist_call_fini(Objlist *, int *lockstate); +static void objlist_call_init(Objlist *, int *lockstate); static void objlist_clear(Objlist *); static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); static void objlist_init(Objlist *); @@ -512,8 +512,8 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ - objlist_call_init(&initlist); lockstate = wlock_acquire(rtld_bind_lock); + objlist_call_init(&initlist, &lockstate); objlist_clear(&initlist); wlock_release(rtld_bind_lock, lockstate); @@ -1433,7 +1433,7 @@ obj_from_addr(const void *addr) * non-NULL fini functions. */ static void -objlist_call_fini(Objlist *list) +objlist_call_fini(Objlist *list, int *lockstate) { Objlist_Entry *elm; char *saved_msg; @@ -1443,6 +1443,7 @@ objlist_call_fini(Objlist *list) * call into the dynamic linker and overwrite it. */ saved_msg = errmsg_save(); + wlock_release(rtld_bind_lock, *lockstate); STAILQ_FOREACH(elm, list, link) { if (elm->obj->refcount == 0) { dbg("calling fini function for %s at %p", elm->obj->path, @@ -1452,6 +1453,7 @@ objlist_call_fini(Objlist *list) call_initfini_pointer(elm->obj, elm->obj->fini); } } + *lockstate = wlock_acquire(rtld_bind_lock); errmsg_restore(saved_msg); } @@ -1461,7 +1463,7 @@ objlist_call_fini(Objlist *list) * functions. */ static void -objlist_call_init(Objlist *list) +objlist_call_init(Objlist *list, int *lockstate) { Objlist_Entry *elm; char *saved_msg; @@ -1471,6 +1473,7 @@ objlist_call_init(Objlist *list) * call into the dynamic linker and overwrite it. */ saved_msg = errmsg_save(); + wlock_release(rtld_bind_lock, *lockstate); STAILQ_FOREACH(elm, list, link) { dbg("calling init function for %s at %p", elm->obj->path, (void *)elm->obj->init); @@ -1478,6 +1481,7 @@ objlist_call_init(Objlist *list) elm->obj->path); call_initfini_pointer(elm->obj, elm->obj->init); } + *lockstate = wlock_acquire(rtld_bind_lock); errmsg_restore(saved_msg); } @@ -1638,15 +1642,18 @@ static void rtld_exit(void) { Obj_Entry *obj; + int lockstate; + lockstate = wlock_acquire(rtld_bind_lock); dbg("rtld_exit()"); /* Clear all the reference counts so the fini functions will be called. */ for (obj = obj_list; obj != NULL; obj = obj->next) obj->refcount = 0; - objlist_call_fini(&list_fini); + objlist_call_fini(&list_fini, &lockstate); /* No need to remove the items from the list, since we are exiting. */ if (!libmap_disable) lm_fini(); + wlock_release(rtld_bind_lock, lockstate); } static void * @@ -1760,11 +1767,9 @@ dlclose(void *handle) if (root->refcount == 0) { /* * The object is no longer referenced, so we must unload it. - * First, call the fini functions with no locks held. + * First, call the fini functions. */ - wlock_release(rtld_bind_lock, lockstate); - objlist_call_fini(&list_fini); - lockstate = wlock_acquire(rtld_bind_lock); + objlist_call_fini(&list_fini, &lockstate); objlist_remove_unref(&list_fini); /* Finish cleaning up the newly-unreferenced objects. */ @@ -1872,10 +1877,8 @@ dlopen(const char *name, int mode) name); GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); - /* Call the init functions with no locks held. */ - wlock_release(rtld_bind_lock, lockstate); - objlist_call_init(&initlist); - lockstate = wlock_acquire(rtld_bind_lock); + /* Call the init functions. */ + objlist_call_init(&initlist, &lockstate); objlist_clear(&initlist); wlock_release(rtld_bind_lock, lockstate); return obj; |
