[FFmpeg-devel] [PATCH 02/13] avcodec/pthread_frame: Move (init|free)_pthread() to pthread.c

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Thu Sep 2 18:41:16 EEST 2021


We have more mutexes/condition variables whose initialization is
unchecked.
Also use a proper namespace for these functions.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
 libavcodec/pthread.c          | 38 ++++++++++++++++++++++++
 libavcodec/pthread_frame.c    | 55 +++++------------------------------
 libavcodec/pthread_internal.h | 32 ++++++++++++++++++++
 3 files changed, 77 insertions(+), 48 deletions(-)

diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
index 14b7cca4fe..e7bad19f8b 100644
--- a/libavcodec/pthread.c
+++ b/libavcodec/pthread.c
@@ -29,6 +29,8 @@
  * @see doc/multithreading.txt
  */
 
+#include "libavutil/thread.h"
+
 #include "avcodec.h"
 #include "internal.h"
 #include "pthread_internal.h"
@@ -86,3 +88,39 @@ void ff_thread_free(AVCodecContext *avctx)
     else
         ff_slice_thread_free(avctx);
 }
+
+av_cold void ff_pthread_free(void *obj, const unsigned offsets[])
+{
+    unsigned cnt = *(unsigned*)((char*)obj + offsets[0]);
+    const unsigned *cur_offset = offsets;
+
+    *(unsigned*)((char*)obj + offsets[0]) = 0;
+
+    for (; *(++cur_offset) != THREAD_SENTINEL && cnt; cnt--)
+        pthread_mutex_destroy((pthread_mutex_t*)((char*)obj + *cur_offset));
+    for (; *(++cur_offset) != THREAD_SENTINEL && cnt; cnt--)
+        pthread_cond_destroy ((pthread_cond_t *)((char*)obj + *cur_offset));
+}
+
+av_cold int ff_pthread_init(void *obj, const unsigned offsets[])
+{
+    const unsigned *cur_offset = offsets;
+    unsigned cnt = 0;
+    int err;
+
+#define PTHREAD_INIT_LOOP(type)                                               \
+    for (; *(++cur_offset) != THREAD_SENTINEL; cnt++) {                       \
+        pthread_ ## type ## _t *dst = (void*)((char*)obj + *cur_offset);      \
+        err = pthread_ ## type ## _init(dst, NULL);                           \
+        if (err) {                                                            \
+            err = AVERROR(err);                                               \
+            goto fail;                                                        \
+        }                                                                     \
+    }
+    PTHREAD_INIT_LOOP(mutex)
+    PTHREAD_INIT_LOOP(cond)
+
+fail:
+    *(unsigned*)((char*)obj + offsets[0]) = cnt;
+    return err;
+}
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 8c0966f026..9c5d66c0d4 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -680,59 +680,18 @@ static void park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
     async_lock(fctx);
 }
 
-#define SENTINEL 0 // This forbids putting a mutex/condition variable at the front.
-#define OFFSET_ARRAY(...) __VA_ARGS__, SENTINEL
-#define DEFINE_OFFSET_ARRAY(type, name, mutexes, conds)                       \
-static const unsigned name ## _offsets[] = { offsetof(type, pthread_init_cnt),\
-                                             OFFSET_ARRAY mutexes,            \
-                                             OFFSET_ARRAY conds }
-
 #define OFF(member) offsetof(FrameThreadContext, member)
