From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
To: ffmpeg-devel@ffmpeg.org
Cc: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Subject: [FFmpeg-devel] [PATCH] avcodec/pthread_slice: Don't reinitialise initialised mutex
Date: Thu, 30 Jun 2022 11:47:43 +0200
Message-ID: <DB6PR0101MB2214B21636729129C878BDA38FBA9@DB6PR0101MB2214.eurprd01.prod.exchangelabs.com> (raw)
It results in undefined behaviour. Instead initialize the mutexes
and condition variables once during init (and check these
initializations).
Also combine the corresponding mutex and condition variable
into one structure so that one can allocate their array
jointly.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/hevcdec.c | 7 +++-
libavcodec/pthread_slice.c | 83 ++++++++++++++++++++++++--------------
libavcodec/thread.h | 1 +
3 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index 7037048d53..f222f20706 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -3803,9 +3803,12 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx)
HEVCContext *s = avctx->priv_data;
int ret;
- if(avctx->active_thread_type & FF_THREAD_SLICE)
+ if (avctx->active_thread_type & FF_THREAD_SLICE) {
s->threads_number = avctx->thread_count;
- else
+ ret = ff_slice_thread_init_progress(avctx);
+ if (ret < 0)
+ return ret;
+ } else
s->threads_number = 1;
if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1)
diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c
index 0ad1965a22..e34116116d 100644
--- a/libavcodec/pthread_slice.c
+++ b/libavcodec/pthread_slice.c
@@ -41,6 +41,11 @@ typedef int (action_func)(AVCodecContext *c, void *arg);
typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr);
typedef int (main_func)(AVCodecContext *c);
+typedef struct Progress {
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+} Progress;
+
typedef struct SliceThreadContext {
AVSliceThread *thread;
action_func *func;
@@ -53,8 +58,7 @@ typedef struct SliceThreadContext {
int *entries;
int entries_count;
int thread_count;
- pthread_cond_t *progress_cond;
- pthread_mutex_t *progress_mutex;
+ Progress *progress;
} SliceThreadContext;
static void main_function(void *priv) {
@@ -83,13 +87,13 @@ void ff_slice_thread_free(AVCodecContext *avctx)
avpriv_slicethread_free(&c->thread);
for (i = 0; i < c->thread_count; i++) {
- pthread_mutex_destroy(&c->progress_mutex[i]);
- pthread_cond_destroy(&c->progress_cond[i]);
+ Progress *const progress = &c->progress[i];
+ pthread_mutex_destroy(&progress->mutex);
+ pthread_cond_destroy(&progress->cond);
}
av_freep(&c->entries);
- av_freep(&c->progress_mutex);
- av_freep(&c->progress_cond);
+ av_freep(&c->progress);
av_freep(&avctx->internal->thread_ctx);
}
@@ -172,65 +176,82 @@ int ff_slice_thread_init(AVCodecContext *avctx)
return 0;
}
+int av_cold ff_slice_thread_init_progress(AVCodecContext *avctx)
+{
+ SliceThreadContext *const p = avctx->internal->thread_ctx;
+ int err, i = 0, thread_count = avctx->thread_count;
+
+ p->progress = av_calloc(thread_count, sizeof(*p->progress));
+ if (!p->progress) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ for (; i < thread_count; i++) {
+ Progress *const progress = &p->progress[i];
+ err = pthread_mutex_init(&progress->mutex, NULL);
+ if (err) {
+ err = AVERROR(err);
+ goto fail;
+ }
+ err = pthread_cond_init (&progress->cond, NULL);
+ if (err) {
+ err = AVERROR(err);
+ pthread_mutex_destroy(&progress->mutex);
+ goto fail;
+ }
+ }
+ err = 0;
+fail:
+ p->thread_count = i;
+ return err;
+}
+
void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n)
{
SliceThreadContext *p = avctx->internal->thread_ctx;
+ Progress *const progress = &p->progress[thread];
int *entries = p->entries;
- pthread_mutex_lock(&p->progress_mutex[thread]);
+ pthread_mutex_lock(&progress->mutex);
entries[field] +=n;
- pthread_cond_signal(&p->progress_cond[thread]);
- pthread_mutex_unlock(&p->progress_mutex[thread]);
+ pthread_cond_signal(&progress->cond);
+ pthread_mutex_unlock(&progress->mutex);
}
void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift)
{
SliceThreadContext *p = avctx->internal->thread_ctx;
+ Progress *progress;
int *entries = p->entries;
if (!entries || !field) return;
thread = thread ? thread - 1 : p->thread_count - 1;
+ progress = &p->progress[thread];
- pthread_mutex_lock(&p->progress_mutex[thread]);
+ pthread_mutex_lock(&progress->mutex);
while ((entries[field - 1] - entries[field]) < shift){
- pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]);
+ pthread_cond_wait(&progress->cond, &progress->mutex);
}
- pthread_mutex_unlock(&p->progress_mutex[thread]);
+ pthread_mutex_unlock(&progress->mutex);
}
int ff_alloc_entries(AVCodecContext *avctx, int count)
{
- int i;
-
if (avctx->active_thread_type & FF_THREAD_SLICE) {
SliceThreadContext *p = avctx->internal->thread_ctx;
if (p->entries) {
- av_assert0(p->thread_count == avctx->thread_count);
av_freep(&p->entries);
}
- p->thread_count = avctx->thread_count;
p->entries = av_calloc(count, sizeof(*p->entries));
-
- if (!p->progress_mutex) {
- p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t));
- p->progress_cond = av_malloc_array(p->thread_count, sizeof(pthread_cond_t));
- }
-
- if (!p->entries || !p->progress_mutex || !p->progress_cond) {
- av_freep(&p->entries);
- av_freep(&p->progress_mutex);
- av_freep(&p->progress_cond);
+ if (!p->entries) {
+ p->entries_count = 0;
return AVERROR(ENOMEM);
}
p->entries_count = count;
-
- for (i = 0; i < p->thread_count; i++) {
- pthread_mutex_init(&p->progress_mutex[i], NULL);
- pthread_cond_init(&p->progress_cond[i], NULL);
- }
}
return 0;
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index d36dc83bd7..92cbd927f1 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -106,6 +106,7 @@ int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx,
void ff_thread_free(AVCodecContext *s);
int ff_alloc_entries(AVCodecContext *avctx, int count);
void ff_reset_entries(AVCodecContext *avctx);
+int ff_slice_thread_init_progress(AVCodecContext *avctx);
void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n);
void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift);
--
2.34.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2022-06-30 9:48 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DB6PR0101MB2214B21636729129C878BDA38FBA9@DB6PR0101MB2214.eurprd01.prod.exchangelabs.com \
--to=andreas.rheinhardt@outlook.com \
--cc=ffmpeg-devel@ffmpeg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git