]> 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>
Wed, 19 Feb 2025 08:42:45 +0000 (09:42 +0100)
lib/io-loop.h
sysdep/unix/io-loop.c

index 9f08420a60227bb4e545eeebe18ffd776a4616b3..ce9002057f1fd8ab8a0740baeca252486d7d1be4 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;
 
@@ -73,4 +74,16 @@ void birdloop_remove_socket(struct birdloop *, struct birdsock *);
 
 void birdloop_init(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 5332a538b3de22521dff7ae134eb44d2c2cc5e4a..75d863757366386b187af4dd3549da9084573200 100644 (file)
@@ -595,6 +595,43 @@ struct birdloop_pickup_group {
 
 static _Thread_local struct bird_thread *this_thread;
 
+#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, struct birdloop_pickup_group *group)
 {
@@ -1087,6 +1124,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_LIST(thr->loops))
   {
@@ -1447,6 +1489,10 @@ birdloop_init(void)
     init_list(&group->threads);
   }
 
+  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;