From 09bdf20aa0a6e29265e5e7b81b941a2b894be3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 13 Jul 2020 13:27:23 +0200 Subject: [PATCH] render: keep lock while pushing dirty rows to worker queue Instead of locking the queue for each dirty row we append, and signaling a condition variable, just keep the lock while going through the visible rows. Release the lock once done. Since we take the lock *before* posting the 'start' semaphore, all workers will be waiting for the lock to be released. Then, one at a time they'll get the lock and pick a row to render. The queue will never get empty - when all rows have been rendered, each worker will pick a 'frame done' "job" from the queue, and break the rendering loop. --- render.c | 12 +++--------- terminal.c | 9 --------- terminal.h | 1 - 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/render.c b/render.c index 5332be89..d745975f 100644 --- a/render.c +++ b/render.c @@ -858,7 +858,6 @@ render_worker_thread(void *_ctx) sem_t *start = &term->render.workers.start; sem_t *done = &term->render.workers.done; mtx_t *lock = &term->render.workers.lock; - cnd_t *cond = &term->render.workers.cond; while (true) { sem_wait(start); @@ -868,8 +867,7 @@ render_worker_thread(void *_ctx) while (!frame_done) { mtx_lock(lock); - while (tll_length(term->render.workers.queue) == 0) - cnd_wait(cond, lock); + assert(tll_length(term->render.workers.queue) > 0); int row_no = tll_pop_front(term->render.workers.queue); mtx_unlock(lock); @@ -1416,6 +1414,8 @@ grid_render(struct terminal *term) if (term->render.workers.count > 0) { + mtx_lock(&term->render.workers.lock); + term->render.workers.buf = buf; for (size_t i = 0; i < term->render.workers.count; i++) sem_post(&term->render.workers.start); @@ -1428,11 +1428,7 @@ grid_render(struct terminal *term) if (!row->dirty) continue; - mtx_lock(&term->render.workers.lock); tll_push_back(term->render.workers.queue, r); - cnd_signal(&term->render.workers.cond); - mtx_unlock(&term->render.workers.lock); - row->dirty = false; wl_surface_damage_buffer( @@ -1441,10 +1437,8 @@ grid_render(struct terminal *term) term->width - term->margins.left - term->margins.right, term->cell_height); } - mtx_lock(&term->render.workers.lock); for (size_t i = 0; i < term->render.workers.count; i++) tll_push_back(term->render.workers.queue, -1); - cnd_broadcast(&term->render.workers.cond); mtx_unlock(&term->render.workers.lock); for (size_t i = 0; i < term->render.workers.count; i++) diff --git a/terminal.c b/terminal.c index a97685c6..3a679b5d 100644 --- a/terminal.c +++ b/terminal.c @@ -507,13 +507,6 @@ initialize_render_workers(struct terminal *term) goto err_sem_destroy; } - if ((err = cnd_init(&term->render.workers.cond)) != thrd_success) { - LOG_ERR( - "failed to instantiate render worker condition variable: %s (%d)", - thrd_err_as_string(err), err); - goto err_sem_destroy; - } - term->render.workers.threads = calloc( term->render.workers.count, sizeof(term->render.workers.threads[0])); @@ -1165,7 +1158,6 @@ term_destroy(struct terminal *term) sem_post(&term->render.workers.start); tll_push_back(term->render.workers.queue, -2); } - cnd_broadcast(&term->render.workers.cond); } mtx_unlock(&term->render.workers.lock); @@ -1198,7 +1190,6 @@ term_destroy(struct terminal *term) } } free(term->render.workers.threads); - cnd_destroy(&term->render.workers.cond); mtx_destroy(&term->render.workers.lock); sem_destroy(&term->render.workers.start); sem_destroy(&term->render.workers.done); diff --git a/terminal.h b/terminal.h index 1c040b00..1193a680 100644 --- a/terminal.h +++ b/terminal.h @@ -369,7 +369,6 @@ struct terminal { size_t count; sem_t start; sem_t done; - cnd_t cond; mtx_t lock; tll(int) queue; thrd_t *threads;