diff --git a/lib/io-loop.h b/lib/io-loop.h index cd4e2132..c043d1a0 100644 --- a/lib/io-loop.h +++ b/lib/io-loop.h @@ -82,5 +82,7 @@ struct thread_config { void bird_thread_commit(struct thread_config *new); +/* Minimalist main */ +void birdloop_minimalist_main(void) NORET; #endif /* _BIRD_IO_LOOP_H_ */ diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index fcda72a7..b4ac55c0 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -297,6 +297,22 @@ wakeup_free(struct bird_thread *loop) pipe_free(&loop->wakeup); } +static inline void +wakeup_forked(struct bird_thread *thr) +{ + struct pipe new; + pipe_new(&new); + + /* This is kinda sketchy but there is probably + * no actual architecture where copying an int + * would create an invalid inbetween value */ + struct pipe old = thr->wakeup; + thr->wakeup = new; + synchronize_rcu(); + + pipe_free(&old); +} + static inline bool birdloop_try_ping(struct birdloop *loop, u32 ltt) { @@ -1599,3 +1615,57 @@ ev_send_defer(event *e) else ev_send(&this_birdloop->defer_list, e); } + +/* + * Minimalist mainloop with no sockets + */ + +void +birdloop_minimalist_main(void) +{ + /* In case we got forked (hack for Flock) */ + wakeup_forked(&main_thread); + + while (1) + { + /* Unset ping information */ + atomic_fetch_and_explicit(&main_birdloop.thread_transition, ~LTT_PING, memory_order_acq_rel); + + times_update(); + ev_run_list(&global_event_list); + ev_run_list(&global_work_list); + ev_run_list(&main_birdloop.event_list); + timers_fire(&main_birdloop.time); + + bool events = + !ev_list_empty(&global_event_list) || + !ev_list_empty(&global_work_list) || + !ev_list_empty(&main_birdloop.event_list); + + int poll_tout = (events ? 0 : 3000); /* Time in milliseconds */ + timer *t; + if (t = timers_first(&main_birdloop.time)) + { + times_update(); + int timeout = (tm_remains(t) TO_MS) + 1; + poll_tout = MIN(poll_tout, timeout); + } + + struct pollfd pfd = { + .fd = main_birdloop.thread->wakeup.fd[0], + .events = POLLIN, + }; + + int rv = poll(&pfd, 1, poll_tout); + if ((rv < 0) && (errno != EINTR) && (errno != EAGAIN)) + bug("poll in main birdloop: %m"); + + /* Drain wakeup fd */ + if (pfd.revents & POLLIN) + { + THREAD_TRACE(DL_WAKEUP, "Ping received"); + ASSERT_DIE(rv == 1); + wakeup_drain(main_birdloop.thread); + } + } +}