From e0c09e6bee8e9bd8686d8165d819a488dc3e09f8 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 5 May 2023 15:19:14 +0200 Subject: [PATCH] Fix loop dropping routines --- sysdep/unix/io-loop.c | 110 +++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 49 deletions(-) diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c index cf54a511..594709d4 100644 --- a/sysdep/unix/io-loop.c +++ b/sysdep/unix/io-loop.c @@ -631,14 +631,12 @@ birdloop_set_thread(struct birdloop *loop, struct bird_thread *thr, struct birdl /* Put into appropriate lists */ if (thr) { - add_tail(&thr->loops, &loop->n); thr->loop_count++; + add_tail(&thr->loops, &loop->n); ev_send_loop(loop->thread->meta, &loop->event); } else { - old->loop_count--; - /* Unschedule from Meta */ ev_postpone(&loop->event); tm_stop(&loop->timer); @@ -686,18 +684,27 @@ birdloop_take(struct birdloop_pickup_group *group) if (drop) { UNLOCK_DOMAIN(resource, group->domain); + node *n; WALK_LIST2(loop, n, this_thread->loops, n) + { + birdloop_enter(loop); if (ev_active(&loop->event)) { LOOP_TRACE(loop, "Moving to another thread"); - /* Pass to another thread */ rem_node(&loop->n); + this_thread->loop_count--; + + /* This also unschedules the loop from Meta */ birdloop_set_thread(loop, NULL, group); + + birdloop_leave(loop); bird_thread_pickup_next(group); break; } + birdloop_leave(loop); + } return NULL; } @@ -731,37 +738,36 @@ poll_timeout(struct birdloop *loop) } static void -bird_thread_busy_update(struct bird_thread *thr, int val) +bird_thread_busy_set(struct bird_thread *thr, int val) { - if (thr->busy_active == val) - return; - - if (val) - thr->busy_counter++; - else - thr->busy_counter--; - - switch (thr->busy_counter) - { - case 0: - thr->busy_active = 0; - break; - case 4: - thr->busy_active = 1; - break; - - default: - return; - } - LOCK_DOMAIN(resource, thr->group->domain); - if (val) + if (thr->busy_active = val) thr->group->thread_busy_count++; else thr->group->thread_busy_count--; + ASSERT_DIE(thr->group->thread_busy_count <= thr->group->thread_count); UNLOCK_DOMAIN(resource, thr->group->domain); } +static void +bird_thread_busy_update(struct bird_thread *thr, int timeout_ms) +{ + int idle_force = (timeout_ms < 0); + int val = (timeout_ms < 5) && !idle_force; + + if (val == thr->busy_active) + return; + + if (val && (++thr->busy_counter == 4)) + return bird_thread_busy_set(thr, 1); + + if (!val && (idle_force || (--thr->busy_counter == 0))) + { + thr->busy_counter = 0; + bird_thread_busy_set(thr, 0); + } +} + static void * bird_thread_main(void *arg) { @@ -847,10 +853,10 @@ bird_thread_main(void *arg) ASSERT_DIE(pfd.loop.used == pfd.pfd.used); } /* Nothing to do in at least 5 seconds, flush local hot page cache */ - else if (timeout > 5000) + else if ((timeout > 5000) && (timeout < 0)) flush_local_pages(); - bird_thread_busy_update(thr, (timeout == 0)); + bird_thread_busy_update(thr, timeout); account_to(&this_thread->idle); poll_retry:; @@ -893,11 +899,12 @@ bird_thread_cleanup(void *_thr) struct bird_thread *thr = _thr; ASSERT_DIE(birdloop_inside(&main_birdloop)); + /* Free the meta loop */ + thr->meta->thread = NULL; + birdloop_free(thr->meta); + /* Thread attributes no longer needed */ pthread_attr_destroy(&thr->thread_attr); - - /* Free all remaining memory */ - rp_free(thr->pool); } static struct bird_thread * @@ -958,6 +965,13 @@ static struct birdloop *thread_dropper; static event *thread_dropper_event; static uint thread_dropper_goal; +static void +bird_thread_dropper_free(void *data) +{ + struct birdloop *tdl_stop = data; + birdloop_free(tdl_stop); +} + static void bird_thread_shutdown(void * _ UNUSED) { @@ -980,35 +994,37 @@ bird_thread_shutdown(void * _ UNUSED) if (tdl_stop) { - birdloop_stop_self(tdl_stop, NULL, NULL); + birdloop_stop_self(tdl_stop, bird_thread_dropper_free, tdl_stop); return; } struct bird_thread *thr = this_thread; - /* Leave the thread-picker list to get no more loops */ LOCK_DOMAIN(resource, group->domain); + /* Leave the thread-picker list to get no more loops */ rem_node(&thr->n); group->thread_count--; + + /* Fix the busy count */ + if (thr->busy_active) + group->thread_busy_count--; + UNLOCK_DOMAIN(resource, group->domain); + /* Leave the thread-dropper loop as we aren't going to return. */ + birdloop_leave(thread_dropper); + /* Drop loops including the thread dropper itself */ while (!EMPTY_LIST(thr->loops)) { struct birdloop *loop = HEAD(thr->loops); /* Remove loop from this thread's list */ + this_thread->loop_count--; rem_node(&loop->n); /* Unset loop's thread */ - if (birdloop_inside(loop)) - birdloop_set_thread(loop, NULL, group); - else - { - birdloop_enter(loop); - birdloop_set_thread(loop, NULL, group); - birdloop_leave(loop); - } + birdloop_set_thread(loop, NULL, group); } /* Let others know about new loops */ @@ -1017,13 +1033,8 @@ bird_thread_shutdown(void * _ UNUSED) wakeup_do_kick(SKIP_BACK(struct bird_thread, n, HEAD(group->threads))); UNLOCK_DOMAIN(resource, group->domain); - /* Leave the thread-dropper loop as we aren't going to return. */ - birdloop_leave(thread_dropper); - /* Stop the meta loop */ birdloop_leave(thr->meta); - domain_free(thr->meta->time.domain); - rp_free(thr->meta->pool); /* Local pages not needed anymore */ flush_local_pages(); @@ -1038,7 +1049,6 @@ bird_thread_shutdown(void * _ UNUSED) pthread_exit(NULL); } - void bird_thread_commit(struct config *new, struct config *old UNUSED) { @@ -1069,6 +1079,7 @@ bird_thread_commit(struct config *new, struct config *old UNUSED) if ((dif > 0) && !thread_dropper_running) { struct birdloop *tdl = birdloop_new(&root_pool, DOMAIN_ORDER(control), group->max_latency, "Thread dropper"); + birdloop_enter(tdl); event *tde = ev_new_init(tdl->pool, bird_thread_shutdown, NULL); LOCK_DOMAIN(resource, group->domain); @@ -1077,6 +1088,7 @@ bird_thread_commit(struct config *new, struct config *old UNUSED) UNLOCK_DOMAIN(resource, group->domain); ev_send_loop(thread_dropper, thread_dropper_event); + birdloop_leave(tdl); } return; @@ -1148,7 +1160,7 @@ bird_thread_show(void *data) LOCK_DOMAIN(control, tsd->lock); if (tsd->show_loops) - tsd_append("Thread %p", this_thread); + tsd_append("Thread %p%s (busy counter %d)", this_thread, this_thread->busy_active ? " [busy]" : "", this_thread->busy_counter); u64 total_time_ns = 0; struct birdloop *loop;