@@ -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;
+}
@@ -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;
}
@@ -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
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@outlook.com> --- libavcodec/pthread.c | 38 ++++++++++++++++++++++++ libavcodec/pthread_frame.c | 55 +++++------------------------------ libavcodec/pthread_internal.h | 32 ++++++++++++++++++++ 3 files changed, 77 insertions(+), 48 deletions(-)