Created
October 5, 2016 15:25
-
-
Save gen2brain/c3a4e2d05708e7ae7479f710c200dbce to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff -urN mpv-0.7.3.orig/osdep/win32/include/pthread.h mpv-0.7.3/osdep/win32/include/pthread.h | |
| --- mpv-0.7.3.orig/osdep/win32/include/pthread.h 1970-01-01 01:00:00.000000000 +0100 | |
| +++ mpv-0.7.3/osdep/win32/include/pthread.h 2016-08-26 19:40:58.000000000 +0200 | |
| @@ -0,0 +1,85 @@ | |
| +#ifndef MP_WRAP_PTHREAD_H_ | |
| +#define MP_WRAP_PTHREAD_H_ | |
| + | |
| +#include <windows.h> | |
| + | |
| +#include <sys/types.h> | |
| + | |
| +// Note: all pthread functions are mangled to make static linking easier. | |
| +#define pthread_once m_pthread_once | |
| +#define pthread_mutex_destroy m_pthread_mutex_destroy | |
| +#define pthread_mutex_init m_pthread_mutex_init | |
| +#define pthread_mutex_lock m_pthread_mutex_lock | |
| +#define pthread_mutex_unlock m_pthread_mutex_unlock | |
| +#define pthread_cond_timedwait m_pthread_cond_timedwait | |
| +#define pthread_cond_wait m_pthread_cond_wait | |
| +#define pthread_self m_pthread_self | |
| +#define pthread_exit m_pthread_exit | |
| +#define pthread_join m_pthread_join | |
| +#define pthread_detach m_pthread_detach | |
| +#define pthread_create m_pthread_create | |
| + | |
| +#define pthread_once_t INIT_ONCE | |
| +#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT | |
| + | |
| +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)); | |
| + | |
| +typedef struct { | |
| + char use_cs; | |
| + union { | |
| + SRWLOCK srw; | |
| + CRITICAL_SECTION cs; | |
| + } lock; | |
| +} pthread_mutex_t; | |
| + | |
| +// Assume SRWLOCK_INIT is {0} so we can easily remain C89-compatible. | |
| +#define PTHREAD_MUTEX_INITIALIZER {0} | |
| + | |
| +#define pthread_mutexattr_t int | |
| +#define pthread_mutexattr_destroy(attr) (void)0 | |
| +#define pthread_mutexattr_init(attr) (*(attr) = 0) | |
| +#define pthread_mutexattr_settype(attr, type) (*(attr) = (type)) | |
| +#define PTHREAD_MUTEX_RECURSIVE 1 | |
| + | |
| +int pthread_mutex_destroy(pthread_mutex_t *mutex); | |
| +int pthread_mutex_init(pthread_mutex_t *restrict mutex, | |
| + const pthread_mutexattr_t *restrict attr); | |
| + | |
| +int pthread_mutex_lock(pthread_mutex_t *mutex); | |
| +int pthread_mutex_unlock(pthread_mutex_t *mutex); | |
| + | |
| +#define pthread_cond_t CONDITION_VARIABLE | |
| +#define pthread_condattr_t int | |
| + | |
| +#define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT | |
| + | |
| +#define pthread_cond_init(cond, attr) InitializeConditionVariable(cond) | |
| +#define pthread_cond_destroy(c) (void)0 | |
| +#define pthread_cond_broadcast(cond) WakeAllConditionVariable(cond) | |
| +#define pthread_cond_signal(cond) WakeConditionVariable(cond) | |
| + | |
| +int pthread_cond_timedwait(pthread_cond_t *restrict cond, | |
| + pthread_mutex_t *restrict mutex, | |
| + const struct timespec *restrict abstime); | |
| +int pthread_cond_wait(pthread_cond_t *restrict cond, | |
| + pthread_mutex_t *restrict mutex); | |
| + | |
| +// Unusual, but allowed by POSIX. | |
| +typedef struct { | |
| + DWORD id; | |
| + struct m_thread_info *info; | |
| +} pthread_t; | |
| + | |
| +#define pthread_equal(a, b) ((a).id == (b).id) | |
| + | |
| +pthread_t pthread_self(void); | |
| +void pthread_exit(void *retval); | |
| +int pthread_join(pthread_t thread, void **retval); | |
| +int pthread_detach(pthread_t thread); | |
| + | |
| +#define pthread_attr_t int | |
| + | |
| +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, | |
| + void *(*start_routine) (void *), void *arg); | |
| + | |
| +#endif | |
| diff -urN mpv-0.7.3.orig/osdep/win32/include/semaphore.h mpv-0.7.3/osdep/win32/include/semaphore.h | |
| --- mpv-0.7.3.orig/osdep/win32/include/semaphore.h 1970-01-01 01:00:00.000000000 +0100 | |
| +++ mpv-0.7.3/osdep/win32/include/semaphore.h 2016-08-26 19:40:58.000000000 +0200 | |
| @@ -0,0 +1,29 @@ | |
| +#ifndef MP_WRAP_SEMAPHORE_H_ | |
| +#define MP_WRAP_SEMAPHORE_H_ | |
| + | |
| +#include <pthread.h> | |
| + | |
| +// See pthread.h for rationale. | |
| +#define sem_init m_sem_init | |
| +#define sem_destroy m_sem_destroy | |
| +#define sem_wait m_sem_wait | |
| +#define sem_trywait m_sem_trywait | |
| +#define sem_timedwait m_sem_timedwait | |
| +#define sem_post m_sem_post | |
| + | |
| +#define SEM_VALUE_MAX 100 | |
| + | |
| +typedef struct { | |
| + pthread_mutex_t lock; | |
| + pthread_cond_t wakeup; | |
| + unsigned int value; | |
| +} sem_t; | |
| + | |
| +int sem_init(sem_t *sem, int pshared, unsigned int value); | |
| +int sem_destroy(sem_t *sem); | |
| +int sem_wait(sem_t *sem); | |
| +int sem_trywait(sem_t *sem); | |
| +int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); | |
| +int sem_post(sem_t *sem); | |
| + | |
| +#endif | |
| diff -urN mpv-0.7.3.orig/osdep/win32/pthread.c mpv-0.7.3/osdep/win32/pthread.c | |
| --- mpv-0.7.3.orig/osdep/win32/pthread.c 1970-01-01 01:00:00.000000000 +0100 | |
| +++ mpv-0.7.3/osdep/win32/pthread.c 2016-08-26 19:40:58.000000000 +0200 | |
| @@ -0,0 +1,261 @@ | |
| +/* Permission to use, copy, modify, and/or distribute this software for any | |
| + * purpose with or without fee is hereby granted, provided that the above | |
| + * copyright notice and this permission notice appear in all copies. | |
| + * | |
| + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
| + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| + */ | |
| +#include <pthread.h> | |
| +#include <semaphore.h> | |
| + | |
| +#include <stdlib.h> | |
| +#include <stdint.h> | |
| +#include <errno.h> | |
| +#include <sys/time.h> | |
| + | |
| +int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) | |
| +{ | |
| + BOOL pending; | |
| + if (!InitOnceBeginInitialize(once_control, 0, &pending, NULL)) | |
| + abort(); | |
| + if (pending) { | |
| + init_routine(); | |
| + InitOnceComplete(once_control, 0, NULL); | |
| + } | |
| + return 0; | |
| +} | |
| + | |
| +int pthread_mutex_destroy(pthread_mutex_t *mutex) | |
| +{ | |
| + if (mutex->use_cs) | |
| + DeleteCriticalSection(&mutex->lock.cs); | |
| + return 0; | |
| +} | |
| + | |
| +int pthread_mutex_init(pthread_mutex_t *restrict mutex, | |
| + const pthread_mutexattr_t *restrict attr) | |
| +{ | |
| + mutex->use_cs = attr && (*attr & PTHREAD_MUTEX_RECURSIVE); | |
| + if (mutex->use_cs) { | |
| + InitializeCriticalSection(&mutex->lock.cs); | |
| + } else { | |
| + InitializeSRWLock(&mutex->lock.srw); | |
| + } | |
| + return 0; | |
| +} | |
| + | |
| +int pthread_mutex_lock(pthread_mutex_t *mutex) | |
| +{ | |
| + if (mutex->use_cs) { | |
| + EnterCriticalSection(&mutex->lock.cs); | |
| + } else { | |
| + AcquireSRWLockExclusive(&mutex->lock.srw); | |
| + } | |
| + return 0; | |
| +} | |
| + | |
| +int pthread_mutex_unlock(pthread_mutex_t *mutex) | |
| +{ | |
| + if (mutex->use_cs) { | |
| + LeaveCriticalSection(&mutex->lock.cs); | |
| + } else { | |
| + ReleaseSRWLockExclusive(&mutex->lock.srw); | |
| + } | |
| + return 0; | |
| +} | |
| + | |
| +static int cond_wait(pthread_cond_t *restrict cond, | |
| + pthread_mutex_t *restrict mutex, | |
| + DWORD ms) | |
| +{ | |
| + BOOL res; | |
| + if (mutex->use_cs) { | |
| + res = SleepConditionVariableCS(cond, &mutex->lock.cs, ms); | |
| + } else { | |
| + res = SleepConditionVariableSRW(cond, &mutex->lock.srw, ms, 0); | |
| + } | |
| + return res ? 0 : ETIMEDOUT; | |
| +} | |
| + | |
| +int pthread_cond_timedwait(pthread_cond_t *restrict cond, | |
| + pthread_mutex_t *restrict mutex, | |
| + const struct timespec *restrict abstime) | |
| +{ | |
| + // mpv uses mingw's gettimeofday() as time source too. | |
| + struct timeval tv; | |
| + gettimeofday(&tv, NULL); | |
| + DWORD timeout_ms = 0; | |
| + if (abstime->tv_sec >= INT64_MAX / 10000) { | |
| + timeout_ms = INFINITE; | |
| + } else if (abstime->tv_sec >= tv.tv_sec) { | |
| + long long msec = (abstime->tv_sec - tv.tv_sec) * 1000LL + | |
| + abstime->tv_nsec / 1000LL / 1000LL - tv.tv_usec / 1000LL; | |
| + if (msec > INT_MAX) { | |
| + timeout_ms = INFINITE; | |
| + } else if (msec > 0) { | |
| + timeout_ms = msec; | |
| + } | |
| + } | |
| + return cond_wait(cond, mutex, timeout_ms); | |
| +} | |
| + | |
| +int pthread_cond_wait(pthread_cond_t *restrict cond, | |
| + pthread_mutex_t *restrict mutex) | |
| +{ | |
| + return cond_wait(cond, mutex, INFINITE); | |
| +} | |
| + | |
| +struct m_thread_info { | |
| + HANDLE handle; | |
| + void *(*user_fn)(void *); | |
| + void *user_arg; | |
| + void *res; | |
| +}; | |
| + | |
| +// Assuming __thread maps to __declspec(thread) | |
| +static __thread struct m_thread_info *self; | |
| + | |
| +pthread_t pthread_self(void) | |
| +{ | |
| + return (pthread_t){GetCurrentThreadId(), self}; | |
| +} | |
| + | |
| +void pthread_exit(void *retval) | |
| +{ | |
| + if (!self) | |
| + abort(); // not started with pthread_create | |
| + self->res = retval; | |
| + if (!self->handle) { | |
| + // detached case | |
| + free(self); | |
| + self = NULL; | |
| + } | |
| + ExitThread(0); | |
| +} | |
| + | |
| +int pthread_join(pthread_t thread, void **retval) | |
| +{ | |
| + if (!thread.info) | |
| + abort(); // not started with pthread_create | |
| + HANDLE h = thread.info->handle; | |
| + if (!h) | |
| + abort(); // thread was detached | |
| + WaitForSingleObject(h, INFINITE); | |
| + CloseHandle(h); | |
| + if (retval) | |
| + *retval = thread.info->res; | |
| + free(thread.info); | |
| + return 0; | |
| +} | |
| + | |
| +int pthread_detach(pthread_t thread) | |
| +{ | |
| + if (!pthread_equal(thread, pthread_self())) | |
| + abort(); // restriction of this wrapper | |
| + if (!thread.info) | |
| + abort(); // not started with pthread_create | |
| + if (!thread.info->handle) | |
| + abort(); // already deatched | |
| + CloseHandle(thread.info->handle); | |
| + thread.info->handle = NULL; | |
| + return 0; | |
| +} | |
| + | |
| +static DWORD WINAPI run_thread(LPVOID lpParameter) | |
| +{ | |
| + struct m_thread_info *info = lpParameter; | |
| + self = info; | |
| + pthread_exit(info->user_fn(info->user_arg)); | |
| + abort(); // not reached | |
| +} | |
| + | |
| +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, | |
| + void *(*start_routine) (void *), void *arg) | |
| +{ | |
| + struct m_thread_info *info = calloc(1, sizeof(*info)); | |
| + if (!info) | |
| + return EAGAIN; | |
| + info->user_fn = start_routine; | |
| + info->user_arg = arg; | |
| + HANDLE h = CreateThread(NULL, 0, run_thread, info, CREATE_SUSPENDED, NULL); | |
| + if (!h) { | |
| + free(info); | |
| + return EAGAIN; | |
| + } | |
| + info->handle = h; | |
| + *thread = (pthread_t){GetThreadId(h), info}; | |
| + ResumeThread(h); | |
| + return 0; | |
| +} | |
| + | |
| +int sem_init(sem_t *sem, int pshared, unsigned int value) | |
| +{ | |
| + if (pshared) | |
| + abort(); // unsupported | |
| + pthread_mutex_init(&sem->lock, NULL); | |
| + pthread_cond_init(&sem->wakeup, NULL); | |
| + sem->value = value; | |
| + return 0; | |
| +} | |
| + | |
| +int sem_destroy(sem_t *sem) | |
| +{ | |
| + pthread_mutex_destroy(&sem->lock); | |
| + pthread_cond_destroy(&sem->wakeup); | |
| + return 0; | |
| +} | |
| + | |
| +int sem_wait(sem_t *sem) | |
| +{ | |
| + pthread_mutex_lock(&sem->lock); | |
| + while (!sem->value) | |
| + pthread_cond_wait(&sem->wakeup, &sem->lock); | |
| + sem->value -= 1; | |
| + pthread_mutex_unlock(&sem->lock); | |
| + return 0; | |
| +} | |
| + | |
| +int sem_trywait(sem_t *sem) | |
| +{ | |
| + pthread_mutex_lock(&sem->lock); | |
| + int r; | |
| + if (sem->value > 0) { | |
| + sem->value -= 1; | |
| + r = 0; | |
| + } else { | |
| + errno = EAGAIN; | |
| + r = -1; | |
| + } | |
| + pthread_mutex_unlock(&sem->lock); | |
| + return r; | |
| +} | |
| + | |
| +int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) | |
| +{ | |
| + pthread_mutex_lock(&sem->lock); | |
| + while (!sem->value) { | |
| + int err = pthread_cond_timedwait(&sem->wakeup, &sem->lock, abs_timeout); | |
| + if (err) { | |
| + pthread_mutex_unlock(&sem->lock); | |
| + errno = err; | |
| + return -1; | |
| + } | |
| + } | |
| + sem->value -= 1; | |
| + pthread_mutex_unlock(&sem->lock); | |
| + return 0; | |
| +} | |
| + | |
| +int sem_post(sem_t *sem) | |
| +{ | |
| + pthread_mutex_lock(&sem->lock); | |
| + sem->value += 1; | |
| + pthread_cond_broadcast(&sem->wakeup); | |
| + pthread_mutex_unlock(&sem->lock); | |
| + return 0; | |
| +} | |
| diff -urN mpv-0.7.3.orig/waftools/checks/custom.py mpv-0.7.3/waftools/checks/custom.py | |
| --- mpv-0.7.3.orig/waftools/checks/custom.py 2015-01-27 02:23:08.000000000 +0100 | |
| +++ mpv-0.7.3/waftools/checks/custom.py 2016-10-05 15:41:16.315002556 +0200 | |
| @@ -20,6 +20,12 @@ | |
| return False | |
| def check_pthreads(ctx, dependency_identifier): | |
| + if ctx.dependency_satisfied('win32-internal-pthreads'): | |
| + h = ctx.path.find_node('osdep/win32/include').abspath() | |
| + # define IN_WINPTHREAD to workaround mingw stupidity (we never want it | |
| + # to define features specific to its own pthread stuff) | |
| + ctx.env.CFLAGS += ['-isystem', h, '-I', h, '-DIN_WINPTHREAD'] | |
| + return True | |
| if check_pthread_flag(ctx, dependency_identifier): | |
| return True | |
| platform_cflags = { | |
| diff -urN mpv-0.7.3.orig/wscript mpv-0.7.3/wscript | |
| --- mpv-0.7.3.orig/wscript 2015-01-27 02:23:08.000000000 +0100 | |
| +++ mpv-0.7.3/wscript 2016-10-05 15:36:39.288793949 +0200 | |
| @@ -120,6 +120,17 @@ | |
| 'fmsg': 'Unable to find either POSIX or MinGW-w64 environment, ' \ | |
| 'or compiler does not work.', | |
| }, { | |
| + 'name': 'win32', | |
| + 'desc': 'win32', | |
| + 'deps_any': [ 'os-win32', 'os-cygwin' ], | |
| + 'func': check_cc(lib=['winmm', 'gdi32', 'ole32', 'avrt', 'dwmapi']), | |
| + }, { | |
| + 'name': '--win32-internal-pthreads', | |
| + 'desc': 'internal pthread wrapper for win32 (Vista+)', | |
| + 'deps_neg': [ 'posix' ], | |
| + 'deps': [ 'win32' ], | |
| + 'func': check_true, | |
| + }, { | |
| 'name': 'pthreads', | |
| 'desc': 'POSIX threads', | |
| 'func': check_pthreads, | |
| diff -urN mpv-0.7.3.orig/wscript_build.py mpv-0.7.3/wscript_build.py | |
| --- mpv-0.7.3.orig/wscript_build.py 2015-01-27 02:23:08.000000000 +0100 | |
| +++ mpv-0.7.3/wscript_build.py 2016-10-05 15:27:13.896935551 +0200 | |
| @@ -392,6 +392,7 @@ | |
| ( "osdep/w32_keyboard.c", "os-win32" ), | |
| ( "osdep/w32_keyboard.c", "os-cygwin" ), | |
| ( "osdep/mpv.rc", "win32-executable" ), | |
| + ( "osdep/win32/pthread.c", "win32-internal-pthreads"), | |
| ## tree_allocator | |
| "ta/ta.c", "ta/ta_talloc.c", "ta/ta_utils.c" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment