w32pthreads.h (5619B)
1 /* 2 * Copyright (C) 2010-2011 x264 project 3 * 4 * Authors: Steven Walters <kemuri9@gmail.com> 5 * Pegasys Inc. <http://www.pegasys-inc.com> 6 * 7 * This file is part of FFmpeg. 8 * 9 * FFmpeg is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * FFmpeg is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with FFmpeg; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 */ 23 24 /** 25 * @file 26 * w32threads to pthreads wrapper 27 */ 28 29 #ifndef COMPAT_W32PTHREADS_H 30 #define COMPAT_W32PTHREADS_H 31 32 /* Build up a pthread-like API using underlying Windows API. Have only static 33 * methods so as to not conflict with a potentially linked in pthread-win32 34 * library. 35 * As most functions here are used without checking return values, 36 * only implement return values as necessary. */ 37 38 #include <windows.h> 39 #include <process.h> 40 #include <time.h> 41 42 #include "libavutil/attributes.h" 43 #include "libavutil/common.h" 44 #include "libavutil/internal.h" 45 #include "libavutil/mem.h" 46 #include "libavutil/fftime.h" 47 48 typedef struct pthread_t { 49 void *handle; 50 void *(*func)(void* arg); 51 void *arg; 52 void *ret; 53 } *pthread_t; 54 55 /* use light weight mutex/condition variable API for Windows Vista and later */ 56 typedef SRWLOCK pthread_mutex_t; 57 typedef CONDITION_VARIABLE pthread_cond_t; 58 59 #define PTHREAD_MUTEX_INITIALIZER SRWLOCK_INIT 60 #define PTHREAD_COND_INITIALIZER CONDITION_VARIABLE_INIT 61 62 #define InitializeCriticalSection(x) InitializeCriticalSectionEx(x, 0, 0) 63 #define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE) 64 65 #define PTHREAD_CANCEL_ENABLE 1 66 #define PTHREAD_CANCEL_DISABLE 0 67 68 #if HAVE_WINRT 69 #define THREADFUNC_RETTYPE DWORD 70 #else 71 #define THREADFUNC_RETTYPE unsigned 72 #endif 73 74 static av_unused THREADFUNC_RETTYPE 75 __stdcall attribute_align_arg win32thread_worker(void *arg) 76 { 77 pthread_t h = (pthread_t)arg; 78 h->ret = h->func(h->arg); 79 return 0; 80 } 81 82 static av_unused int pthread_create(pthread_t *thread, const void *unused_attr, 83 void *(*start_routine)(void*), void *arg) 84 { 85 pthread_t ret; 86 87 ret = av_mallocz(sizeof(*ret)); 88 if (!ret) 89 return EAGAIN; 90 91 ret->func = start_routine; 92 ret->arg = arg; 93 #if HAVE_WINRT 94 ret->handle = (void*)CreateThread(NULL, 0, win32thread_worker, ret, 95 0, NULL); 96 #else 97 ret->handle = (void*)_beginthreadex(NULL, 0, win32thread_worker, ret, 98 0, NULL); 99 #endif 100 101 if (!ret->handle) { 102 av_free(ret); 103 return EAGAIN; 104 } 105 106 *thread = ret; 107 108 return 0; 109 } 110 111 static av_unused int pthread_join(pthread_t thread, void **value_ptr) 112 { 113 DWORD ret = WaitForSingleObject(thread->handle, INFINITE); 114 if (ret != WAIT_OBJECT_0) { 115 if (ret == WAIT_ABANDONED) 116 return EINVAL; 117 else 118 return EDEADLK; 119 } 120 if (value_ptr) 121 *value_ptr = thread->ret; 122 CloseHandle(thread->handle); 123 av_free(thread); 124 return 0; 125 } 126 127 static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr) 128 { 129 InitializeSRWLock(m); 130 return 0; 131 } 132 static inline int pthread_mutex_destroy(pthread_mutex_t *m) 133 { 134 /* Unlocked SWR locks use no resources */ 135 return 0; 136 } 137 static inline int pthread_mutex_lock(pthread_mutex_t *m) 138 { 139 AcquireSRWLockExclusive(m); 140 return 0; 141 } 142 static inline int pthread_mutex_unlock(pthread_mutex_t *m) 143 { 144 ReleaseSRWLockExclusive(m); 145 return 0; 146 } 147 148 typedef INIT_ONCE pthread_once_t; 149 #define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT 150 151 static av_unused int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) 152 { 153 BOOL pending = FALSE; 154 InitOnceBeginInitialize(once_control, 0, &pending, NULL); 155 if (pending) 156 init_routine(); 157 InitOnceComplete(once_control, 0, NULL); 158 return 0; 159 } 160 161 static inline int pthread_cond_init(pthread_cond_t *cond, const void *unused_attr) 162 { 163 InitializeConditionVariable(cond); 164 return 0; 165 } 166 167 /* native condition variables do not destroy */ 168 static inline int pthread_cond_destroy(pthread_cond_t *cond) 169 { 170 return 0; 171 } 172 173 static inline int pthread_cond_broadcast(pthread_cond_t *cond) 174 { 175 WakeAllConditionVariable(cond); 176 return 0; 177 } 178 179 static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) 180 { 181 SleepConditionVariableSRW(cond, mutex, INFINITE, 0); 182 return 0; 183 } 184 185 static inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, 186 const struct timespec *abstime) 187 { 188 int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000; 189 DWORD t = av_clip64(abs_milli - av_gettime() / 1000, 0, UINT32_MAX); 190 191 if (!SleepConditionVariableSRW(cond, mutex, t, 0)) { 192 DWORD err = GetLastError(); 193 if (err == ERROR_TIMEOUT) 194 return ETIMEDOUT; 195 else 196 return EINVAL; 197 } 198 return 0; 199 } 200 201 static inline int pthread_cond_signal(pthread_cond_t *cond) 202 { 203 WakeConditionVariable(cond); 204 return 0; 205 } 206 207 static inline int pthread_setcancelstate(int state, int *oldstate) 208 { 209 return 0; 210 } 211 212 #endif /* COMPAT_W32PTHREADS_H */