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=9bb790c4add0c87904f50de75d90504d38468aec;p=thirdparty%2Fbird.git Threads: add a callback for thread shutdown --- diff --git a/lib/io-loop.h b/lib/io-loop.h index d2c27754c..d19d3fe5a 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; @@ -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_ */ diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index a9c4b3c5a..82f9782d5 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -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;