mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-11 05:33:55 -04:00
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.
This commit is contained in:
parent
669d36afa8
commit
09bdf20aa0
3 changed files with 3 additions and 19 deletions
12
render.c
12
render.c
|
|
@ -858,7 +858,6 @@ render_worker_thread(void *_ctx)
|
||||||
sem_t *start = &term->render.workers.start;
|
sem_t *start = &term->render.workers.start;
|
||||||
sem_t *done = &term->render.workers.done;
|
sem_t *done = &term->render.workers.done;
|
||||||
mtx_t *lock = &term->render.workers.lock;
|
mtx_t *lock = &term->render.workers.lock;
|
||||||
cnd_t *cond = &term->render.workers.cond;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
sem_wait(start);
|
sem_wait(start);
|
||||||
|
|
@ -868,8 +867,7 @@ render_worker_thread(void *_ctx)
|
||||||
|
|
||||||
while (!frame_done) {
|
while (!frame_done) {
|
||||||
mtx_lock(lock);
|
mtx_lock(lock);
|
||||||
while (tll_length(term->render.workers.queue) == 0)
|
assert(tll_length(term->render.workers.queue) > 0);
|
||||||
cnd_wait(cond, lock);
|
|
||||||
|
|
||||||
int row_no = tll_pop_front(term->render.workers.queue);
|
int row_no = tll_pop_front(term->render.workers.queue);
|
||||||
mtx_unlock(lock);
|
mtx_unlock(lock);
|
||||||
|
|
@ -1416,6 +1414,8 @@ grid_render(struct terminal *term)
|
||||||
|
|
||||||
if (term->render.workers.count > 0) {
|
if (term->render.workers.count > 0) {
|
||||||
|
|
||||||
|
mtx_lock(&term->render.workers.lock);
|
||||||
|
|
||||||
term->render.workers.buf = buf;
|
term->render.workers.buf = buf;
|
||||||
for (size_t i = 0; i < term->render.workers.count; i++)
|
for (size_t i = 0; i < term->render.workers.count; i++)
|
||||||
sem_post(&term->render.workers.start);
|
sem_post(&term->render.workers.start);
|
||||||
|
|
@ -1428,11 +1428,7 @@ grid_render(struct terminal *term)
|
||||||
if (!row->dirty)
|
if (!row->dirty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mtx_lock(&term->render.workers.lock);
|
|
||||||
tll_push_back(term->render.workers.queue, r);
|
tll_push_back(term->render.workers.queue, r);
|
||||||
cnd_signal(&term->render.workers.cond);
|
|
||||||
mtx_unlock(&term->render.workers.lock);
|
|
||||||
|
|
||||||
row->dirty = false;
|
row->dirty = false;
|
||||||
|
|
||||||
wl_surface_damage_buffer(
|
wl_surface_damage_buffer(
|
||||||
|
|
@ -1441,10 +1437,8 @@ grid_render(struct terminal *term)
|
||||||
term->width - term->margins.left - term->margins.right, term->cell_height);
|
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++)
|
for (size_t i = 0; i < term->render.workers.count; i++)
|
||||||
tll_push_back(term->render.workers.queue, -1);
|
tll_push_back(term->render.workers.queue, -1);
|
||||||
cnd_broadcast(&term->render.workers.cond);
|
|
||||||
mtx_unlock(&term->render.workers.lock);
|
mtx_unlock(&term->render.workers.lock);
|
||||||
|
|
||||||
for (size_t i = 0; i < term->render.workers.count; i++)
|
for (size_t i = 0; i < term->render.workers.count; i++)
|
||||||
|
|
|
||||||
|
|
@ -507,13 +507,6 @@ initialize_render_workers(struct terminal *term)
|
||||||
goto err_sem_destroy;
|
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.threads = calloc(
|
||||||
term->render.workers.count, sizeof(term->render.workers.threads[0]));
|
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);
|
sem_post(&term->render.workers.start);
|
||||||
tll_push_back(term->render.workers.queue, -2);
|
tll_push_back(term->render.workers.queue, -2);
|
||||||
}
|
}
|
||||||
cnd_broadcast(&term->render.workers.cond);
|
|
||||||
}
|
}
|
||||||
mtx_unlock(&term->render.workers.lock);
|
mtx_unlock(&term->render.workers.lock);
|
||||||
|
|
||||||
|
|
@ -1198,7 +1190,6 @@ term_destroy(struct terminal *term)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(term->render.workers.threads);
|
free(term->render.workers.threads);
|
||||||
cnd_destroy(&term->render.workers.cond);
|
|
||||||
mtx_destroy(&term->render.workers.lock);
|
mtx_destroy(&term->render.workers.lock);
|
||||||
sem_destroy(&term->render.workers.start);
|
sem_destroy(&term->render.workers.start);
|
||||||
sem_destroy(&term->render.workers.done);
|
sem_destroy(&term->render.workers.done);
|
||||||
|
|
|
||||||
|
|
@ -369,7 +369,6 @@ struct terminal {
|
||||||
size_t count;
|
size_t count;
|
||||||
sem_t start;
|
sem_t start;
|
||||||
sem_t done;
|
sem_t done;
|
||||||
cnd_t cond;
|
|
||||||
mtx_t lock;
|
mtx_t lock;
|
||||||
tll(int) queue;
|
tll(int) queue;
|
||||||
thrd_t *threads;
|
thrd_t *threads;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue