/* module.c : Implementation of the module loading/unloading mechanism. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#include <lttv/module.h>
#include <gmodule.h>
static void init();
-static finish_destroy();
+static void finish_destroy();
static void module_release(LttvModule *m);
LttvModule *m;
GPtrArray *modules;
-
+ GPtrArray **modules_ptr = &modules; /* for strict aliasing */
guint i;
char *key;
+ char **key_ptr = &key; /* for strict aliasing */
for(i = 0 ; i < l->modules->len ; i++) {
m = (LttvModule *)(l->modules->pdata[i]);
g_hash_table_lookup_extended(modules_by_name, m->info.name,
- (gpointer *)&key, (gpointer *)&modules);
+ (gpointer *)key_ptr, (gpointer *)modules_ptr);
g_assert(modules != NULL);
g_ptr_array_remove(modules, m);
if(modules->len == 0) {
static LttvLibrary *library_load(char *name, GError **error)
{
- GModule *gm;
+ GModule *gm = NULL;
int i, nb;
- char *path, *pathname;
+ /* path is always initialized, checked */
+ char *path = NULL, *pathname;
LttvLibrary *l;
module_chain = NULL;
module_next = &module_chain;
gm = g_module_open(pathname,0);
- g_free(pathname);
+ g_free(pathname);
if(gm != NULL) break;
LttvLibrary *lttv_library_load(char *name, GError **error)
{
- LttvLibrary *l = library_load(name, error);
- l->info.load_count++;
+ LttvLibrary *l = library_load(name, error);
+ if(l != NULL) l->info.load_count++;
return l;
}
-
-static void library_unload(LttvLibrary *l)
+/* Returns < 0 if still in use, 0 if freed */
+static gint library_unload(LttvLibrary *l)
{
- guint i, len;
+ guint i;
GModule *gm;
if(l->locked_loaded > 0) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: locked loaded",
l->info.name);
- return;
+ return 1;
}
if(l->info.load_count > 0) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "Unload library %s: load count %d",
l->info.name, l->info.load_count);
- return;
+ return l->info.load_count;
}
/* Check if all its modules have been released */
if(m->info.use_count > 0) {
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO,"Unload library %s: module %s used",
l->info.name, m->info.name);
- return;
+ return 1;
}
}
/* insure that module.c will be finalized */
finish_destroy();
+ return 0;
}
-void lttv_library_unload(LttvLibrary *l)
+gint lttv_library_unload(LttvLibrary *l)
{
- l->info.load_count--;
- library_unload(l);
+ /* In the case where we wait for a module to release, the load count is 0
+ * and should not be decremented. */
+ if(l->info.load_count != 0) {
+ l->info.load_count--;
+ return l->info.load_count;
+ } else {
+ library_unload(l);
+ return 0;
+ }
}
}
-static void library_unlock_loaded(LttvLibrary *l)
+static gint library_unlock_loaded(LttvLibrary *l)
{
l->locked_loaded--;
- library_unload(l);
+ return library_unload(l);
}
}
-static finish_destroy()
+static void finish_destroy()
{
guint i;
locked_libraries = g_new(LttvLibrary *, nb);
for(i = 0 ; i < nb ; i++) {
+ //g_assert(nb == libraries->len);
l = (LttvLibrary *)(libraries->pdata[i]);
locked_libraries[i] = l;
library_lock_loaded(l);
m = (LttvModule *)(l->modules->pdata[j]);
while(m->info.require_count > 0) lttv_module_release(m);
}
- while(l->info.load_count > 0) lttv_library_unload(l);
+ if(library_unlock_loaded(l) > 0)
+ while(lttv_library_unload(l) > 0);
+
+ /* If the number of librairies loaded have changed, restart from the
+ * beginning */
+ if(nb != libraries->len) {
+ i = 0;
+ nb = libraries->len;
+ }
+
}
for(i = 0 ; i < nb ; i++) {