Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ld.elf_so Refine locking scheme around init/fini to ...



details:   https://anonhg.NetBSD.org/src/rev/963cf488eb3a
branches:  trunk
changeset: 763627:963cf488eb3a
user:      joerg <joerg%NetBSD.org@localhost>
date:      Mon Mar 28 00:37:40 2011 +0000

description:
Refine locking scheme around init/fini to not hold the exclusive lock.
Use a simple generation count instead and restart looking for work if it
changed (e.g. due to an dlopen call from an init function).
Leave the possible dlclose() race for now.

diffstat:

 libexec/ld.elf_so/rtld.c |  72 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 54 insertions(+), 18 deletions(-)

diffs (140 lines):

diff -r 6f745955cd06 -r 963cf488eb3a libexec/ld.elf_so/rtld.c
--- a/libexec/ld.elf_so/rtld.c  Mon Mar 28 00:14:51 2011 +0000
+++ b/libexec/ld.elf_so/rtld.c  Mon Mar 28 00:37:40 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rtld.c,v 1.146 2011/03/27 22:20:51 joerg Exp $  */
+/*     $NetBSD: rtld.c,v 1.147 2011/03/28 00:37:40 joerg Exp $  */
 
 /*
  * Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: rtld.c,v 1.146 2011/03/27 22:20:51 joerg Exp $");
+__RCSID("$NetBSD: rtld.c,v 1.147 2011/03/28 00:37:40 joerg Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -89,6 +89,7 @@
 Obj_Entry       _rtld_objself; /* The dynamic linker shared object */
 u_int          _rtld_objcount; /* Number of objects in _rtld_objlist */
 u_int          _rtld_objloads; /* Number of objects loaded in _rtld_objlist */
+u_int          _rtld_objgen;   /* Generation count for _rtld_objlist */
 const char     _rtld_path[] = _PATH_RTLD;
 
 /* Initialize a fake symbol for resolving undefined weak references. */
@@ -139,9 +140,13 @@
        Objlist_Entry *elm;
        Objlist finilist;
        Obj_Entry *obj;
+       void (*fini)(void);
+       u_int cur_objgen;
 
        dbg(("_rtld_call_fini_functions(%d)", force));
 
+restart:
+       cur_objgen = ++_rtld_objgen;
        SIMPLEQ_INIT(&finilist);
        _rtld_initlist_tsort(&finilist, 1);
 
@@ -157,10 +162,20 @@
                dbg (("calling fini function %s at %p",  obj->path,
                    (void *)obj->fini));
                obj->fini_called = 1;
-               /* XXXlocking: exit point */
-               _rtld_mutex_may_recurse = true;
-               (*obj->fini)();
-               _rtld_mutex_may_recurse = false;
+               /*
+                * XXX This can race against a concurrent dlclose().
+                * XXX In that case, the object could be unmapped before
+                * XXX the fini() call is done.
+                */
+               fini = obj->fini;
+               _rtld_exclusive_exit();
+               (*fini)();
+               _rtld_exclusive_enter();
+               if (_rtld_objgen != cur_objgen) {
+                       dbg(("restarting fini iteration"));
+                       _rtld_objlist_clear(&finilist);
+                       goto restart;
+               }
        }
 
        /* Second pass: objects marked with DF_1_INITFIRST. */
@@ -175,10 +190,16 @@
                dbg (("calling fini function %s at %p (DF_1_INITFIRST)",
                    obj->path, (void *)obj->fini));
                obj->fini_called = 1;
-               /* XXXlocking: exit point */
-               _rtld_mutex_may_recurse = true;
-               (*obj->fini)();
-               _rtld_mutex_may_recurse = false;
+               /* XXX See above for the race condition here */
+               fini = obj->fini;
+               _rtld_exclusive_exit();
+               (*fini)();
+               _rtld_exclusive_enter();
+               if (_rtld_objgen != cur_objgen) {
+                       dbg(("restarting fini iteration"));
+                       _rtld_objlist_clear(&finilist);
+                       goto restart;
+               }
        }
 
         _rtld_objlist_clear(&finilist);
@@ -190,8 +211,13 @@
        Objlist_Entry *elm;
        Objlist initlist;
        Obj_Entry *obj;
+       void (*init)(void);
+       u_int cur_objgen;
 
        dbg(("_rtld_call_init_functions()"));
+
+restart:
+       cur_objgen = ++_rtld_objgen;
        SIMPLEQ_INIT(&initlist);
        _rtld_initlist_tsort(&initlist, 0);
 
@@ -204,10 +230,15 @@
                dbg (("calling init function %s at %p (DF_1_INITFIRST)",
                    obj->path, (void *)obj->init));
                obj->init_called = 1;
-               /* XXXlocking: exit point */
-               _rtld_mutex_may_recurse = true;
-               (*obj->init)();
-               _rtld_mutex_may_recurse = false;
+               init = obj->init;
+               _rtld_exclusive_exit();
+               (*init)();
+               _rtld_exclusive_enter();
+               if (_rtld_objgen != cur_objgen) {
+                       dbg(("restarting init iteration"));
+                       _rtld_objlist_clear(&initlist);
+                       goto restart;
+               }
        }
 
        /* Second pass: all other objects. */
@@ -219,10 +250,15 @@
                dbg (("calling init function %s at %p",  obj->path,
                    (void *)obj->init));
                obj->init_called = 1;
-               /* XXXlocking: exit point */
-               _rtld_mutex_may_recurse = true;
-               (*obj->init)();
-               _rtld_mutex_may_recurse = false;
+               init = obj->init;
+               _rtld_exclusive_exit();
+               (*init)();
+               _rtld_exclusive_enter();
+               if (_rtld_objgen != cur_objgen) {
+                       dbg(("restarting init iteration"));
+                       _rtld_objlist_clear(&initlist);
+                       goto restart;
+               }
        }
 
         _rtld_objlist_clear(&initlist);



Home | Main Index | Thread Index | Old Index