0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-18 17:18:42 +00:00

Loop flags: a simple idempotent event announcement mechanism

This commit is contained in:
Maria Matejka 2022-09-12 10:24:55 +02:00
parent 66f27005ec
commit eac6345759
3 changed files with 37 additions and 1 deletions

View File

@ -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. */

View File

@ -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;

View File

@ -34,6 +34,9 @@ struct birdloop
uint links;
_Atomic u32 flags;
struct birdloop_flag_handler *flag_handler;
void (*stopped)(void *data);
void *stop_data;