From 48bf1322aa141ca6259b26b37551402758cff0cc Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Wed, 2 Mar 2022 10:35:21 +0100 Subject: Introducing an universal temporary linpool flushed after every task --- lib/timer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/timer.c') diff --git a/lib/timer.c b/lib/timer.c index 381163d0..c47e0bbc 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -233,6 +233,7 @@ timers_fire(struct timeloop *loop) io_log_event(t->hook, t->data); t->hook(t); + tmp_flush(); } } -- cgit v1.2.3 From e858dce757f8766a29f2151ec3ffef3df85af66b Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Thu, 28 Jul 2022 19:49:03 +0200 Subject: Moved the thread starting code to IO loop code --- lib/coro.h | 29 -------- lib/timer.c | 3 +- lib/timer.h | 1 - nest/proto.c | 1 - nest/protocol.h | 4 +- nest/rt-table.c | 2 +- sysdep/unix/Makefile | 2 +- sysdep/unix/coroutine.c | 192 ------------------------------------------------ sysdep/unix/domain.c | 116 +++++++++++++++++++++++++++++ sysdep/unix/io-loop.c | 50 +++++++++++-- sysdep/unix/io-loop.h | 4 + sysdep/unix/log.c | 10 +-- 12 files changed, 172 insertions(+), 242 deletions(-) delete mode 100644 lib/coro.h delete mode 100644 sysdep/unix/coroutine.c create mode 100644 sysdep/unix/domain.c (limited to 'lib/timer.c') diff --git a/lib/coro.h b/lib/coro.h deleted file mode 100644 index 17ccff89..00000000 --- a/lib/coro.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * BIRD Coroutines - * - * (c) 2017 Martin Mares - * (c) 2020-2021 Maria Matejka - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#ifndef _BIRD_CORO_H_ -#define _BIRD_CORO_H_ - -#include "lib/resource.h" - -/* A completely opaque coroutine handle. */ -struct coroutine; - -/* Coroutines are independent threads bound to pools. - * You request a coroutine by calling coro_run(). - * It is forbidden to free a running coroutine from outside. - * The running coroutine must free itself by rfree() before returning. - */ -struct coroutine *coro_run(pool *, void (*entry)(void *), void *data); - -/* Get self. */ -extern _Thread_local struct coroutine *this_coro; - - -#endif diff --git a/lib/timer.c b/lib/timer.c index c1241ba7..ff6975a4 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -32,7 +32,6 @@ #include "nest/bird.h" -#include "lib/coro.h" #include "lib/heap.h" #include "lib/resource.h" #include "lib/timer.h" @@ -117,7 +116,7 @@ tm_set_in_tl(timer *t, btime when, struct timeloop *local_timeloop) t->loop = local_timeloop; - if ((t->index == 1) && (local_timeloop->coro != this_coro)) + if (t->index == 1) birdloop_ping(local_timeloop->loop); } diff --git a/lib/timer.h b/lib/timer.h index 04544ace..555fc96f 100644 --- a/lib/timer.h +++ b/lib/timer.h @@ -41,7 +41,6 @@ struct timeloop BUFFER_(timer *) timers; struct domain_generic *domain; struct birdloop *loop; - struct coroutine *coro; }; #define TLOCK_TIMER_ASSERT(loop) ASSERT_DIE((loop)->domain && DG_IS_LOCKED((loop)->domain)) diff --git a/nest/proto.c b/nest/proto.c index 17cd08f7..1d480ba2 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -15,7 +15,6 @@ #include "lib/event.h" #include "lib/timer.h" #include "lib/string.h" -#include "lib/coro.h" #include "conf/conf.h" #include "nest/rt.h" #include "nest/iface.h" diff --git a/nest/protocol.h b/nest/protocol.h index d6224015..3c823ae1 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -134,7 +134,7 @@ struct proto { u32 debug; /* Debugging flags */ u32 mrtdump; /* MRTDump flags */ uint active_channels; /* Number of active channels */ - uint active_coroutines; /* Number of active coroutines */ + uint active_loops; /* Number of active IO loops */ byte net_type; /* Protocol network type (NET_*), 0 for undefined */ byte disabled; /* Manually disabled */ byte vrf_set; /* Related VRF instance (above) is defined */ @@ -342,7 +342,7 @@ void proto_notify_state(struct proto *p, unsigned state); */ static inline int proto_is_inactive(struct proto *p) -{ return (p->active_channels == 0) && (p->active_coroutines == 0); } +{ return (p->active_channels == 0) && (p->active_loops == 0); } /* diff --git a/nest/rt-table.c b/nest/rt-table.c index ca092678..65fc142a 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1984,7 +1984,7 @@ rt_export_stopped(void *data) /* Reporting the hook as finished. */ CALL(tab->done, hook); - /* Free the hook together with its coroutine. */ + /* Free the hook. */ rfree(hook->pool); } diff --git a/sysdep/unix/Makefile b/sysdep/unix/Makefile index 9831dc96..3f1a8b3a 100644 --- a/sysdep/unix/Makefile +++ b/sysdep/unix/Makefile @@ -1,4 +1,4 @@ -src := alloc.c io.c io-loop.c krt.c log.c main.c random.c coroutine.c +src := alloc.c io.c io-loop.c krt.c log.c main.c random.c domain.c obj := $(src-o-files) $(all-daemon) $(cf-local) diff --git a/sysdep/unix/coroutine.c b/sysdep/unix/coroutine.c deleted file mode 100644 index 4758c056..00000000 --- a/sysdep/unix/coroutine.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * BIRD Coroutines - * - * (c) 2017 Martin Mares - * (c) 2020 Maria Matejka - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - -#undef LOCAL_DEBUG - -#undef DEBUG_LOCKING - -#include "lib/birdlib.h" -#include "lib/locking.h" -#include "lib/coro.h" -#include "lib/resource.h" -#include "lib/timer.h" - -#include "conf/conf.h" - -#define CORO_STACK_SIZE 65536 - -/* - * Implementation of coroutines based on POSIX threads - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Locking subsystem - */ - -_Thread_local struct lock_order locking_stack = {}; -_Thread_local struct domain_generic **last_locked = NULL; - -#define ASSERT_NO_LOCK ASSERT_DIE(last_locked == NULL) - -struct domain_generic { - pthread_mutex_t mutex; - uint order; - struct domain_generic **prev; - struct lock_order *locked_by; - const char *name; -}; - -#define DOMAIN_INIT(_name, _order) { .mutex = PTHREAD_MUTEX_INITIALIZER, .name = _name, .order = _order } - -static struct domain_generic the_bird_domain_gen = DOMAIN_INIT("The BIRD", OFFSETOF(struct lock_order, the_bird)); - -DOMAIN(the_bird) the_bird_domain = { .the_bird = &the_bird_domain_gen }; - -struct domain_generic * -domain_new(const char *name, uint order) -{ - ASSERT_DIE(order < sizeof(struct lock_order)); - struct domain_generic *dg = xmalloc(sizeof(struct domain_generic)); - *dg = (struct domain_generic) DOMAIN_INIT(name, order); - return dg; -} - -void -domain_free(struct domain_generic *dg) -{ - pthread_mutex_destroy(&dg->mutex); - xfree(dg); -} - -uint dg_order(struct domain_generic *dg) -{ - return dg->order; -} - -void do_lock(struct domain_generic *dg, struct domain_generic **lsp) -{ - if ((char *) lsp - (char *) &locking_stack != dg->order) - bug("Trying to lock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack); - - if (lsp <= last_locked) - bug("Trying to lock in a bad order"); - if (*lsp) - bug("Inconsistent locking stack state on lock"); - - btime lock_begin = current_time(); - pthread_mutex_lock(&dg->mutex); - btime duration = current_time() - lock_begin; - if (config && (duration > config->watchdog_warning)) - log(L_WARN "Locking of %s took %d ms", dg->name, (int) (duration TO_MS)); - - if (dg->prev || dg->locked_by) - bug("Previous unlock not finished correctly"); - dg->prev = last_locked; - *lsp = dg; - last_locked = lsp; - dg->locked_by = &locking_stack; -} - -void do_unlock(struct domain_generic *dg, struct domain_generic **lsp) -{ - if ((char *) lsp - (char *) &locking_stack != dg->order) - bug("Trying to unlock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack); - - if (dg->locked_by != &locking_stack) - bug("Inconsistent domain state on unlock"); - if ((last_locked != lsp) || (*lsp != dg)) - bug("Inconsistent locking stack state on unlock"); - dg->locked_by = NULL; - last_locked = dg->prev; - *lsp = NULL; - dg->prev = NULL; - pthread_mutex_unlock(&dg->mutex); -} - -/* Coroutines */ -struct coroutine { - resource r; - pthread_t id; - pthread_attr_t attr; - void (*entry)(void *); - void *data; -}; - -static _Thread_local _Bool coro_cleaned_up = 0; - -static void coro_free(resource *r) -{ - struct coroutine *c = (void *) r; - ASSERT_DIE(pthread_equal(pthread_self(), c->id)); - pthread_attr_destroy(&c->attr); - coro_cleaned_up = 1; -} - -static struct resclass coro_class = { - .name = "Coroutine", - .size = sizeof(struct coroutine), - .free = coro_free, -}; - -_Thread_local struct coroutine *this_coro = NULL; - -static void *coro_entry(void *p) -{ - struct coroutine *c = p; - - ASSERT_DIE(c->entry); - - this_coro = c; - - c->entry(c->data); - ASSERT_DIE(coro_cleaned_up); - - return NULL; -} - -struct coroutine *coro_run(pool *p, void (*entry)(void *), void *data) -{ - ASSERT_DIE(entry); - ASSERT_DIE(p); - - struct coroutine *c = ralloc(p, &coro_class); - - c->entry = entry; - c->data = data; - - int e = 0; - - if (e = pthread_attr_init(&c->attr)) - die("pthread_attr_init() failed: %M", e); - - if (e = pthread_attr_setstacksize(&c->attr, CORO_STACK_SIZE)) - die("pthread_attr_setstacksize(%u) failed: %M", CORO_STACK_SIZE, e); - - if (e = pthread_attr_setdetachstate(&c->attr, PTHREAD_CREATE_DETACHED)) - die("pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed: %M", e); - - if (e = pthread_create(&c->id, &c->attr, coro_entry, c)) - die("pthread_create() failed: %M", e); - - return c; -} diff --git a/sysdep/unix/domain.c b/sysdep/unix/domain.c new file mode 100644 index 00000000..0a5858a6 --- /dev/null +++ b/sysdep/unix/domain.c @@ -0,0 +1,116 @@ +/* + * BIRD Locking + * + * (c) 2020 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#undef LOCAL_DEBUG + +#undef DEBUG_LOCKING + +#include "lib/birdlib.h" +#include "lib/locking.h" +#include "lib/resource.h" +#include "lib/timer.h" + +#include "conf/conf.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Locking subsystem + */ + +_Thread_local struct lock_order locking_stack = {}; +_Thread_local struct domain_generic **last_locked = NULL; + +#define ASSERT_NO_LOCK ASSERT_DIE(last_locked == NULL) + +struct domain_generic { + pthread_mutex_t mutex; + uint order; + struct domain_generic **prev; + struct lock_order *locked_by; + const char *name; +}; + +#define DOMAIN_INIT(_name, _order) { .mutex = PTHREAD_MUTEX_INITIALIZER, .name = _name, .order = _order } + +static struct domain_generic the_bird_domain_gen = DOMAIN_INIT("The BIRD", OFFSETOF(struct lock_order, the_bird)); + +DOMAIN(the_bird) the_bird_domain = { .the_bird = &the_bird_domain_gen }; + +struct domain_generic * +domain_new(const char *name, uint order) +{ + ASSERT_DIE(order < sizeof(struct lock_order)); + struct domain_generic *dg = xmalloc(sizeof(struct domain_generic)); + *dg = (struct domain_generic) DOMAIN_INIT(name, order); + return dg; +} + +void +domain_free(struct domain_generic *dg) +{ + pthread_mutex_destroy(&dg->mutex); + xfree(dg); +} + +uint dg_order(struct domain_generic *dg) +{ + return dg->order; +} + +void do_lock(struct domain_generic *dg, struct domain_generic **lsp) +{ + if ((char *) lsp - (char *) &locking_stack != dg->order) + bug("Trying to lock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack); + + if (lsp <= last_locked) + bug("Trying to lock in a bad order"); + if (*lsp) + bug("Inconsistent locking stack state on lock"); + + btime lock_begin = current_time(); + pthread_mutex_lock(&dg->mutex); + btime duration = current_time() - lock_begin; + if (config && (duration > config->watchdog_warning)) + log(L_WARN "Locking of %s took %d ms", dg->name, (int) (duration TO_MS)); + + if (dg->prev || dg->locked_by) + bug("Previous unlock not finished correctly"); + dg->prev = last_locked; + *lsp = dg; + last_locked = lsp; + dg->locked_by = &locking_stack; +} + +void do_unlock(struct domain_generic *dg, struct domain_generic **lsp) +{ + if ((char *) lsp - (char *) &locking_stack != dg->order) + bug("Trying to unlock on bad position: order=%u, lsp=%p, base=%p", dg->order, lsp, &locking_stack); + + if (dg->locked_by != &locking_stack) + bug("Inconsistent domain state on unlock"); + if ((last_locked != lsp) || (*lsp != dg)) + bug("Inconsistent locking stack state on unlock"); + dg->locked_by = NULL; + last_locked = dg->prev; + *lsp = NULL; + dg->prev = NULL; + pthread_mutex_unlock(&dg->mutex); +} diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index dfb2ce49..3419d9d8 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -17,7 +17,6 @@ #include "nest/bird.h" #include "lib/buffer.h" -#include "lib/coro.h" #include "lib/lists.h" #include "lib/resource.h" #include "lib/event.h" @@ -28,6 +27,8 @@ #include "sysdep/unix/io-loop.h" #include "conf/conf.h" +#define THREAD_STACK_SIZE 65536 /* To be lowered in near future */ + /* * Current thread context */ @@ -132,11 +133,10 @@ wakeup_do_kick(struct birdloop *loop) pipe_kick(loop->wakeup_fds[1]); } -void -birdloop_ping(struct birdloop *loop) +static inline void +birdloop_do_ping(struct birdloop *loop) { - u32 ping_sent = atomic_fetch_add_explicit(&loop->ping_sent, 1, memory_order_acq_rel); - if (ping_sent) + if (atomic_fetch_add_explicit(&loop->ping_sent, 1, memory_order_acq_rel)) return; if (loop == birdloop_wakeup_masked) @@ -145,6 +145,15 @@ birdloop_ping(struct birdloop *loop) wakeup_do_kick(loop); } +void +birdloop_ping(struct birdloop *loop) +{ + if (birdloop_inside(loop) && !loop->ping_pending) + loop->ping_pending++; + else + birdloop_do_ping(loop); +} + /* * Sockets @@ -336,7 +345,7 @@ birdloop_init(void) birdloop_enter_locked(&main_birdloop); } -static void birdloop_main(void *arg); +static void *birdloop_main(void *arg); struct birdloop * birdloop_new(pool *pp, uint order, const char *name) @@ -357,7 +366,19 @@ birdloop_new(pool *pp, uint order, const char *name) timers_init(&loop->time, p); sockets_init(loop); - loop->time.coro = coro_run(p, birdloop_main, loop); + int e = 0; + + if (e = pthread_attr_init(&loop->thread_attr)) + die("pthread_attr_init() failed: %M", e); + + if (e = pthread_attr_setstacksize(&loop->thread_attr, THREAD_STACK_SIZE)) + die("pthread_attr_setstacksize(%u) failed: %M", THREAD_STACK_SIZE, e); + + if (e = pthread_attr_setdetachstate(&loop->thread_attr, PTHREAD_CREATE_DETACHED)) + die("pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed: %M", e); + + if (e = pthread_create(&loop->thread_id, &loop->thread_attr, birdloop_main, loop)) + die("pthread_create() failed: %M", e); birdloop_leave(loop); @@ -393,6 +414,10 @@ void birdloop_free(struct birdloop *loop) { ASSERT_DIE(loop->links == 0); + ASSERT_DIE(pthread_equal(pthread_self(), loop->thread_id)); + + pthread_attr_destroy(&loop->thread_attr); + domain_free(loop->time.domain); rfree(loop->pool); } @@ -423,6 +448,13 @@ birdloop_leave_locked(struct birdloop *loop) /* Check the current context */ ASSERT_DIE(birdloop_current == loop); + /* Send pending pings */ + if (loop->ping_pending) + { + loop->ping_pending = 0; + birdloop_do_ping(loop); + } + /* Restore the old context */ birdloop_current = loop->prev_loop; } @@ -466,7 +498,7 @@ birdloop_unlink(struct birdloop *loop) loop->links--; } -static void +static void * birdloop_main(void *arg) { struct birdloop *loop = arg; @@ -532,6 +564,8 @@ birdloop_main(void *arg) birdloop_leave(loop); loop->stopped(loop->stop_data); + + return NULL; } diff --git a/sysdep/unix/io-loop.h b/sysdep/unix/io-loop.h index 4024b6c5..ca4322fc 100644 --- a/sysdep/unix/io-loop.h +++ b/sysdep/unix/io-loop.h @@ -21,9 +21,13 @@ struct birdloop u8 poll_changed; u8 close_scheduled; + uint ping_pending; _Atomic u32 ping_sent; int wakeup_fds[2]; + pthread_t thread_id; + pthread_attr_t thread_attr; + uint links; void (*stopped)(void *data); diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index f48588b6..185231e8 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -36,10 +36,10 @@ static FILE *dbgf; static list *current_log_list; static char *current_syslog_name; /* NULL -> syslog closed */ -static _Atomic uint max_coro_id = ATOMIC_VAR_INIT(1); -static _Thread_local uint this_coro_id; +static _Atomic uint max_thread_id = ATOMIC_VAR_INIT(1); +static _Thread_local uint this_thread_id; -#define THIS_CORO_ID (this_coro_id ?: (this_coro_id = atomic_fetch_add_explicit(&max_coro_id, 1, memory_order_acq_rel))) +#define THIS_THREAD_ID (this_thread_id ?: (this_thread_id = atomic_fetch_add_explicit(&max_thread_id, 1, memory_order_acq_rel))) #include @@ -183,7 +183,7 @@ log_commit(int class, buffer *buf) l->pos += msg_len; } - fprintf(l->fh, "%s [%04x] <%s> ", tbuf, THIS_CORO_ID, class_names[class]); + fprintf(l->fh, "%s [%04x] <%s> ", tbuf, THIS_THREAD_ID, class_names[class]); } fputs(buf->start, l->fh); fputc('\n', l->fh); @@ -329,7 +329,7 @@ debug(const char *msg, ...) sec = dbg_time.tv_sec - dbg_time_start.tv_sec - 1; } - int n = bsnprintf(pos, max, "%u.%09u: [%04x] ", sec, nsec, THIS_CORO_ID); + int n = bsnprintf(pos, max, "%u.%09u: [%04x] ", sec, nsec, THIS_THREAD_ID); pos += n; max -= n; -- cgit v1.2.3