summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2023-05-07 23:40:38 +0200
committerMaria Matejka <mq@ucw.cz>2023-05-11 11:41:01 +0200
commitb36d2847887b8e398885d4401ce3e7d23ad4b4c5 (patch)
tree7df93d3a13134e0bbf37055534889d70a053475e
parenta818a3011e6543f6e224e37fb8eb46f64bafa490 (diff)
Threads take loops faster
-rw-r--r--sysdep/unix/io-loop.c68
1 files changed, 42 insertions, 26 deletions
diff --git a/sysdep/unix/io-loop.c b/sysdep/unix/io-loop.c
index 751f882f..c73381da 100644
--- a/sysdep/unix/io-loop.c
+++ b/sysdep/unix/io-loop.c
@@ -589,8 +589,9 @@ struct birdloop_pickup_group {
list loops;
list threads;
uint thread_count;
- uint loop_count;
uint thread_busy_count;
+ uint loop_count;
+ uint loop_unassigned_count;
btime max_latency;
event start_threads;
} pickup_groups[2] = {
@@ -647,6 +648,9 @@ birdloop_set_thread(struct birdloop *loop, struct bird_thread *thr, struct birdl
{
thr->loop_count++;
add_tail(&thr->loops, &loop->n);
+
+ if (!EMPTY_LIST(loop->sock_list))
+ thr->sock_changed = 1;
ev_send_loop(loop->thread->meta, &loop->event);
}
else
@@ -654,6 +658,7 @@ birdloop_set_thread(struct birdloop *loop, struct bird_thread *thr, struct birdl
/* Put into pickup list */
LOCK_DOMAIN(attrs, group->domain);
add_tail(&group->loops, &loop->n);
+ group->loop_unassigned_count++;
UNLOCK_DOMAIN(attrs, group->domain);
}
}
@@ -662,17 +667,15 @@ static void
bird_thread_pickup_next(struct birdloop_pickup_group *group)
{
/* This thread goes to the end of the pickup list */
- LOCK_DOMAIN(attrs, group->domain);
rem_node(&this_thread->n);
add_tail(&group->threads, &this_thread->n);
/* If there are more loops to be picked up, wakeup the next thread in order */
if (!EMPTY_LIST(group->loops))
wakeup_do_kick(SKIP_BACK(struct bird_thread, n, HEAD(group->threads)));
- UNLOCK_DOMAIN(attrs, group->domain);
}
-static struct birdloop *
+static void
birdloop_take(struct birdloop_pickup_group *group)
{
struct birdloop *loop = NULL;
@@ -704,30 +707,49 @@ birdloop_take(struct birdloop_pickup_group *group)
birdloop_set_thread(loop, NULL, group);
birdloop_leave(loop);
+
+ LOCK_DOMAIN(attrs, group->domain);
bird_thread_pickup_next(group);
+ UNLOCK_DOMAIN(attrs, group->domain);
break;
}
birdloop_leave(loop);
}
- return NULL;
+ return;
}
- else if (take)
+
+ if (take)
{
- /* Take the first loop from the pickup list and unlock */
- loop = SKIP_BACK(struct birdloop, n, HEAD(group->loops));
- rem_node(&loop->n);
- UNLOCK_DOMAIN(attrs, group->domain);
+ /* Take a proportional amount of loops from the pickup list and unlock */
+ uint thread_count = group->thread_count + 1;
+ if (group->thread_busy_count < group->thread_count)
+ thread_count -= group->thread_busy_count;
+
+ uint assign = 1 + group->loop_unassigned_count / thread_count;
+ for (uint i=0; !EMPTY_LIST(group->loops) && i<assign; i++)
+ {
+ loop = SKIP_BACK(struct birdloop, n, HEAD(group->loops));
+ rem_node(&loop->n);
+ group->loop_unassigned_count--;
+ UNLOCK_DOMAIN(attrs, group->domain);
+
+ birdloop_enter(loop);
+ birdloop_set_thread(loop, this_thread, group);
+
+ node *n;
+ WALK_LIST(n, loop->sock_list)
+ SKIP_BACK(sock, n, n)->index = -1;
+
+ birdloop_leave(loop);
+
+ LOCK_DOMAIN(attrs, group->domain);
+ }
- birdloop_set_thread(loop, this_thread, group);
bird_thread_pickup_next(group);
- return loop;
- }
- else
- {
- UNLOCK_DOMAIN(attrs, group->domain);
- return NULL;
}
+
+ UNLOCK_DOMAIN(attrs, group->domain);
}
static int
@@ -800,14 +822,7 @@ bird_thread_main(void *arg)
int timeout;
/* Pickup new loops */
- struct birdloop *loop = birdloop_take(thr->group);
- if (loop)
- {
- birdloop_enter(loop);
- if (!EMPTY_LIST(loop->sock_list))
- thr->sock_changed = 1;
- birdloop_leave(loop);
- }
+ birdloop_take(thr->group);
/* Schedule all loops with timed out timers */
timers_fire(&thr->meta->time, 0);
@@ -847,6 +862,7 @@ bird_thread_main(void *arg)
pipe_pollin(&thr->wakeup, &pfd);
node *nn;
+ struct birdloop *loop;
WALK_LIST2(loop, nn, thr->loops, n)
{
birdloop_enter(loop);
@@ -1173,7 +1189,7 @@ bird_thread_show(void *data)
{
if (tsd->show_loops)
bird_thread_show_loop(tsd, loop);
-
+
total_time_ns += loop->working.total_ns + loop->locking.total_ns;
}