ref: 707a32a57df226e3364dcc4373fc32ae7a69af91
parent: e2892ffa2dd1e893d0229c5fcbe0bbbee8e11c20
author: Hugo Beauzée-Luyssen <hugo@videolan.org>
date: Thu Sep 20 09:21:08 EDT 2018
Add & use a thread compatibility layer
--- a/meson.build
+++ b/meson.build
@@ -34,8 +34,11 @@
if not meson.is_cross_build()
thread_dependency = dependency('threads')
else
- thread_dependency = cc.find_library('pthread')
+ thread_dependency = cc.find_library('pthread', required: false)
endif
+if thread_dependency.found()
+ cdata.set('HAVE_PTHREAD_H', 1)
+endif
dav1d_inc_dirs = include_directories(['include', 'include/dav1d'])
@@ -192,6 +195,10 @@
'src/wedge.c',
'src/qm.c',
)
+
+if host_machine.system() == 'windows'
+ libdav1d_sources += files('src/win32/thread.c')
+endif
libdav1d = library('dav1d',
libdav1d_sources, rev_target,
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -28,9 +28,9 @@
#include "config.h"
#include <assert.h>
-#include <pthread.h>
#include <string.h>
+#include "src/thread.h"
#include "common/intops.h"
#include "src/cdf.h"
--- a/src/internal.h
+++ b/src/internal.h
@@ -28,7 +28,6 @@
#ifndef __DAV1D_SRC_INTERNAL_H__
#define __DAV1D_SRC_INTERNAL_H__
-#include <pthread.h>
#include <stdatomic.h>
#include "dav1d/data.h"
@@ -54,6 +53,7 @@
#include "src/picture.h"
#include "src/recon.h"
#include "src/ref_mvs.h"
+#include "src/thread.h"
typedef struct Dav1dDSPContext {
Dav1dIntraPredDSPContext ipred;
--- a/src/picture.c
+++ b/src/picture.c
@@ -39,6 +39,7 @@
#include "src/picture.h"
#include "src/ref.h"
+#include "src/thread.h"
static int picture_alloc_with_edges(Dav1dPicture *const p,
const int w, const int h,
--- a/src/picture.h
+++ b/src/picture.h
@@ -28,9 +28,9 @@
#ifndef __DAV1D_SRC_PICTURE_H__
#define __DAV1D_SRC_PICTURE_H__
-#include <pthread.h>
#include <stdatomic.h>
+#include "src/thread.h"
#include "dav1d/picture.h"
#include "src/thread_data.h"
--- /dev/null
+++ b/src/thread.h
@@ -1,0 +1,63 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DAV1D_THREAD_H__
+# define __DAV1D_THREAD_H__
+
+#if defined(_WIN32) && !defined(HAVE_PTHREAD_H)
+
+#include <windows.h>
+
+typedef CRITICAL_SECTION pthread_mutex_t;
+typedef CONDITION_VARIABLE pthread_cond_t;
+typedef void *pthread_t;
+typedef void *pthread_mutexattr_t;
+typedef void *pthread_condattr_t;
+typedef void *pthread_attr_t;
+
+void pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr);
+void pthread_mutex_destroy(pthread_mutex_t* mutex);
+void pthread_mutex_lock(pthread_mutex_t* mutex);
+void pthread_mutex_unlock(pthread_mutex_t* mutex);
+
+void pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* attr);
+void pthread_cond_destroy(pthread_cond_t* cond);
+void pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
+void pthread_cond_signal(pthread_cond_t* cond);
+void pthread_cond_broadcast(pthread_cond_t* cond);
+
+int pthread_create(pthread_t* thread, const pthread_attr_t* attr,
+ void*(*proc)(void*), void* param);
+void pthread_join(pthread_t thread, void** res);
+
+#else
+
+#include <pthread.h>
+
+#endif
+
+#endif // __DAV1D_THREAD_H__
--- a/src/thread_data.h
+++ b/src/thread_data.h
@@ -28,6 +28,8 @@
#ifndef __DAV1D_SRC_THREAD_DATA_H__
#define __DAV1D_SRC_THREAD_DATA_H__
+#include "src/thread.h"
+
struct thread_data {
pthread_t thread;
pthread_cond_t cond;
--- a/src/thread_task.c
+++ b/src/thread_task.c
@@ -53,7 +53,6 @@
decode_frame(f);
}
- pthread_exit(NULL);
return NULL;
}
@@ -132,6 +131,5 @@
}
}
- pthread_exit(NULL);
return NULL;
}
--- /dev/null
+++ b/src/win32/thread.c
@@ -1,0 +1,128 @@
+/*
+ * Copyright © 2018, VideoLAN and dav1d authors
+ * Copyright © 2018, Two Orioles, LLC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if defined(_WIN32) && !defined(HAVE_PTHREAD_H)
+
+#include <windows.h>
+#include <process.h>
+#include <errno.h>
+
+#include "config.h"
+#include "src/thread.h"
+
+void pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr)
+{
+ (void)attr;
+ InitializeCriticalSection(mutex);
+}
+
+void pthread_mutex_destroy(pthread_mutex_t* mutex)
+{
+ DeleteCriticalSection(mutex);
+}
+
+void pthread_mutex_lock(pthread_mutex_t* mutex)
+{
+ EnterCriticalSection(mutex);
+}
+
+void pthread_mutex_unlock(pthread_mutex_t* mutex)
+{
+ LeaveCriticalSection(mutex);
+}
+
+void pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* attr)
+{
+ (void)attr;
+ InitializeConditionVariable(cond);
+}
+
+void pthread_cond_destroy(pthread_cond_t* cond)
+{
+ (void)cond;
+}
+
+void pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
+{
+ SleepConditionVariableCS(cond, mutex, INFINITE);
+}
+
+void pthread_cond_signal(pthread_cond_t* cond)
+{
+ WakeConditionVariable(cond);
+}
+
+void pthread_cond_broadcast(pthread_cond_t* cond)
+{
+ WakeAllConditionVariable(cond);
+}
+
+typedef struct dav1d_win32_thread_t {
+ HANDLE h;
+ void* param;
+ void*(*proc)(void*);
+ void* res;
+} dav1d_win32_thread_t;
+
+static unsigned __stdcall dav1d_thread_entrypoint(void* data)
+{
+ dav1d_win32_thread_t* t = data;
+ t->res = t->proc( t->param );
+ return 0;
+}
+
+int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void*(*proc)(void*), void* param)
+{
+ dav1d_win32_thread_t* th = *thread = malloc(sizeof(*th));
+ if (th == NULL)
+ return ENOMEM;
+ th->proc = proc;
+ th->param = param;
+ uintptr_t h = _beginthreadex(NULL, 0, dav1d_thread_entrypoint, th, 0, NULL);
+ if ( h == 0 ) {
+ int err = errno;
+ free(th);
+ *thread = NULL;
+ return err;
+ }
+ th->h = (HANDLE)h;
+ return 0;
+}
+
+void pthread_join(pthread_t thread, void** res)
+{
+ dav1d_win32_thread_t* th = thread;
+ WaitForSingleObject(th->h, INFINITE);
+
+ if (res != NULL)
+ *res = th->res;
+ free(th);
+}
+
+#endif