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
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)
return NULL;
}
+static
void ctf_text_close_trace(struct trace_descriptor *td)
{
struct ctf_text_stream_pos *pos =
g_free(pos);
}
+static
void __attribute__((constructor)) ctf_text_init(void)
{
int ret;
assert(!ret);
}
-/* TODO: finalize */
+static
+void __attribute__((destructor)) ctf_text_exit(void)
+{
+ bt_unregister_format(&ctf_text_format);
+}
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)
{
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();
}