From: Maria Matejka Date: Thu, 23 Jan 2025 12:15:43 +0000 (+0100) Subject: Threads: add a callback for thread shutdown X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ff1b5e035cfe8eec1f120188326c065be0ec928;p=thirdparty%2Fbird.git Threads: add a callback for thread shutdown --- diff --git a/lib/io-loop.h b/lib/io-loop.h index 9f08420a6..ce9002057 100644 --- a/lib/io-loop.h +++ b/lib/io-loop.h @@ -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_ */ diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index 5332a538b..75d863757 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -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;