0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Fix loop dropping routines

This commit is contained in:
Maria Matejka 2023-05-05 15:19:14 +02:00
parent a95141111c
commit e0c09e6bee

View File

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