[PATCH 7/7] xfree86/loader: add back silly reference counting. (and move it a layer higher)

Michal Suchanek hramrach at gmail.com
Mon Jul 23 08:14:33 PDT 2012


ab7f057ce removes reference counting of loaded objects.

However, DuplicateModule is used extensively in X server to create
copies of modules. Without the reference counting layer DuplicateModule
cannot call LoaderOpen since at least glibc will happily realod
(possibly different) object from disk, and DuplicateModule does not
perform version checks nor module initialization.

To make it possible to unload module safely a duplicate count should be
tracked so that duplicated modules that are possibly still in use
somewhere are not uninitialized. Calling UnloadModule on a duplicated
module has no effect but no error is returned as the loader interface
does not allow for that.

Signed-off-by: Michal Suchanek <hramrach at gmail.com>
---
 hw/xfree86/loader/loaderProcs.h |    2 ++
 hw/xfree86/loader/loadmod.c     |   30 ++++++++++++++++++------------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/hw/xfree86/loader/loaderProcs.h b/hw/xfree86/loader/loaderProcs.h
index 5028554..973428b 100644
--- a/hw/xfree86/loader/loaderProcs.h
+++ b/hw/xfree86/loader/loaderProcs.h
@@ -66,6 +66,8 @@ typedef struct module_desc {
     ModuleTearDownProc TearDownProc;
     void *TearDownData;         /* returned from SetupProc */
     const XF86ModuleVersionInfo *VersionInfo;
+    struct module_desc *original;
+    int duplicate_count;
 } ModuleDesc, *ModuleDescPtr;
 
 /* External API for the loader */
diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
index 8a48adb..aee2f68 100644
--- a/hw/xfree86/loader/loadmod.c
+++ b/hw/xfree86/loader/loadmod.c
@@ -93,8 +93,6 @@ const ModuleVersions LoaderVersionInfo = {
     ABI_FONT_VERSION
 };
 
-static int ModuleDuplicated[] = { };
-
 static void
 FreeStringList(char **paths)
 {
@@ -803,8 +801,11 @@ NewModuleDesc(const char *name)
     return mdp;
 }
 
-/* An advisory function. When true is returned unloading the module should be
- * safe. Uload can be attempted nonetheless. */
+static ModuleDescPtr ModuleGetOriginal(ModuleDescPtr mod)
+{
+    return (mod->original ? mod->original : mod);
+}
+
 int CanUnloadModule(ModuleDescPtr mod)
 {
     if (IsBuiltinModule(mod))
@@ -829,10 +830,11 @@ DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
         return NULL;
 
     ret->handle = mod->handle;
-
+    /* some code may check the procs are the same */
     ret->SetupProc = mod->SetupProc;
     ret->TearDownProc = mod->TearDownProc;
-    ret->TearDownData = ModuleDuplicated;
+    ret->original = ModuleGetOriginal(mod);
+    ret->original->duplicate_count++;
     ret->child = DuplicateModule(mod->child, ret);
     ret->sib = DuplicateModule(mod->sib, parent);
     ret->parent = parent;
@@ -1106,24 +1108,26 @@ Bool IsBuiltinModule(ModuleDescPtr mod)
 /* Is given module duplicate of another? */
 Bool IsDuplicateModule(ModuleDescPtr mod)
 {
-    return (mod->TearDownData == ModuleDuplicated);
+    return (mod->original != NULL);
 }
 
 /* Do duplicates of given module exist? */
 Bool IsDuplicated(ModuleDescPtr mod)
 {
-    /* cannot tell until reference counting is added */
-    return TRUE;
+    return (mod->duplicate_count > 0);
 }
 
 static void
 UnloadModuleOrDriver(ModuleDescPtr mod)
 {
-    if (IsBuiltinModule(mod))
+    if (mod == NULL || mod->name == NULL)
         return;
 
-    if (mod == NULL || mod->name == NULL)
+    if (!CanUnloadModule(mod)) {
+        if (IsDuplicated(mod))
+            xf86MsgVerb(X_WARNING, 3, "Cannot unload duplicated module: \"%s\"\n", mod->name);
         return;
+    }
 
     if (mod->parent)
         LogMessageVerbSigSafe(X_INFO, 3, "UnloadSubModule: \"%s\"\n",
@@ -1132,7 +1136,9 @@ UnloadModuleOrDriver(ModuleDescPtr mod)
         LogMessageVerbSigSafe(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
 
     RemoveChild(mod);
-    if (!IsDuplicateModule(mod)) {
+    if (IsDuplicateModule(mod)) {
+            ModuleGetOriginal(mod)->duplicate_count--;
+    } else {
         if ((mod->TearDownProc) && (mod->TearDownData))
             mod->TearDownProc(mod->TearDownData);
         LoaderUnload(mod->name, mod->handle);
-- 
1.7.10.4



More information about the xorg-devel mailing list