diff options
author | Victorien Le Couviour--Tuffet <victorien@videolan.org> | 2022-10-06 12:14:06 +0300 |
---|---|---|
committer | Victorien Le Couviour--Tuffet <victorien@videolan.org> | 2022-10-20 15:23:30 +0300 |
commit | 3e7886db54d0cb3ce32909c71ad2a8c9d9eab223 (patch) | |
tree | 0bf03411882df77cb438f340a46479620fed6b5f /src/obu.c | |
parent | 5b07b4256617913ec81277f07af592ebd62b11a3 (diff) |
threading: Fix a race around frame completion (frame-mt)
The completion of the first frame to decode while an async reset
request on that same frame is pending will render it stale. The
processing of such a stale request is likely to result in a hang.
One reason this happens is the skip condition at the beginning of
reset_task_cur().
=> Consume the async request before that check.
Another reason is several threads producing async reset requests in
parallel: an async request for the first frame could cascade through the
other threads (other frames) during completion of that frame, meaning
not being caught by the last synchronous reset_task_cur() after
signaling the main thread and before releasing the lock.
=> To solve this we need to add protections at the racy locations. That
means after we increase first, before returning from
reset_task_cur_async(), and after consuming the async request.
Diffstat (limited to 'src/obu.c')
-rw-r--r-- | src/obu.c | 5 |
1 files changed, 4 insertions, 1 deletions
@@ -1581,10 +1581,13 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, const int globa Dav1dThreadPicture *const out_delayed = &c->frame_thread.out_delayed[next]; if (out_delayed->p.data[0] || atomic_load(&f->task_thread.error)) { - if (atomic_load(&c->task_thread.first) + 1U < c->n_fc) + unsigned first = atomic_load(&c->task_thread.first); + if (first + 1U < c->n_fc) atomic_fetch_add(&c->task_thread.first, 1U); else atomic_store(&c->task_thread.first, 0); + atomic_compare_exchange_strong(&c->task_thread.reset_task_cur, + &first, UINT_MAX); if (c->task_thread.cur && c->task_thread.cur < c->n_fc) c->task_thread.cur--; } |