mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
compat/w32pthreads: change pthread_t into pointer to malloced struct
pthread_t is currently defined as a struct, which gets placed into caller's memory and filled by pthread_create() (which accepts a pthread_t*). The problem with this approach is that pthread_join() accepts pthread_t itself rather than a pointer to it, so it gets a _copy_ of this structure. This causes non-deterministic failures of pthread_join() to produce the correct return value - depending on whether the thread already finished before pthread_join() is called (and thus the copy contains the correct value), or not (then it contains 0). Change the definition of pthread_t into a pointer to a struct, that gets malloced by pthread_create() and freed by pthread_join(). Fixes random failures of fate-ffmpeg-error-rate-fail on Windows after433cf391f5
. See also [1] for an alternative approach that does not require dynamic allocation, but relies on an assumption that the pthread_t value remains in a fixed memory location. [1]23829dd2b2
Reviewed-By: Martin Storsjö <martin@martin.st>
This commit is contained in:
parent
17e4746687
commit
d2096679d5
@ -50,7 +50,7 @@ typedef struct pthread_t {
|
||||
void *(*func)(void* arg);
|
||||
void *arg;
|
||||
void *ret;
|
||||
} pthread_t;
|
||||
} *pthread_t;
|
||||
|
||||
/* use light weight mutex/condition variable API for Windows Vista and later */
|
||||
typedef SRWLOCK pthread_mutex_t;
|
||||
@ -74,7 +74,7 @@ typedef CONDITION_VARIABLE pthread_cond_t;
|
||||
static av_unused THREADFUNC_RETTYPE
|
||||
__stdcall attribute_align_arg win32thread_worker(void *arg)
|
||||
{
|
||||
pthread_t *h = (pthread_t*)arg;
|
||||
pthread_t h = (pthread_t)arg;
|
||||
h->ret = h->func(h->arg);
|
||||
return 0;
|
||||
}
|
||||
@ -82,21 +82,35 @@ __stdcall attribute_align_arg win32thread_worker(void *arg)
|
||||
static av_unused int pthread_create(pthread_t *thread, const void *unused_attr,
|
||||
void *(*start_routine)(void*), void *arg)
|
||||
{
|
||||
thread->func = start_routine;
|
||||
thread->arg = arg;
|
||||
pthread_t ret;
|
||||
|
||||
ret = av_mallocz(sizeof(*ret));
|
||||
if (!ret)
|
||||
return EAGAIN;
|
||||
|
||||
ret->func = start_routine;
|
||||
ret->arg = arg;
|
||||
#if HAVE_WINRT
|
||||
thread->handle = (void*)CreateThread(NULL, 0, win32thread_worker, thread,
|
||||
0, NULL);
|
||||
ret->handle = (void*)CreateThread(NULL, 0, win32thread_worker, ret,
|
||||
0, NULL);
|
||||
#else
|
||||
thread->handle = (void*)_beginthreadex(NULL, 0, win32thread_worker, thread,
|
||||
0, NULL);
|
||||
ret->handle = (void*)_beginthreadex(NULL, 0, win32thread_worker, ret,
|
||||
0, NULL);
|
||||
#endif
|
||||
return !thread->handle;
|
||||
|
||||
if (!ret->handle) {
|
||||
av_free(ret);
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
*thread = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_unused int pthread_join(pthread_t thread, void **value_ptr)
|
||||
{
|
||||
DWORD ret = WaitForSingleObject(thread.handle, INFINITE);
|
||||
DWORD ret = WaitForSingleObject(thread->handle, INFINITE);
|
||||
if (ret != WAIT_OBJECT_0) {
|
||||
if (ret == WAIT_ABANDONED)
|
||||
return EINVAL;
|
||||
@ -104,8 +118,9 @@ static av_unused int pthread_join(pthread_t thread, void **value_ptr)
|
||||
return EDEADLK;
|
||||
}
|
||||
if (value_ptr)
|
||||
*value_ptr = thread.ret;
|
||||
CloseHandle(thread.handle);
|
||||
*value_ptr = thread->ret;
|
||||
CloseHandle(thread->handle);
|
||||
av_free(thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user