From 98e1376b9b6dd62c1aadc54f51afc96881644e78 Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Sat, 14 Jan 2017 17:32:40 +0200 Subject: [PATCH] worker_thread: Drop process priority when executing low priority work When executing low priority work, it is a good idea to nice() the process priority as well so that the executing of the work is truly run as a low priority work. This decreases the interference the work might have on the rest of the system. To achieve this, the work executing loop is rewritten. Instead of having a loop that always tries to execute the highest priority work, separate the low priority and high priority handling in separate loops. This simplifies the logic quite a bit. Furthermore, there is really no need to convert a low priority worker back to executing high priority work. When queuing work, a new worker thread is always spawned whenever a high priority work is queued. Thus, there is no really any chance a low priority worker could pick up any high priority work once it has finished low priority work. Now we no longer can do that as it is not possible to rise a thread priority back up once it lowered its priority. The executing logic of the worker thread is thus much simpler now. Signed-off-by: Timo Kokkonen --- process.c | 71 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/process.c b/process.c index 98033f0..13fe7e5 100644 --- a/process.c +++ b/process.c @@ -83,8 +83,7 @@ static int run_work_on_queue(struct work_queue *queue) static void *worker_thread(void *arg) { - int stop_working = 0; - int work_done = 0; + int ret; char name[16]; mutex_lock(&work_stats_mutex); @@ -97,38 +96,46 @@ static void *worker_thread(void *arg) pr_info("Worker started\n"); - while (!stop_working) { - while (1) { - int prio; - - /* - * Execute as much work from the high priority - * queue as possible. Once there are no more - * high prio work left, break out the loop and - * see if we still need this many workers. - */ - for (prio = 0; prio < WORK_PRIORITIES_NUM; prio++) { - work_done = - run_work_on_queue(&work_queues[prio]); - if (work_done) - break; - } + /* Execute all high priority work from the queue */ + while (run_work_on_queue(&work_queues[WORK_PRIORITY_HIGH])) + ; + /* + * All high priority work is now done, see if we have enough + * workers executing low priority worl. Continue from there if + * needed. + */ + mutex_lock(&work_stats_mutex); + if (workers_active > max_jobs) + goto out_unlock; - if (!work_done || prio != WORK_PRIORITY_HIGH) - break; - } + mutex_unlock(&work_stats_mutex); - mutex_lock(&work_stats_mutex); - if (workers_active > max_jobs || !work_done) { - workers_active--; - pr_info("Worker exiting, %d left active\n", - workers_active); - if (!workers_active) - worker_count = 0; - stop_working = 1; - } - mutex_unlock(&work_stats_mutex); - } + /* + * Start executing the low priority work. Drop the nice value + * as this really is low priority stuff + */ + ret = nice(19); + pr_info("Worker priority dropped to %d\n", ret); + + while (run_work_on_queue(&work_queues[WORK_PRIORITY_LOW])) + ; + + /* All done, exit */ + mutex_lock(&work_stats_mutex); +out_unlock: + workers_active--; + pr_info("Worker exiting, %d left active\n", + workers_active); + + /* + * Last exiting worker zeroes the worker_count. This + * ensures next time we start spawning worker threads + * the first thread will have number zero on its name. + */ + if (!workers_active) + worker_count = 0; + + mutex_unlock(&work_stats_mutex); return NULL; } -- 2.45.0