]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Threads: add a callback for thread shutdown
authorMaria Matejka <mq@ucw.cz>
Thu, 23 Jan 2025 12:15:43 +0000 (13:15 +0100)
committerMaria Matejka <mq@ucw.cz>
Mon, 10 Mar 2025 10:51:28 +0000 (11:51 +0100)
lib/io-loop.h
sysdep/unix/io-loop.c

index d2c27754cd2910becc50a1897be92725ea95bcc6..d19d3fe5ab6258cc05a6ab667dce5d88068f5e52 100644 (file)
@@ -13,6 +13,7 @@
 #include "lib/resource.h"
 #include "lib/event.h"
 #include "lib/socket.h"
+#include "lib/tlists.h"
 
 extern struct birdloop main_birdloop;
 
@@ -101,4 +102,16 @@ extern const struct thread_group_config thread_group_config_default_worker, thre
 
 void thread_group_finalize_config(void);
 
+/* What if a thread ends */
+struct bird_thread_end_callback {
+  TLIST_NODE(bird_thread_end, struct bird_thread_end_callback) n;
+
+  /* The hook runs locked on the resource level. DO NOT LOCK ANYTHING FROM THERE.
+   * If you need to lock, schedule an event from this hook. */
+  void (*hook)(struct bird_thread_end_callback *);
+};
+
+void bird_thread_end_register(struct bird_thread_end_callback *);
+void bird_thread_end_unregister(struct bird_thread_end_callback *);
+
 #endif /* _BIRD_IO_LOOP_H_ */
index a9c4b3c5a1de6acf83e078b403aaeacff91c61d6..82f9782d5dc5dc384f382d09206c638a5b7d9e5f 100644 (file)
@@ -642,6 +642,43 @@ static _Thread_local struct bird_thread *this_thread;
 
 static void bird_thread_busy_set(struct thread_group_private *, int val);
 
+#define TLIST_PREFIX bird_thread_end
+#define TLIST_TYPE struct bird_thread_end_callback
+#define TLIST_ITEM n
+#define TLIST_WANT_ADD_TAIL
+#define TLIST_WALK
+#include "lib/tlists.h"
+
+struct bird_thread_end_private {
+  DOMAIN(resource) lock;
+  struct bird_thread_end_private **locked_at;
+  TLIST_LIST(bird_thread_end) cbs;
+};
+
+typedef union bird_thread_end {
+  DOMAIN(resource) lock;
+  struct bird_thread_end_private priv;
+} bird_thread_end;
+
+static bird_thread_end bird_thread_end_public;
+
+LOBJ_UNLOCK_CLEANUP(bird_thread_end, resource);
+#define BIRD_THREAD_END_LOCKED(p)      LOBJ_LOCKED(&bird_thread_end_public, p, bird_thread_end, resource)
+
+void
+bird_thread_end_register(struct bird_thread_end_callback *btec)
+{
+  BIRD_THREAD_END_LOCKED(p)
+    bird_thread_end_add_tail(&p->cbs, btec);
+}
+
+void
+bird_thread_end_unregister(struct bird_thread_end_callback *btec)
+{
+  BIRD_THREAD_END_LOCKED(p)
+    bird_thread_end_rem_node(&p->cbs, btec);
+}
+
 static void
 birdloop_set_thread(struct birdloop *loop, struct bird_thread *thr)
 {
@@ -1256,6 +1293,11 @@ bird_thread_shutdown(void * _ UNUSED)
   ev_run_list(&this_thread->priority_events);
   memset(&this_thread->priority_events, 0xa5, sizeof(this_thread->priority_events));
 
+  /* Run thread-stop hooks */
+  BIRD_THREAD_END_LOCKED(p)
+    WALK_TLIST(bird_thread_end, n, &p->cbs)
+      n->hook(n);
+
   /* Drop loops including the thread dropper itself */
   while (!EMPTY_TLIST(birdloop, &thr->loops))
   {
@@ -1722,6 +1764,10 @@ birdloop_init(void)
   DOMAIN_SETUP(attrs, default_thread_group->priv.lock, "Startup Thread Group", NULL);
   thread_group_add_tail(&global_thread_group_list, default_thread_group);
 
+  bird_thread_end_public = (bird_thread_end) {
+    .lock = DOMAIN_NEW(resource),
+  };
+
   wakeup_init(main_birdloop.thread);
 
   main_birdloop.time.domain = the_bird_domain.the_bird;