-DEFINE_OFFSET_ARRAY(FrameThreadContext, thread_ctx,
+DEFINE_OFFSET_ARRAY(FrameThreadContext, thread_ctx, pthread_init_cnt,
                     (OFF(buffer_mutex), OFF(hwaccel_mutex), OFF(async_mutex)),
                     (OFF(async_cond)));
 #undef OFF
 
 #define OFF(member) offsetof(PerThreadContext, member)
-DEFINE_OFFSET_ARRAY(PerThreadContext, per_thread,
+DEFINE_OFFSET_ARRAY(PerThreadContext, per_thread, pthread_init_cnt,
                     (OFF(progress_mutex), OFF(mutex)),
                     (OFF(input_cond), OFF(progress_cond), OFF(output_cond)));
 #undef OFF
 
-static av_cold void free_pthread(void *obj, const unsigned offsets[])
-{
-    unsigned cnt = *(unsigned*)((char*)obj + offsets[0]);
-    const unsigned *cur_offset = offsets;
-
-    for (; *(++cur_offset) != SENTINEL && cnt; cnt--)
-        pthread_mutex_destroy((pthread_mutex_t*)((char*)obj + *cur_offset));
-    for (; *(++cur_offset) != SENTINEL && cnt; cnt--)
-        pthread_cond_destroy ((pthread_cond_t *)((char*)obj + *cur_offset));
-}
-
-static av_cold int init_pthread(void *obj, const unsigned offsets[])
-{
-    const unsigned *cur_offset = offsets;
-    unsigned cnt = 0;
-    int err;
-
-#define PTHREAD_INIT_LOOP(type)                                               \
-    for (; *(++cur_offset) != SENTINEL; cnt++) {                              \
-        pthread_ ## type ## _t *dst = (void*)((char*)obj + *cur_offset);      \
-        err = pthread_ ## type ## _init(dst, NULL);                           \
-        if (err) {                                                            \
-            err = AVERROR(err);                                               \
-            goto fail;                                                        \
-        }                                                                     \
-    }
-    PTHREAD_INIT_LOOP(mutex)
-    PTHREAD_INIT_LOOP(cond)
-
-fail:
-    *(unsigned*)((char*)obj + offsets[0]) = cnt;
-    return err;
-}
-
 void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
 {
     FrameThreadContext *fctx = avctx->internal->thread_ctx;
@@ -792,14 +751,14 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
 
         av_frame_free(&p->frame);
 
-        free_pthread(p, per_thread_offsets);
+        ff_pthread_free(p, per_thread_offsets);
         av_packet_free(&p->avpkt);
 
         av_freep(&p->avctx);
     }
 
     av_freep(&fctx->threads);
-    free_pthread(fctx, thread_ctx_offsets);
+    ff_pthread_free(fctx, thread_ctx_offsets);
 
     av_freep(&avctx->internal->thread_ctx);
 }
@@ -845,7 +804,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free,
         }
     }
 
-    err = init_pthread(p, per_thread_offsets);
+    err = ff_pthread_init(p, per_thread_offsets);
     if (err < 0)
         return err;
 
@@ -906,9 +865,9 @@ int ff_frame_thread_init(AVCodecContext *avctx)
     if (!fctx)
         return AVERROR(ENOMEM);
 
-    err = init_pthread(fctx, thread_ctx_offsets);
+    err = ff_pthread_init(fctx, thread_ctx_offsets);
     if (err < 0) {
-        free_pthread(fctx, thread_ctx_offsets);
+        ff_pthread_free(fctx, thread_ctx_offsets);
         av_freep(&avctx->internal->thread_ctx);
         return err;
     }
diff --git a/libavcodec/pthread_internal.h b/libavcodec/pthread_internal.h
index d2115cbbaf..d0b6a7a673 100644
--- a/libavcodec/pthread_internal.h
+++ b/libavcodec/pthread_internal.h
@@ -31,4 +31,36 @@ void ff_slice_thread_free(AVCodecContext *avctx);
 int ff_frame_thread_init(AVCodecContext *avctx);
 void ff_frame_thread_free(AVCodecContext *avctx, int thread_count);
 
+#define THREAD_SENTINEL 0 // This forbids putting a mutex/condition variable at the front.
+/**
+ * Initialize/destroy a list of mutexes/conditions contained in a structure.
+ * The positions of these mutexes/conditions in the structure are given by
+ * their offsets. Because it is undefined behaviour to destroy
+ * an uninitialized mutex/condition, ff_pthread_init() stores the number
+ * of successfully initialized mutexes and conditions in the object itself
+ * and ff_pthread_free() uses this number to destroy exactly the mutexes and
+ * condition variables that have been successfully initialized.
+ *
+ * @param     obj     The object containing the mutexes/conditions.
+ * @param[in] offsets An array of offsets. Its first member gives the offset
+ *                    of the variable that contains the count of successfully
+ *                    initialized mutexes/condition variables; said variable
+ *                    must be an unsigned int. Two arrays of offsets, each
+ *                    delimited by a THREAD_SENTINEL follow. The first
+ *                    contains the offsets of all the mutexes, the second
+ *                    contains the offsets of all the condition variables.
+ */
+int  ff_pthread_init(void *obj, const unsigned offsets[]);
+void ff_pthread_free(void *obj, const unsigned offsets[]);
+
+/**
+ * Macros to help creating the above lists. mutexes and conds need
+ * to be parentheses-enclosed lists of offsets in the containing structure.
+ */
+#define OFFSET_ARRAY(...) __VA_ARGS__, THREAD_SENTINEL
+#define DEFINE_OFFSET_ARRAY(type, name, cnt_variable, mutexes, conds)         \
+static const unsigned name ## _offsets[] = { offsetof(type, cnt_variable),    \
+                                             OFFSET_ARRAY mutexes,            \
+                                             OFFSET_ARRAY conds }
+
 #endif // AVCODEC_PTHREAD_INTERNAL_H
-- 
2.30.2



More information about the ffmpeg-devel mailing list