From: Willy Tarreau Date: Mon, 30 Nov 2020 14:39:00 +0000 (+0100) Subject: MINOR: task: perform atomic counter increments only once per wakeup X-Git-Tag: v2.4-dev2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c309dbdd9932f7ecd8976e8f0a2479b65149eb76;p=thirdparty%2Fhaproxy.git MINOR: task: perform atomic counter increments only once per wakeup In process_runnable_tasks(), we walk the run queue and pick tasks to insert them into the local list. And for each of these operations we perform a few increments, some of which are atomic, and they're even performed under the runqueue's lock. This is useless inside the loop, better do them at the end, since we don't use these values inside the loop and they're not used anywhere else either during this time. The only one is task_list_size which is accessed in parallel by other threads performing remote tasklet wakeups, but it's already approximative and is used to decide to get out of the loop when the limit is reached. So now we compute it first as an initial budget instead. --- diff --git a/src/task.c b/src/task.c index 8d574216f2..93e30227da 100644 --- a/src/task.c +++ b/src/task.c @@ -561,6 +561,8 @@ void process_runnable_tasks() struct mt_list *tmp_list; unsigned int queue; int max_processed; + int picked; + int budget; ti->flags &= ~TI_FL_STUCK; // this thread is still running @@ -612,7 +614,9 @@ void process_runnable_tasks() /* pick up to max[TL_NORMAL] regular tasks from prio-ordered run queues */ /* Note: the grq lock is always held when grq is not null */ - while (tt->task_list_size < max[TL_NORMAL]) { + picked = 0; + budget = max[TL_NORMAL] - tt->task_list_size; + while (picked < budget) { if ((global_tasks_mask & tid_bit) && !grq) { #ifdef USE_THREAD HA_SPIN_LOCK(TASK_RQ_LOCK, &rq_lock); @@ -662,10 +666,7 @@ void process_runnable_tasks() /* Add it to the local task list */ LIST_ADDQ(&tt->tasklets[TL_NORMAL], &((struct tasklet *)t)->list); - _HA_ATOMIC_ADD(&tasks_run_queue, 1); - tt->tl_class_mask |= 1 << TL_NORMAL; - _HA_ATOMIC_ADD(&tt->task_list_size, 1); - activity[tid].tasksw++; + picked++; } /* release the rqueue lock */ @@ -674,6 +675,13 @@ void process_runnable_tasks() grq = NULL; } + if (picked) { + tt->tl_class_mask |= 1 << TL_NORMAL; + _HA_ATOMIC_ADD(&tt->task_list_size, picked); + _HA_ATOMIC_ADD(&tasks_run_queue, picked); + activity[tid].tasksw += picked; + } + /* Merge the list of tasklets waken up by other threads to the * main list. */