From 95febab3a71bc0d64d9ebd0ce08787d96a51d475 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 16 Oct 2012 18:04:39 -0400 Subject: [PATCH] plugins: implement plugin unregister Signed-off-by: Mathieu Desnoyers --- formats/bt-dummy/bt-dummy.c | 6 ++++- formats/ctf-text/ctf-text.c | 13 +++++++--- formats/ctf/ctf.c | 7 ++++- include/babeltrace/format.h | 2 +- lib/registry.c | 52 ++++++++++++++++++++++++++++++++----- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/formats/bt-dummy/bt-dummy.c b/formats/bt-dummy/bt-dummy.c index 2e94421f..94edc3be 100644 --- a/formats/bt-dummy/bt-dummy.c +++ b/formats/bt-dummy/bt-dummy.c @@ -74,4 +74,8 @@ void __attribute__((constructor)) bt_dummy_init(void) assert(!ret); } -/* TODO: finalize */ +static +void __attribute__((destructor)) bt_dummy_exit(void) +{ + bt_unregister_format(&bt_dummy_format); +} diff --git a/formats/ctf-text/ctf-text.c b/formats/ctf-text/ctf-text.c index 40f2f008..cbf074e0 100644 --- a/formats/ctf-text/ctf-text.c +++ b/formats/ctf-text/ctf-text.c @@ -78,10 +78,11 @@ enum bt_loglevel { BT_LOGLEVEL_DEBUG = 14, }; - +static struct trace_descriptor *ctf_text_open_trace(const char *path, int flags, void (*packet_seek)(struct stream_pos *pos, size_t index, int whence), FILE *metadata_fp); +static void ctf_text_close_trace(struct trace_descriptor *descriptor); static @@ -545,7 +546,7 @@ error: return ret; } - +static struct trace_descriptor *ctf_text_open_trace(const char *path, int flags, void (*packet_seek)(struct stream_pos *pos, size_t index, int whence), FILE *metadata_fp) @@ -582,6 +583,7 @@ error: return NULL; } +static void ctf_text_close_trace(struct trace_descriptor *td) { struct ctf_text_stream_pos *pos = @@ -590,6 +592,7 @@ void ctf_text_close_trace(struct trace_descriptor *td) g_free(pos); } +static void __attribute__((constructor)) ctf_text_init(void) { int ret; @@ -599,4 +602,8 @@ void __attribute__((constructor)) ctf_text_init(void) assert(!ret); } -/* TODO: finalize */ +static +void __attribute__((destructor)) ctf_text_exit(void) +{ + bt_unregister_format(&ctf_text_format); +} diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index e59e3573..b07c45c3 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -1935,6 +1935,7 @@ void ctf_set_handle(struct trace_descriptor *descriptor, td->handle = handle; } +static void __attribute__((constructor)) ctf_init(void) { int ret; @@ -1944,4 +1945,8 @@ void __attribute__((constructor)) ctf_init(void) assert(!ret); } -/* TODO: finalize */ +static +void __attribute__((destructor)) ctf_exit(void) +{ + bt_unregister_format(&ctf_format); +} diff --git a/include/babeltrace/format.h b/include/babeltrace/format.h index ef340da1..5de52fcf 100644 --- a/include/babeltrace/format.h +++ b/include/babeltrace/format.h @@ -77,8 +77,8 @@ struct format { extern struct format *bt_lookup_format(bt_intern_str qname); extern void bt_fprintf_format_list(FILE *fp); extern int bt_register_format(struct format *format); +extern void bt_unregister_format(struct format *format); -/* TBD: format unregistration */ #ifdef __cplusplus } #endif diff --git a/lib/registry.c b/lib/registry.c index 3cef63d9..4d09e5db 100644 --- a/lib/registry.c +++ b/lib/registry.c @@ -29,16 +29,35 @@ struct walk_data { int iter; }; -static int init_done; -void __attribute__((constructor)) format_init(void); -void __attribute__((destructor)) format_finalize(void); - /* * Format registry hash table contains the registered formats. Format * registration is typically performed by a format plugin. - * TODO: support plugin unload (unregistration of formats). */ -GHashTable *format_registry; +static GHashTable *format_registry; +static int format_refcount; +static int init_done; + +static __attribute__((constructor)) void format_init(void); + +static +void format_refcount_inc(void) +{ + format_refcount++; +} + +static +void format_cleanup(void) +{ + if (format_registry) + g_hash_table_destroy(format_registry); +} + +static +void format_refcount_dec(void) +{ + if (!--format_refcount) + format_cleanup(); +} struct format *bt_lookup_format(bt_intern_str name) { @@ -87,22 +106,41 @@ int bt_register_format(struct format *format) if (bt_lookup_format(format->name)) return -EEXIST; + format_refcount_inc(); g_hash_table_insert(format_registry, (gpointer) (unsigned long) format->name, format); return 0; } +void bt_unregister_format(struct format *format) +{ + assert(bt_lookup_format(format->name)); + g_hash_table_remove(format_registry, + (gpointer) (unsigned long) format->name); + format_refcount_dec(); +} + +/* + * We cannot assume that the constructor and destructor order will be + * right: another library might be loaded before us, and initialize us + * from bt_register_format(). This is why we use a reference count to + * handle cleanup of this module. The format_finalize destructor + * refcount decrement matches format_init refcount increment. + */ +static __attribute__((constructor)) void format_init(void) { if (init_done) return; + format_refcount_inc(); format_registry = g_hash_table_new(g_direct_hash, g_direct_equal); assert(format_registry); init_done = 1; } +static __attribute__((destructor)) void format_finalize(void) { - g_hash_table_destroy(format_registry); + format_refcount_dec(); } -- 2.34.1