diff options
author | Maria Matejka <mq@ucw.cz> | 2023-04-24 10:39:13 +0200 |
---|---|---|
committer | Maria Matejka <mq@ucw.cz> | 2023-04-24 10:39:13 +0200 |
commit | fa8848aca3f0473412f3ae6288d71dee8458bcfa (patch) | |
tree | 20aa1c64f866079684f4923f857021baff4d2b53 /sysdep/unix/io-loop.c | |
parent | 942d3cbcdd548a73ecc1915a97e297e9bf0bb5e6 (diff) | |
parent | 22f54eaee6c6dbe12ad7bb0ee1da09e3e026b970 (diff) |
Merge branch 'mq-resource-locking' into thread-next
Diffstat (limited to 'sysdep/unix/io-loop.c')
-rw-r--r-- | sysdep/unix/io-loop.c | 99 |
1 files changed, 70 insertions, 29 deletions
diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index efb408e0..8e95a698 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -31,7 +31,7 @@ #define THREAD_STACK_SIZE 65536 /* To be lowered in near future */ -static struct birdloop *birdloop_new_internal(pool *pp, uint order, const char *name, int request_pickup, struct birdloop_pickup_group *group); +static struct birdloop *birdloop_new_no_pickup(pool *pp, uint order, const char *name, ...); /* * Nanosecond time for accounting purposes @@ -87,6 +87,12 @@ birdloop_time_loop(struct birdloop *loop) return &loop->time; } +pool * +birdloop_pool(struct birdloop *loop) +{ + return loop->pool; +} + _Bool birdloop_inside(struct birdloop *loop) { @@ -497,12 +503,14 @@ sockets_fire(struct birdloop *loop) */ DEFINE_DOMAIN(resource); +static void bird_thread_start_event(void *_data); struct birdloop_pickup_group { DOMAIN(resource) domain; list loops; list threads; btime max_latency; + event start_threads; } pickup_groups[2] = { { /* all zeroes */ @@ -510,6 +518,8 @@ struct birdloop_pickup_group { { /* FIXME: make this dynamic, now it copies the loop_max_latency value from proto/bfd/config.Y */ .max_latency = 10 MS, + .start_threads.hook = bird_thread_start_event, + .start_threads.data = &pickup_groups[1], }, }; @@ -624,13 +634,11 @@ bird_thread_main(void *arg) rcu_thread_start(&thr->rcu); synchronize_rcu(); - tmp_init(thr->pool); - init_list(&thr->loops); - - thr->meta = birdloop_new_internal(thr->pool, DOMAIN_ORDER(meta), "Thread Meta", 0, thr->group); - thr->meta->thread = thr; birdloop_enter(thr->meta); + tmp_init(thr->pool, birdloop_domain(thr->meta)); + init_list(&thr->loops); + thr->sock_changed = 1; struct pfd pfd; @@ -746,22 +754,27 @@ bird_thread_cleanup(void *_thr) pthread_attr_destroy(&thr->thread_attr); /* Free all remaining memory */ - rfree(thr->pool); + rp_free(thr->pool); } static struct bird_thread * bird_thread_start(struct birdloop_pickup_group *group) { ASSERT_DIE(birdloop_inside(&main_birdloop)); - ASSERT_DIE(DOMAIN_IS_LOCKED(resource, group->domain)); - pool *p = rp_new(&root_pool, "Thread"); + struct birdloop *meta = birdloop_new_no_pickup(&root_pool, DOMAIN_ORDER(meta), "Thread Meta"); + pool *p = birdloop_pool(meta); + + birdloop_enter(meta); + LOCK_DOMAIN(resource, group->domain); struct bird_thread *thr = mb_allocz(p, sizeof(*thr)); thr->pool = p; thr->cleanup_event = (event) { .hook = bird_thread_cleanup, .data = thr, }; thr->group = group; thr->max_latency_ns = (group->max_latency ?: 5 S) TO_NS; + thr->meta = meta; + thr->meta->thread = thr; wakeup_init(thr); ev_init_list(&thr->priority_events, NULL, "Thread direct event list"); @@ -784,9 +797,18 @@ bird_thread_start(struct birdloop_pickup_group *group) if (e = pthread_create(&thr->thread_id, &thr->thread_attr, bird_thread_main, thr)) die("pthread_create() failed: %M", e); + UNLOCK_DOMAIN(resource, group->domain); + birdloop_leave(meta); return thr; } +static void +bird_thread_start_event(void *_data) +{ + struct birdloop_pickup_group *group = _data; + bird_thread_start(group); +} + static struct birdloop *thread_dropper; static event *thread_dropper_event; static uint thread_dropper_goal; @@ -839,7 +861,7 @@ bird_thread_shutdown(void * _ UNUSED) /* Stop the meta loop */ birdloop_leave(thr->meta); domain_free(thr->meta->time.domain); - rfree(thr->meta->pool); + rp_free(thr->meta->pool); /* Local pages not needed anymore */ flush_local_pages(); @@ -874,18 +896,17 @@ bird_thread_commit(struct config *new, struct config *old UNUSED) int dif = list_length(&group->threads) - (thread_dropper_goal = new->thread_count); _Bool thread_dropper_running = !!thread_dropper; + UNLOCK_DOMAIN(resource, group->domain); + if (dif < 0) { bird_thread_start(group); - UNLOCK_DOMAIN(resource, group->domain); continue; } - UNLOCK_DOMAIN(resource, group->domain); - if ((dif > 0) && !thread_dropper_running) { - struct birdloop *tdl = birdloop_new(&root_pool, DOMAIN_ORDER(control), "Thread dropper", group->max_latency); + struct birdloop *tdl = birdloop_new(&root_pool, DOMAIN_ORDER(control), group->max_latency, "Thread dropper"); event *tde = ev_new_init(tdl->pool, bird_thread_shutdown, NULL); LOCK_DOMAIN(resource, group->domain); @@ -990,7 +1011,7 @@ bird_thread_show(void *data) cli_write_trigger(tsd->cli); DOMAIN_FREE(control, tsd->lock); - rfree(tsd->pool); + rp_free(tsd->pool); the_bird_unlock(); } @@ -1000,12 +1021,13 @@ bird_thread_show(void *data) void cmd_show_threads(int show_loops) { - pool *p = rp_new(&root_pool, "Show Threads"); + DOMAIN(control) lock = DOMAIN_NEW(control, "Show Threads"); + pool *p = rp_new(&root_pool, lock.control, "Show Threads"); struct bird_thread_show_data *tsd = mb_allocz(p, sizeof(struct bird_thread_show_data)); - tsd->lock = DOMAIN_NEW(control, "Show Threads"); tsd->cli = this_cli; tsd->pool = p; + tsd->lock = lock; tsd->show_loops = show_loops; this_cli->cont = bird_thread_show_cli_cont; @@ -1106,8 +1128,10 @@ birdloop_stop_internal(struct birdloop *loop) /* Request local socket reload */ this_thread->sock_changed++; - /* Tail-call the stopped hook */ - loop->stopped(loop->stop_data); + /* Call the stopped hook from the main loop */ + loop->event.hook = loop->stopped; + loop->event.data = loop->stop_data; + ev_send_loop(&main_birdloop, &loop->event); } static void @@ -1178,11 +1202,12 @@ birdloop_run_timer(timer *tm) } static struct birdloop * -birdloop_new_internal(pool *pp, uint order, const char *name, int request_pickup, struct birdloop_pickup_group *group) +birdloop_vnew_internal(pool *pp, uint order, struct birdloop_pickup_group *group, const char *name, va_list args) { struct domain_generic *dg = domain_new(name, order); + DG_LOCK(dg); - pool *p = rp_new(pp, name); + pool *p = rp_vnewf(pp, dg, name, args); struct birdloop *loop = mb_allocz(p, sizeof(struct birdloop)); loop->pool = p; @@ -1191,7 +1216,7 @@ birdloop_new_internal(pool *pp, uint order, const char *name, int request_pickup atomic_store_explicit(&loop->thread_transition, 0, memory_order_relaxed); - birdloop_enter(loop); + birdloop_enter_locked(loop); ev_init_list(&loop->event_list, loop, name); timers_init(&loop->time, p); @@ -1200,13 +1225,12 @@ birdloop_new_internal(pool *pp, uint order, const char *name, int request_pickup loop->event = (event) { .hook = birdloop_run, .data = loop, }; loop->timer = (timer) { .hook = birdloop_run_timer, .data = loop, }; - if (request_pickup) + if (group) { LOCK_DOMAIN(resource, group->domain); add_tail(&group->loops, &loop->n); if (EMPTY_LIST(group->threads)) - bird_thread_start(group); - + ev_send(&global_event_list, &group->start_threads); wakeup_do_kick(SKIP_BACK(struct bird_thread, n, HEAD(group->threads))); UNLOCK_DOMAIN(resource, group->domain); } @@ -1218,10 +1242,24 @@ birdloop_new_internal(pool *pp, uint order, const char *name, int request_pickup return loop; } +static struct birdloop * +birdloop_new_no_pickup(pool *pp, uint order, const char *name, ...) +{ + va_list args; + va_start(args, name); + struct birdloop *loop = birdloop_vnew_internal(pp, order, NULL, name, args); + va_end(args); + return loop; +} + struct birdloop * -birdloop_new(pool *pp, uint order, const char *name, btime max_latency) +birdloop_new(pool *pp, uint order, btime max_latency, const char *name, ...) { - return birdloop_new_internal(pp, order, name, 1, max_latency ? &pickup_groups[1] : &pickup_groups[0]); + va_list args; + va_start(args, name); + struct birdloop *loop = birdloop_vnew_internal(pp, order, max_latency ? &pickup_groups[1] : &pickup_groups[0], name, args); + va_end(args); + return loop; } static void @@ -1257,8 +1295,11 @@ birdloop_free(struct birdloop *loop) { ASSERT_DIE(loop->thread == NULL); - domain_free(loop->time.domain); - rfree(loop->pool); + struct domain_generic *dg = loop->time.domain; + DG_LOCK(dg); + rp_free(loop->pool); + DG_UNLOCK(dg); + domain_free(dg); } static void |