avcodec/pthread_frame: Move (init|free)_pthread() to pthread.c

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>
This commit is contained in:
Andreas Rheinhardt 2021-09-02 13:00:42 +02:00
parent bd95f2f599
commit a4f7fabc26
3 changed files with 77 additions and 48 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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