-extern void afb_hook_evt_create(const char *evt);
-extern void afb_hook_evt_push_before(const char *evt);
-extern int afb_hook_evt_push_after(const char *evt, int result);
-extern void afb_hook_evt_broadcast_before(const char *evt);
-extern int afb_hook_evt_broadcast_after(const char *evt, int result);
-extern void afb_hook_evt_drop(const char *evt);
-extern void afb_hook_evt_name(const char *evt);
-
-extern int afb_hook_flags_evt(const char *name);
-extern struct afb_hook_evt *afb_hook_create_evt(const char *name, int flags, struct afb_hook_evt_itf *itf, void *closure);
-extern struct afb_hook_evt *afb_hook_addref_evt(struct afb_hook_evt *hook);
-extern void afb_hook_unref_evt(struct afb_hook_evt *hook);
-#endif
+/******************************************************************************
+ * section: hooks for tracing globals (global)
+ *****************************************************************************/
+
+#define _HOOK_GLOBAL_(what,...) \
+ struct afb_hook_global *hook; \
+ struct afb_hookid hookid; \
+ pthread_rwlock_rdlock(&rwlock); \
+ init_hookid(&hookid); \
+ hook = list_of_global_hooks; \
+ while (hook) { \
+ if (hook->refcount \
+ && hook->itf->hook_global_##what \
+ && (hook->flags & afb_hook_flag_global_##what) != 0) { \
+ hook->itf->hook_global_##what(hook->closure, &hookid, __VA_ARGS__); \
+ } \
+ hook = hook->next; \
+ } \
+ pthread_rwlock_unlock(&rwlock);
+
+static void afb_hook_global_vverbose(int level, const char *file, int line, const char *func, const char *fmt, va_list args)
+{
+ _HOOK_GLOBAL_(vverbose, level, file ?: "?", line, func ?: "?", fmt ?: "", args);
+}
+
+/******************************************************************************
+ * section: hooking globals (global)
+ *****************************************************************************/
+
+static void update_global()
+{
+ struct afb_hook_global *hook;
+ int flags = 0;
+
+ pthread_rwlock_rdlock(&rwlock);
+ hook = list_of_global_hooks;
+ while (hook) {
+ if (hook->refcount)
+ flags = hook->flags;
+ hook = hook->next;
+ }
+ verbose_observer = (flags & afb_hook_flag_global_vverbose) ? afb_hook_global_vverbose : NULL;
+ pthread_rwlock_unlock(&rwlock);
+}
+
+struct afb_hook_global *afb_hook_create_global(int flags, struct afb_hook_global_itf *itf, void *closure)
+{
+ struct afb_hook_global *hook;
+
+ /* alloc the result */
+ hook = calloc(1, sizeof *hook);
+ if (hook == NULL)
+ return NULL;
+
+ /* initialise the rest */
+ hook->refcount = 1;
+ hook->flags = flags;
+ hook->itf = itf ? itf : &hook_global_default_itf;
+ hook->closure = closure;
+
+ /* record the hook */
+ pthread_mutex_lock(&mutex);
+ hook->next = list_of_global_hooks;
+ list_of_global_hooks = hook;
+ pthread_mutex_unlock(&mutex);
+
+ /* update hooking */
+ update_global();
+
+ /* returns it */
+ return hook;
+}
+
+struct afb_hook_global *afb_hook_addref_global(struct afb_hook_global *hook)
+{
+ __atomic_add_fetch(&hook->refcount, 1, __ATOMIC_RELAXED);
+ return hook;
+}
+
+static void hook_clean_global()
+{
+ struct afb_hook_global **prv, *hook, *head;
+
+ if (pthread_rwlock_trywrlock(&rwlock) == 0) {
+ /* unlink under mutex */
+ head = NULL;
+ pthread_mutex_lock(&mutex);
+ prv = &list_of_global_hooks;
+ while ((hook = *prv)) {
+ if (hook->refcount)
+ prv = &(*prv)->next;
+ else {
+ *prv = hook->next;
+ hook->next = head;
+ head = hook;
+ }
+ }
+ pthread_mutex_unlock(&mutex);
+ pthread_rwlock_unlock(&rwlock);
+
+ /* free found hooks */
+ while((hook = head)) {
+ head = hook->next;
+ free(hook);
+ }
+ }
+}
+
+void afb_hook_unref_global(struct afb_hook_global *hook)
+{
+ if (hook && !__atomic_sub_fetch(&hook->refcount, 1, __ATOMIC_RELAXED)) {
+ /* update hooking */
+ update_global();
+ hook_clean_global();
+ }
+}
+
+#endif /* WITH_AFB_HOOK *******************************************************/