diff options
author | Maria Matejka <mq@ucw.cz> | 2022-09-12 10:24:55 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2022-09-18 16:33:51 +0200 |
commit | eac634575959a3d32007ebed9921897976c9a82d (patch) | |
tree | a263dd20f62c90b456fb4836705903f516e406fa | |
parent | 66f27005ec1a3e1fa78733aad56dcd976fbb2744 (diff) |
Loop flags: a simple idempotent event announcement mechanism
-rw-r--r-- | lib/io-loop.h | 8 | ||||
-rw-r--r-- | sysdep/unix/io-loop.c | 27 | ||||
-rw-r--r-- | sysdep/unix/io-loop.h | 3 |
3 files changed, 37 insertions, 1 deletions
diff --git a/lib/io-loop.h b/lib/io-loop.h index 2450a609..ae58bbee 100644 --- a/lib/io-loop.h +++ b/lib/io-loop.h @@ -50,6 +50,14 @@ void birdloop_unlink(struct birdloop *loop); void birdloop_ping(struct birdloop *loop); +struct birdloop_flag_handler { + void (*hook)(struct birdloop_flag_handler *, u32 flags); + void *data; +}; + +void birdloop_flag(struct birdloop *loop, u32 flag); +void birdloop_flag_set_handler(struct birdloop *, struct birdloop_flag_handler *); + void birdloop_init(void); /* Yield for a little while. Use only in special cases. */ diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index b7c858c6..575e5403 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -59,6 +59,31 @@ birdloop_inside(struct birdloop *loop) return 0; } +void +birdloop_flag(struct birdloop *loop, u32 flag) +{ + atomic_fetch_or_explicit(&loop->flags, flag, memory_order_acq_rel); + birdloop_ping(loop); +} + +void +birdloop_flag_set_handler(struct birdloop *loop, struct birdloop_flag_handler *fh) +{ + ASSERT_DIE(birdloop_inside(loop)); + loop->flag_handler = fh; +} + +static int +birdloop_process_flags(struct birdloop *loop) +{ + if (!loop->flag_handler) + return 0; + + u32 flags = atomic_exchange_explicit(&loop->flags, 0, memory_order_acq_rel); + loop->flag_handler->hook(loop->flag_handler, flags); + return !!flags; +} + /* * Wakeup code for birdloop */ @@ -516,7 +541,7 @@ birdloop_main(void *arg) while (1) { timers_fire(&loop->time, 0); - if (ev_run_list(&loop->event_list)) + if (birdloop_process_flags(loop) + ev_run_list(&loop->event_list)) timeout = 0; else if (t = timers_first(&loop->time)) timeout = (tm_remains(t) TO_MS) + 1; diff --git a/sysdep/unix/io-loop.h b/sysdep/unix/io-loop.h index 31c40459..aec7a409 100644 --- a/sysdep/unix/io-loop.h +++ b/sysdep/unix/io-loop.h @@ -34,6 +34,9 @@ struct birdloop uint links; + _Atomic u32 flags; + struct birdloop_flag_handler *flag_handler; + void (*stopped)(void *data); void *stop_data; |