Commit 6cf75568 authored by peastman's avatar peastman
Browse files

Switched over to new Windows pthreads library

parent 08945326
......@@ -81,20 +81,6 @@ ENDIF(${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT})
SET(OPENMM_SOURCE_SUBDIRS . openmmapi olla libraries/jama libraries/quern libraries/lepton libraries/sfmt libraries/lbfgs libraries/hilbert libraries/csha1 platforms/reference serialization libraries/validate libraries/irrxml)
IF(WIN32)
SET(OPENMM_SOURCE_SUBDIRS ${OPENMM_SOURCE_SUBDIRS} libraries/pthreads)
ADD_CUSTOM_TARGET(PthreadsLibraries ALL)
FILE(GLOB PTHREADS_LIBRARIES libraries/pthreads/lib/*.dll libraries/pthreads/lib/*.lib)
ADD_CUSTOM_COMMAND(TARGET PthreadsLibraries COMMAND ${CMAKE_COMMAND} ARGS -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/")
FOREACH(lib ${PTHREADS_LIBRARIES})
ADD_CUSTOM_COMMAND(TARGET PthreadsLibraries COMMAND ${CMAKE_COMMAND} ARGS -E copy ${lib} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/")
INSTALL(FILES ${lib} DESTINATION "lib/")
ENDFOREACH(lib)
LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(PTHREADS_LIB pthreadVC2_x64)
ELSE(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(PTHREADS_LIB pthreadVC2)
SET(PTHREADS_LIB_STATIC pthreadVC2_static_mt)
ENDIF(CMAKE_SIZEOF_VOID_P EQUAL 8)
ELSE(WIN32)
IF (NOT ANDROID)
SET(PTHREADS_LIB pthread)
......@@ -301,17 +287,14 @@ ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
IF(OPENMM_BUILD_SHARED_LIB)
ADD_LIBRARY(${SHARED_TARGET} SHARED ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES})
SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_BUILDING_SHARED_LIBRARY -DLEPTON_BUILDING_SHARED_LIBRARY -DOPENMM_VALIDATE_BUILDING_SHARED_LIBRARY")
IF(WIN32)
ADD_DEPENDENCIES(${SHARED_TARGET} PthreadsLibraries)
ENDIF(WIN32)
SET_TARGET_PROPERTIES(${SHARED_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_BUILDING_SHARED_LIBRARY -DLEPTON_BUILDING_SHARED_LIBRARY -DOPENMM_VALIDATE_BUILDING_SHARED_LIBRARY -DPTHREAD_BUILDING_SHARED_LIBRARY")
ENDIF(OPENMM_BUILD_SHARED_LIB)
SET(OPENMM_BUILD_STATIC_LIB OFF CACHE BOOL "Whether to build static OpenMM libraries")
IF(OPENMM_BUILD_STATIC_LIB)
ADD_LIBRARY(${STATIC_TARGET} STATIC ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES})
SET(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_USE_STATIC_LIBRARIES -DLEPTON_USE_STATIC_LIBRARIES -DPTW32_STATIC_LIB")
SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_BUILDING_STATIC_LIBRARY -DLEPTON_BUILDING_STATIC_LIBRARY -DOPENMMM_VALIDATE_BUILDING_STATIC_LIBRARY -DOPENMM_VALIDATE_BUILDING_STATIC_LIBRARY")
SET_TARGET_PROPERTIES(${STATIC_TARGET} PROPERTIES LINK_FLAGS "${EXTRA_LINK_FLAGS}" COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -DOPENMM_BUILDING_STATIC_LIBRARY -DLEPTON_BUILDING_STATIC_LIBRARY -DOPENMMM_VALIDATE_BUILDING_STATIC_LIBRARY -DOPENMM_VALIDATE_BUILDING_STATIC_LIBRARY -DPTHREAD_BUILDING_STATIC_LIBRARY")
ENDIF(OPENMM_BUILD_STATIC_LIB)
IF(OPENMM_BUILD_C_AND_FORTRAN_WRAPPERS)
......
/*
* Posix Threads library for Microsoft Windows
*
* Use at own risk, there is no implied warranty to this code.
* It uses undocumented features of Microsoft Windows that can change
* at any time in the future.
*
* (C) 2010 Lockless Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of Lockless Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
* 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 HOLDER 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.
*/
/*
* You may want to use the MingW64 winpthreads library instead.
* It is based on this, but adds error checking.
*/
/*
* Version 1.0.1 Released 2 Feb 2012
* Fixes pthread_barrier_destroy() to wait for threads to exit the barrier.
*/
#ifndef WIN_PTHREADS
#define WIN_PTHREADS
#include <windows.h>
#include <intrin.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/timeb.h>
#include <process.h>
#define ETIMEDOUT 110
#define ENOTSUP 134
#define PTHREAD_CANCEL_DISABLE 0
#define PTHREAD_CANCEL_ENABLE 0x01
#define PTHREAD_CANCEL_DEFERRED 0
#define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 0x04
#define PTHREAD_EXPLICT_SCHED 0
#define PTHREAD_INHERIT_SCHED 0x08
#define PTHREAD_SCOPE_PROCESS 0
#define PTHREAD_SCOPE_SYSTEM 0x10
#define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE)
#define PTHREAD_CANCELED ((void *) 0xDEADBEEF)
#define PTHREAD_ONCE_INIT 0
#define PTHREAD_MUTEX_INITIALIZER {(void*)-1,-1,0,0,0,0}
#define PTHREAD_RWLOCK_INITIALIZER {0}
#define PTHREAD_COND_INITIALIZER {0}
#define PTHREAD_BARRIER_INITIALIZER \
{0,0,PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER}
#define PTHREAD_SPINLOCK_INITIALIZER 0
#define PTHREAD_DESTRUCTOR_ITERATIONS 256
#define PTHREAD_KEYS_MAX (1<<20)
#define PTHREAD_MUTEX_NORMAL 0
#define PTHREAD_MUTEX_ERRORCHECK 1
#define PTHREAD_MUTEX_RECURSIVE 2
#define PTHREAD_MUTEX_DEFAULT 3
#define PTHREAD_MUTEX_SHARED 4
#define PTHREAD_MUTEX_PRIVATE 0
#define PTHREAD_PRIO_NONE 0
#define PTHREAD_PRIO_INHERIT 8
#define PTHREAD_PRIO_PROTECT 16
#define PTHREAD_PRIO_MULT 32
#define PTHREAD_PROCESS_SHARED 0
#define PTHREAD_PROCESS_PRIVATE 1
#define PTHREAD_BARRIER_SERIAL_THREAD 1
#ifdef _X86_
#define INTERLOCKED_COMPARE_EXCHANGE(destination, exchange, comparand) _InterlockedCompareExchange((volatile long*) destination, (long) exchange, (long) comparand)
#else
#define INTERLOCKED_COMPARE_EXCHANGE(destination, exchange, comparand) _InterlockedCompareExchangePointer((volatile PVOID*) destination, (void*) exchange, (void*) comparand)
#endif
/* Windows doesn't have this, so declare it ourselves. */
struct timespec
{
/* long long in windows is the same as long in unix for 64bit */
long long tv_sec;
long long tv_nsec;
};
typedef struct _pthread_cleanup _pthread_cleanup;
struct _pthread_cleanup
{
void (*func)(void *);
void *arg;
_pthread_cleanup *next;
};
struct _pthread_v
{
void *ret_arg;
void *(* func)(void *);
_pthread_cleanup *clean;
HANDLE h;
int cancelled;
unsigned p_state;
int keymax;
void **keyval;
jmp_buf jb;
};
typedef struct _pthread_v *pthread_t;
typedef struct pthread_barrier_t pthread_barrier_t;
struct pthread_barrier_t
{
int count;
int total;
CRITICAL_SECTION m;
CONDITION_VARIABLE cv;
};
typedef struct pthread_attr_t pthread_attr_t;
struct pthread_attr_t
{
unsigned p_state;
void *stack;
size_t s_size;
};
typedef long pthread_once_t;
typedef unsigned pthread_mutexattr_t;
typedef SRWLOCK pthread_rwlock_t;
typedef CRITICAL_SECTION pthread_mutex_t;
typedef unsigned pthread_key_t;
typedef void *pthread_barrierattr_t;
typedef long pthread_spinlock_t;
typedef int pthread_condattr_t;
typedef CONDITION_VARIABLE pthread_cond_t;
typedef int pthread_rwlockattr_t;
extern volatile long _pthread_cancelling;
extern int _pthread_concur;
/* Will default to zero as needed */
extern pthread_once_t _pthread_tls_once;
extern DWORD _pthread_tls;
/* Note initializer is zero, so this works */
extern pthread_rwlock_t _pthread_key_lock;
extern long _pthread_key_max;
extern long _pthread_key_sch;
extern void (**_pthread_key_dest)(void *);
#define pthread_cleanup_push(F, A)\
{\
const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\
_ReadWriteBarrier();\
pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\
_ReadWriteBarrier()
/* Note that if async cancelling is used, then there is a race here */
#define pthread_cleanup_pop(E)\
(pthread_self()->clean = _pthread_cup.next, (E?_pthread_cup.func(_pthread_cup.arg):0));}
static void _pthread_once_cleanup(pthread_once_t *o)
{
*o = 0;
}
static pthread_t pthread_self(void);
static int pthread_once(pthread_once_t *o, void (*func)(void))
{
long state = *o;
_ReadWriteBarrier();
while (state != 1)
{
if (!state)
{
if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
#ifdef __cplusplus
pthread_cleanup_push(reinterpret_cast<void (__cdecl *)(void *)>(_pthread_once_cleanup), o);
#else
pthread_cleanup_push(_pthread_once_cleanup, o);
#endif
func();
pthread_cleanup_pop(0);
/* Mark as done */
*o = 1;
return 0;
}
}
YieldProcessor();
_ReadWriteBarrier();
state = *o;
}
/* Done */
return 0;
}
static int _pthread_once_raw(pthread_once_t *o, void (*func)(void))
{
long state = *o;
_ReadWriteBarrier();
while (state != 1)
{
if (!state)
{
if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
func();
/* Mark as done */
*o = 1;
return 0;
}
}
YieldProcessor();
_ReadWriteBarrier();
state = *o;
}
/* Done */
return 0;
}
static int pthread_mutex_lock(pthread_mutex_t *m)
{
EnterCriticalSection(m);
return 0;
}
static int pthread_mutex_unlock(pthread_mutex_t *m)
{
LeaveCriticalSection(m);
return 0;
}
static int pthread_mutex_trylock(pthread_mutex_t *m)
{
return TryEnterCriticalSection(m) ? 0 : EBUSY;
}
static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
{
(void) a;
InitializeCriticalSection(m);
return 0;
}
static int pthread_mutex_destroy(pthread_mutex_t *m)
{
DeleteCriticalSection(m);
return 0;
}
#define pthread_mutex_getprioceiling(M, P) ENOTSUP
#define pthread_mutex_setprioceiling(M, P) ENOTSUP
static int pthread_equal(pthread_t t1, pthread_t t2)
{
return t1 == t2;
}
static void pthread_testcancel(void);
static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
{
(void) a;
InitializeSRWLock(l);
return 0;
}
static int pthread_rwlock_destroy(pthread_rwlock_t *l)
{
(void) *l;
return 0;
}
static int pthread_rwlock_rdlock(pthread_rwlock_t *l)
{
pthread_testcancel();
AcquireSRWLockShared(l);
return 0;
}
static int pthread_rwlock_wrlock(pthread_rwlock_t *l)
{
pthread_testcancel();
AcquireSRWLockExclusive(l);
return 0;
}
static void pthread_tls_init(void)
{
_pthread_tls = TlsAlloc();
/* Cannot continue if out of indexes */
if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
}
static int pthread_rwlock_unlock(pthread_rwlock_t *l)
{
void *state = *(void **)l;
if (state == (void *) 1)
{
/* Known to be an exclusive lock */
ReleaseSRWLockExclusive(l);
}
else
{
/* A shared unlock will work */
ReleaseSRWLockShared(l);
}
return 0;
}
static void _pthread_cleanup_dest(pthread_t t)
{
int i, j;
for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
{
int flag = 0;
for (i = 0; i < t->keymax; i++)
{
void *val = t->keyval[i];
if (val)
{
pthread_rwlock_rdlock(&_pthread_key_lock);
if ((uintptr_t) _pthread_key_dest[i] > 1)
{
/* Call destructor */
t->keyval[i] = NULL;
_pthread_key_dest[i](val);
flag = 1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
}
}
/* Nothing to do? */
if (!flag) return;
}
}
static pthread_t pthread_self(void)
{
pthread_t t;
_pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
t = (pthread_t) TlsGetValue(_pthread_tls);
/* Main thread? */
if (!t)
{
t = (pthread_t) malloc(sizeof(struct _pthread_v));
/* If cannot initialize main thread, then the only thing we can do is abort */
if (!t) abort();
t->ret_arg = NULL;
t->func = NULL;
t->clean = NULL;
t->cancelled = 0;
t->p_state = PTHREAD_DEFAULT_ATTR;
t->keymax = 0;
t->keyval = NULL;
t->h = GetCurrentThread();
/* Save for later */
TlsSetValue(_pthread_tls, t);
if (setjmp(t->jb))
{
/* Make sure we free ourselves if we are detached */
if (!t->h) free(t);
/* Time to die */
_endthreadex(0);
}
}
return t;
}
static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
{
/* Get the current state of the lock */
void *state = *(void **) l;
if (!state)
{
/* Unlocked to locked */
if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)0x11, NULL)) return 0;
return EBUSY;
}
/* A single writer exists */
if (state == (void *) 1) return EBUSY;
/* Multiple writers exist? */
if ((uintptr_t) state & 14) return EBUSY;
if ((void*) INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *) ((uintptr_t)state + 16), state) == state) return 0;
return EBUSY;
}
static int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
{
/* Try to grab lock if it has no users */
if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)1, NULL)) return 0;
return EBUSY;
}
static unsigned long long _pthread_time_in_ms(void)
{
struct __timeb64 tb;
_ftime64(&tb);
return tb.time * 1000 + tb.millitm;
}
static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
{
unsigned long long t = ts->tv_sec * 1000;
t += ts->tv_nsec / 1000000;
return t;
}
static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
{
unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
unsigned long long t2 = _pthread_time_in_ms();
/* Prevent underflow */
if (t1 < t2) return 0;
return t1 - t2;
}
static int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts)
{
unsigned long long ct = _pthread_time_in_ms();
unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
pthread_testcancel();
/* Use a busy-loop */
while (1)
{
/* Try to grab lock */
if (!pthread_rwlock_tryrdlock(l)) return 0;
/* Get current time */
ct = _pthread_time_in_ms();
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
}
}
static int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts)
{
unsigned long long ct = _pthread_time_in_ms();
unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
pthread_testcancel();
/* Use a busy-loop */
while (1)
{
/* Try to grab lock */
if (!pthread_rwlock_trywrlock(l)) return 0;
/* Get current time */
ct = _pthread_time_in_ms();
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
}
}
static int pthread_get_concurrency(int *val)
{
*val = _pthread_concur;
return 0;
}
static int pthread_set_concurrency(int val)
{
_pthread_concur = val;
return 0;
}
#define pthread_getschedparam(T, P, S) ENOTSUP
#define pthread_setschedparam(T, P, S) ENOTSUP
#define pthread_getcpuclockid(T, C) ENOTSUP
static int pthread_exit(void *res)
{
pthread_t t = pthread_self();
t->ret_arg = res;
_pthread_cleanup_dest(t);
longjmp(t->jb, 1);
}
static void _pthread_invoke_cancel(void)
{
_pthread_cleanup *pcup;
_InterlockedDecrement(&_pthread_cancelling);
/* Call cancel queue */
for (pcup = pthread_self()->clean; pcup; pcup = pcup->next)
{
pcup->func(pcup->arg);
}
pthread_exit(PTHREAD_CANCELED);
}
static void pthread_testcancel(void)
{
if (_pthread_cancelling)
{
pthread_t t = pthread_self();
if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
{
_pthread_invoke_cancel();
}
}
}
static int pthread_cancel(pthread_t t)
{
if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS)
{
/* Dangerous asynchronous cancelling */
CONTEXT ctxt;
/* Already done? */
if (t->cancelled) return ESRCH;
ctxt.ContextFlags = CONTEXT_CONTROL;
SuspendThread(t->h);
GetThreadContext(t->h, &ctxt);
#ifdef _M_X64
ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
#else
ctxt.Eip = (uintptr_t) _pthread_invoke_cancel;
#endif
SetThreadContext(t->h, &ctxt);
/* Also try deferred Cancelling */
t->cancelled = 1;
/* Notify everyone to look */
_InterlockedIncrement(&_pthread_cancelling);
ResumeThread(t->h);
}
else
{
/* Safe deferred Cancelling */
t->cancelled = 1;
/* Notify everyone to look */
_InterlockedIncrement(&_pthread_cancelling);
}
return 0;
}
static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag)
{
return attr->p_state & flag;
}
static int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val)
{
if (~flag & val) return EINVAL;
attr->p_state &= ~flag;
attr->p_state |= val;
return 0;
}
static int pthread_attr_init(pthread_attr_t *attr)
{
attr->p_state = PTHREAD_DEFAULT_ATTR;
attr->stack = NULL;
attr->s_size = 0;
return 0;
}
static int pthread_attr_destroy(pthread_attr_t *attr)
{
/* No need to do anything */
return 0;
}
static int pthread_attr_setdetachstate(pthread_attr_t *a, int flag)
{
return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
}
static int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag)
{
*flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
return 0;
}
static int pthread_attr_setinheritsched(pthread_attr_t *a, int flag)
{
return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
}
static int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag)
{
*flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
return 0;
}
static int pthread_attr_setscope(pthread_attr_t *a, int flag)
{
return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
}
static int pthread_attr_getscope(pthread_attr_t *a, int *flag)
{
*flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
return 0;
}
static int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack)
{
*stack = attr->stack;
return 0;
}
static int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack)
{
attr->stack = stack;
return 0;
}
static int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size)
{
*size = attr->s_size;
return 0;
}
static int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
{
attr->s_size = size;
return 0;
}
#define pthread_attr_getguardsize(A, S) ENOTSUP
#define pthread_attr_setgaurdsize(A, S) ENOTSUP
#define pthread_attr_getschedparam(A, S) ENOTSUP
#define pthread_attr_setschedparam(A, S) ENOTSUP
#define pthread_attr_getschedpolicy(A, S) ENOTSUP
#define pthread_attr_setschedpolicy(A, S) ENOTSUP
static int pthread_setcancelstate(int state, int *oldstate)
{
pthread_t t = pthread_self();
if ((state & PTHREAD_CANCEL_ENABLE) != state) return EINVAL;
if (oldstate) *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE;
t->p_state &= ~PTHREAD_CANCEL_ENABLE;
t->p_state |= state;
return 0;
}
static int pthread_setcanceltype(int type, int *oldtype)
{
pthread_t t = pthread_self();
if ((type & PTHREAD_CANCEL_ASYNCHRONOUS) != type) return EINVAL;
if (oldtype) *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS;
t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
t->p_state |= type;
return 0;
}
static int pthread_create_wrapper(void *args)
{
struct _pthread_v *tv = (_pthread_v*) args;
int i, j;
_pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
TlsSetValue(_pthread_tls, tv);
if (!setjmp(tv->jb))
{
/* Call function and save return value */
tv->ret_arg = tv->func(tv->ret_arg);
/* Clean up destructors */
_pthread_cleanup_dest(tv);
}
/* If we exit too early, then we can race with create */
while (tv->h == (HANDLE) -1)
{
YieldProcessor();
_ReadWriteBarrier();
}
/* Make sure we free ourselves if we are detached */
if (!tv->h) free(tv);
return 0;
}
static int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(* func)(void *), void *arg)
{
struct _pthread_v *tv = (_pthread_v*) malloc(sizeof(struct _pthread_v));
unsigned ssize = 0;
if (!tv) return 1;
*th = tv;
/* Save data in pthread_t */
tv->ret_arg = arg;
tv->func = func;
tv->clean = NULL;
tv->cancelled = 0;
tv->p_state = PTHREAD_DEFAULT_ATTR;
tv->keymax = 0;
tv->keyval = NULL;
tv->h = (HANDLE) -1;
if (attr)
{
tv->p_state = attr->p_state;
ssize = attr->s_size;
}
/* Make sure tv->h has value of -1 */
_ReadWriteBarrier();
#ifdef __cplusplus
tv->h = (HANDLE) _beginthreadex(NULL, ssize, reinterpret_cast<unsigned int (__stdcall *)(void *)>(pthread_create_wrapper), tv, 0, NULL);
#else
tv->h = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL);
#endif
/* Failed */
if (!tv->h) return 1;
if (tv->p_state & PTHREAD_CREATE_DETACHED)
{
CloseHandle(tv->h);
_ReadWriteBarrier();
tv->h = 0;
}
return 0;
}
static int pthread_join(pthread_t t, void **res)
{
struct _pthread_v *tv = t;
pthread_testcancel();
WaitForSingleObject(tv->h, INFINITE);
CloseHandle(tv->h);
/* Obtain return value */
if (res) *res = tv->ret_arg;
free(tv);
return 0;
}
static int pthread_detach(pthread_t t)
{
struct _pthread_v *tv = t;
/*
* This can't race with thread exit because
* our call would be undefined if called on a dead thread.
*/
CloseHandle(tv->h);
_ReadWriteBarrier();
tv->h = 0;
return 0;
}
static int pthread_mutexattr_init(pthread_mutexattr_t *a)
{
*a = 0;
return 0;
}
static int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
{
(void) a;
return 0;
}
static int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type)
{
*type = *a & 3;
return 0;
}
static int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
{
if ((unsigned) type > 3) return EINVAL;
*a &= ~3;
*a |= type;
return 0;
}
static int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type)
{
*type = *a & 4;
return 0;
}
static int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type)
{
if ((type & 4) != type) return EINVAL;
*a &= ~4;
*a |= type;
return 0;
}
static int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type)
{
*type = *a & (8 + 16);
return 0;
}
static int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type)
{
if ((type & (8 + 16)) != 8 + 16) return EINVAL;
*a &= ~(8 + 16);
*a |= type;
return 0;
}
static int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio)
{
*prio = *a / PTHREAD_PRIO_MULT;
return 0;
}
static int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
{
*a &= (PTHREAD_PRIO_MULT - 1);
*a += prio * PTHREAD_PRIO_MULT;
return 0;
}
static int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts)
{
unsigned long long t, ct;
struct _pthread_crit_t
{
void *debug;
LONG count;
LONG r_count;
HANDLE owner;
HANDLE sem;
ULONG_PTR spin;
};
/* Try to lock it without waiting */
if (!pthread_mutex_trylock(m)) return 0;
ct = _pthread_time_in_ms();
t = _pthread_time_in_ms_from_timespec(ts);
while (1)
{
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
/* Wait on semaphore within critical section */
WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, t - ct);
/* Try to grab lock */
if (!pthread_mutex_trylock(m)) return 0;
/* Get current time */
ct = _pthread_time_in_ms();
}
}
#define _PTHREAD_BARRIER_FLAG (1<<30)
static int pthread_barrier_destroy(pthread_barrier_t *b)
{
EnterCriticalSection(&b->m);
while (b->total > _PTHREAD_BARRIER_FLAG)
{
/* Wait until everyone exits the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
LeaveCriticalSection(&b->m);
DeleteCriticalSection(&b->m);
return 0;
}
static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count)
{
/* Ignore attr */
(void) attr;
b->count = count;
b->total = 0;
InitializeCriticalSection(&b->m);
InitializeConditionVariable(&b->cv);
return 0;
}
static int pthread_barrier_wait(pthread_barrier_t *b)
{
EnterCriticalSection(&b->m);
while (b->total > _PTHREAD_BARRIER_FLAG)
{
/* Wait until everyone exits the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
/* Are we the first to enter? */
if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0;
b->total++;
if (b->total == b->count)
{
b->total += _PTHREAD_BARRIER_FLAG - 1;
WakeAllConditionVariable(&b->cv);
LeaveCriticalSection(&b->m);
return 1;
}
else
{
while (b->total < _PTHREAD_BARRIER_FLAG)
{
/* Wait until enough threads enter the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
b->total--;
/* Get entering threads to wake up */
if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
LeaveCriticalSection(&b->m);
return 0;
}
}
static int pthread_barrierattr_init(void **attr)
{
*attr = NULL;
return 0;
}
static int pthread_barrierattr_destroy(void **attr)
{
/* Ignore attr */
(void) attr;
return 0;
}
static int pthread_barrierattr_setpshared(void **attr, int s)
{
*attr = (void *) s;
return 0;
}
static int pthread_barrierattr_getpshared(void **attr, int *s)
{
*s = (int) (size_t) *attr;
return 0;
}
static int pthread_key_create(pthread_key_t *key, void (* dest)(void *))
{
int i;
long nmax;
void (**d)(void *);
if (!key) return EINVAL;
pthread_rwlock_wrlock(&_pthread_key_lock);
for (i = _pthread_key_sch; i < _pthread_key_max; i++)
{
if (!_pthread_key_dest[i])
{
*key = i;
if (dest)
{
_pthread_key_dest[i] = dest;
}
else
{
_pthread_key_dest[i] = (void(*)(void *))1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
return 0;
}
}
for (i = 0; i < _pthread_key_sch; i++)
{
if (!_pthread_key_dest[i])
{
*key = i;
if (dest)
{
_pthread_key_dest[i] = dest;
}
else
{
_pthread_key_dest[i] = (void(*)(void *))1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
return 0;
}
}
if (!_pthread_key_max) _pthread_key_max = 1;
if (_pthread_key_max == PTHREAD_KEYS_MAX)
{
pthread_rwlock_unlock(&_pthread_key_lock);
return ENOMEM;
}
nmax = _pthread_key_max * 2;
if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX;
/* No spare room anywhere */
#ifdef __cplusplus
d = reinterpret_cast<void (__cdecl **)(void *)>(realloc(_pthread_key_dest, nmax * sizeof(*d)));
#else
d = realloc(_pthread_key_dest, nmax * sizeof(*d));
#endif
if (!d)
{
pthread_rwlock_unlock(&_pthread_key_lock);
return ENOMEM;
}
/* Clear new region */
memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
/* Use new region */
_pthread_key_dest = d;
_pthread_key_sch = _pthread_key_max + 1;
*key = _pthread_key_max;
_pthread_key_max = nmax;
if (dest)
{
_pthread_key_dest[*key] = dest;
}
else
{
_pthread_key_dest[*key] = (void(*)(void *))1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
return 0;
}
static int pthread_key_delete(pthread_key_t key)
{
if (key > _pthread_key_max) return EINVAL;
if (!_pthread_key_dest) return EINVAL;
pthread_rwlock_wrlock(&_pthread_key_lock);
_pthread_key_dest[key] = NULL;
/* Start next search from our location */
if (_pthread_key_sch > key) _pthread_key_sch = key;
pthread_rwlock_unlock(&_pthread_key_lock);
return 0;
}
static void *pthread_getspecific(pthread_key_t key)
{
pthread_t t = pthread_self();
if (key >= t->keymax) return NULL;
return t->keyval[key];
}
static int pthread_setspecific(pthread_key_t key, const void *value)
{
pthread_t t = pthread_self();
if (key > t->keymax)
{
int keymax = (key + 1) * 2;
void **kv = (void**) realloc(t->keyval, keymax * sizeof(void *));
if (!kv) return ENOMEM;
/* Clear new region */
memset(&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void*));
t->keyval = kv;
t->keymax = keymax;
}
t->keyval[key] = (void *) value;
return 0;
}
static int pthread_spin_init(pthread_spinlock_t *l, int pshared)
{
(void) pshared;
*l = 0;
return 0;
}
static int pthread_spin_destroy(pthread_spinlock_t *l)
{
(void) l;
return 0;
}
/* No-fair spinlock due to lack of knowledge of thread number */
static int pthread_spin_lock(pthread_spinlock_t *l)
{
while (_InterlockedExchange(l, EBUSY))
{
/* Don't lock the bus whilst waiting */
while (*l)
{
YieldProcessor();
/* Compiler barrier. Prevent caching of *l */
_ReadWriteBarrier();
}
}
return 0;
}
static int pthread_spin_trylock(pthread_spinlock_t *l)
{
return _InterlockedExchange(l, EBUSY);
}
static int pthread_spin_unlock(pthread_spinlock_t *l)
{
/* Compiler barrier. The store below acts with release symmantics */
_ReadWriteBarrier();
*l = 0;
return 0;
}
static int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a)
{
(void) a;
InitializeConditionVariable(c);
return 0;
}
static int pthread_cond_signal(pthread_cond_t *c)
{
WakeConditionVariable(c);
return 0;
}
static int pthread_cond_broadcast(pthread_cond_t *c)
{
WakeAllConditionVariable(c);
return 0;
}
static int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
{
pthread_testcancel();
SleepConditionVariableCS(c, m, INFINITE);
return 0;
}
static int pthread_cond_destroy(pthread_cond_t *c)
{
(void) c;
return 0;
}
static int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t)
{
unsigned long long tm = _pthread_rel_time_in_ms(t);
pthread_testcancel();
if (!SleepConditionVariableCS(c, m, tm)) return ETIMEDOUT;
/* We can have a spurious wakeup after the timeout */
if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT;
return 0;
}
static int pthread_condattr_destroy(pthread_condattr_t *a)
{
(void) a;
return 0;
}
#define pthread_condattr_getclock(A, C) ENOTSUP
#define pthread_condattr_setclock(A, C) ENOTSUP
static int pthread_condattr_init(pthread_condattr_t *a)
{
*a = 0;
return 0;
}
static int pthread_condattr_getpshared(pthread_condattr_t *a, int *s)
{
*s = *a;
return 0;
}
static int pthread_condattr_setpshared(pthread_condattr_t *a, int s)
{
*a = s;
return 0;
}
static int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
{
(void) a;
return 0;
}
static int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
{
*a = 0;
}
static int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s)
{
*s = *a;
return 0;
}
static int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s)
{
*a = s;
return 0;
}
/* No fork() in windows - so ignore this */
#define pthread_atfork(F1,F2,F3) 0
/* Windows has rudimentary signals support */
#define pthread_kill(T, S) 0
#define pthread_sigmask(H, S1, S2) 0
/* Wrap cancellation points */
/*
#define accept(...) (pthread_testcancel(), accept(__VA_ARGS__))
#define aio_suspend(...) (pthread_testcancel(), aio_suspend(__VA_ARGS__))
#define clock_nanosleep(...) (pthread_testcancel(), clock_nanosleep(__VA_ARGS__))
#define close(...) (pthread_testcancel(), close(__VA_ARGS__))
#define connect(...) (pthread_testcancel(), connect(__VA_ARGS__))
#define creat(...) (pthread_testcancel(), creat(__VA_ARGS__))
#define fcntl(...) (pthread_testcancel(), fcntl(__VA_ARGS__))
#define fdatasync(...) (pthread_testcancel(), fdatasync(__VA_ARGS__))
#define fsync(...) (pthread_testcancel(), fsync(__VA_ARGS__))
#define getmsg(...) (pthread_testcancel(), getmsg(__VA_ARGS__))
#define getpmsg(...) (pthread_testcancel(), getpmsg(__VA_ARGS__))
#define lockf(...) (pthread_testcancel(), lockf(__VA_ARGS__))
#define mg_receive(...) (pthread_testcancel(), mg_receive(__VA_ARGS__))
#define mg_send(...) (pthread_testcancel(), mg_send(__VA_ARGS__))
#define mg_timedreceive(...) (pthread_testcancel(), mg_timedreceive(__VA_ARGS__))
#define mg_timessend(...) (pthread_testcancel(), mg_timedsend(__VA_ARGS__))
#define msgrcv(...) (pthread_testcancel(), msgrecv(__VA_ARGS__))
#define msgsnd(...) (pthread_testcancel(), msgsnd(__VA_ARGS__))
#define msync(...) (pthread_testcancel(), msync(__VA_ARGS__))
#define nanosleep(...) (pthread_testcancel(), nanosleep(__VA_ARGS__))
#define open(...) (pthread_testcancel(), open(__VA_ARGS__))
#define pause(...) (pthread_testcancel(), pause(__VA_ARGS__))
#define poll(...) (pthread_testcancel(), poll(__VA_ARGS__))
#define pread(...) (pthread_testcancel(), pread(__VA_ARGS__))
#define pselect(...) (pthread_testcancel(), pselect(__VA_ARGS__))
#define putmsg(...) (pthread_testcancel(), putmsg(__VA_ARGS__))
#define putpmsg(...) (pthread_testcancel(), putpmsg(__VA_ARGS__))
#define pwrite(...) (pthread_testcancel(), pwrite(__VA_ARGS__))
#define read(...) (pthread_testcancel(), read(__VA_ARGS__))
#define readv(...) (pthread_testcancel(), readv(__VA_ARGS__))
#define recv(...) (pthread_testcancel(), recv(__VA_ARGS__))
#define recvfrom(...) (pthread_testcancel(), recvfrom(__VA_ARGS__))
#define recvmsg(...) (pthread_testcancel(), recvmsg(__VA_ARGS__))
#define select(...) (pthread_testcancel(), select(__VA_ARGS__))
#define sem_timedwait(...) (pthread_testcancel(), sem_timedwait(__VA_ARGS__))
#define sem_wait(...) (pthread_testcancel(), sem_wait(__VA_ARGS__))
#define send(...) (pthread_testcancel(), send(__VA_ARGS__))
#define sendmsg(...) (pthread_testcancel(), sendmsg(__VA_ARGS__))
#define sendto(...) (pthread_testcancel(), sendto(__VA_ARGS__))
#define sigpause(...) (pthread_testcancel(), sigpause(__VA_ARGS__))
#define sigsuspend(...) (pthread_testcancel(), sigsuspend(__VA_ARGS__))
#define sigwait(...) (pthread_testcancel(), sigwait(__VA_ARGS__))
#define sigwaitinfo(...) (pthread_testcancel(), sigwaitinfo(__VA_ARGS__))
#define sleep(...) (pthread_testcancel(), sleep(__VA_ARGS__))
//#define Sleep(...) (pthread_testcancel(), Sleep(__VA_ARGS__))
#define system(...) (pthread_testcancel(), system(__VA_ARGS__))
#define access(...) (pthread_testcancel(), access(__VA_ARGS__))
#define asctime(...) (pthread_testcancel(), asctime(__VA_ARGS__))
#define asctime_r(...) (pthread_testcancel(), asctime_r(__VA_ARGS__))
#define catclose(...) (pthread_testcancel(), catclose(__VA_ARGS__))
#define catgets(...) (pthread_testcancel(), catgets(__VA_ARGS__))
#define catopen(...) (pthread_testcancel(), catopen(__VA_ARGS__))
#define closedir(...) (pthread_testcancel(), closedir(__VA_ARGS__))
#define closelog(...) (pthread_testcancel(), closelog(__VA_ARGS__))
#define ctermid(...) (pthread_testcancel(), ctermid(__VA_ARGS__))
#define ctime(...) (pthread_testcancel(), ctime(__VA_ARGS__))
#define ctime_r(...) (pthread_testcancel(), ctime_r(__VA_ARGS__))
#define dbm_close(...) (pthread_testcancel(), dbm_close(__VA_ARGS__))
#define dbm_delete(...) (pthread_testcancel(), dbm_delete(__VA_ARGS__))
#define dbm_fetch(...) (pthread_testcancel(), dbm_fetch(__VA_ARGS__))
#define dbm_nextkey(...) (pthread_testcancel(), dbm_nextkey(__VA_ARGS__))
#define dbm_open(...) (pthread_testcancel(), dbm_open(__VA_ARGS__))
#define dbm_store(...) (pthread_testcancel(), dbm_store(__VA_ARGS__))
#define dlclose(...) (pthread_testcancel(), dlclose(__VA_ARGS__))
#define dlopen(...) (pthread_testcancel(), dlopen(__VA_ARGS__))
#define endgrent(...) (pthread_testcancel(), endgrent(__VA_ARGS__))
#define endhostent(...) (pthread_testcancel(), endhostent(__VA_ARGS__))
#define endnetent(...) (pthread_testcancel(), endnetent(__VA_ARGS__))
#define endprotoent(...) (pthread_testcancel(), endprotoend(__VA_ARGS__))
#define endpwent(...) (pthread_testcancel(), endpwent(__VA_ARGS__))
#define endservent(...) (pthread_testcancel(), endservent(__VA_ARGS__))
#define endutxent(...) (pthread_testcancel(), endutxent(__VA_ARGS__))
#define fclose(...) (pthread_testcancel(), fclose(__VA_ARGS__))
#define fflush(...) (pthread_testcancel(), fflush(__VA_ARGS__))
#define fgetc(...) (pthread_testcancel(), fgetc(__VA_ARGS__))
#define fgetpos(...) (pthread_testcancel(), fgetpos(__VA_ARGS__))
#define fgets(...) (pthread_testcancel(), fgets(__VA_ARGS__))
#define fgetwc(...) (pthread_testcancel(), fgetwc(__VA_ARGS__))
#define fgetws(...) (pthread_testcancel(), fgetws(__VA_ARGS__))
#define fmtmsg(...) (pthread_testcancel(), fmtmsg(__VA_ARGS__))
#define fopen(...) (pthread_testcancel(), fopen(__VA_ARGS__))
#define fpathconf(...) (pthread_testcancel(), fpathconf(__VA_ARGS__))
#define fprintf(...) (pthread_testcancel(), fprintf(__VA_ARGS__))
#define fputc(...) (pthread_testcancel(), fputc(__VA_ARGS__))
#define fputs(...) (pthread_testcancel(), fputs(__VA_ARGS__))
#define fputwc(...) (pthread_testcancel(), fputwc(__VA_ARGS__))
#define fputws(...) (pthread_testcancel(), fputws(__VA_ARGS__))
#define fread(...) (pthread_testcancel(), fread(__VA_ARGS__))
#define freopen(...) (pthread_testcancel(), freopen(__VA_ARGS__))
#define fscanf(...) (pthread_testcancel(), fscanf(__VA_ARGS__))
#define fseek(...) (pthread_testcancel(), fseek(__VA_ARGS__))
#define fseeko(...) (pthread_testcancel(), fseeko(__VA_ARGS__))
#define fsetpos(...) (pthread_testcancel(), fsetpos(__VA_ARGS__))
#define fstat(...) (pthread_testcancel(), fstat(__VA_ARGS__))
#define ftell(...) (pthread_testcancel(), ftell(__VA_ARGS__))
#define ftello(...) (pthread_testcancel(), ftello(__VA_ARGS__))
#define ftw(...) (pthread_testcancel(), ftw(__VA_ARGS__))
#define fwprintf(...) (pthread_testcancel(), fwprintf(__VA_ARGS__))
#define fwrite(...) (pthread_testcancel(), fwrite(__VA_ARGS__))
#define fwscanf(...) (pthread_testcancel(), fwscanf(__VA_ARGS__))
#define getaddrinfo(...) (pthread_testcancel(), getaddrinfo(__VA_ARGS__))
#define getc(...) (pthread_testcancel(), getc(__VA_ARGS__))
#define getc_unlocked(...) (pthread_testcancel(), getc_unlocked(__VA_ARGS__))
#define getchar(...) (pthread_testcancel(), getchar(__VA_ARGS__))
#define getchar_unlocked(...) (pthread_testcancel(), getchar_unlocked(__VA_ARGS__))
#define getcwd(...) (pthread_testcancel(), getcwd(__VA_ARGS__))
#define getdate(...) (pthread_testcancel(), getdate(__VA_ARGS__))
#define getgrent(...) (pthread_testcancel(), getgrent(__VA_ARGS__))
#define getgrgid(...) (pthread_testcancel(), getgrgid(__VA_ARGS__))
#define getgrgid_r(...) (pthread_testcancel(), getgrgid_r(__VA_ARGS__))
#define gergrnam(...) (pthread_testcancel(), getgrnam(__VA_ARGS__))
#define getgrnam_r(...) (pthread_testcancel(), getgrnam_r(__VA_ARGS__))
#define gethostbyaddr(...) (pthread_testcancel(), gethostbyaddr(__VA_ARGS__))
#define gethostbyname(...) (pthread_testcancel(), gethostbyname(__VA_ARGS__))
#define gethostent(...) (pthread_testcancel(), gethostent(__VA_ARGS__))
#define gethostid(...) (pthread_testcancel(), gethostid(__VA_ARGS__))
#define gethostname(...) (pthread_testcancel(), gethostname(__VA_ARGS__))
#define getlogin(...) (pthread_testcancel(), getlogin(__VA_ARGS__))
#define getlogin_r(...) (pthread_testcancel(), getlogin_r(__VA_ARGS__))
#define getnameinfo(...) (pthread_testcancel(), getnameinfo(__VA_ARGS__))
#define getnetbyaddr(...) (pthread_testcancel(), getnetbyaddr(__VA_ARGS__))
#define getnetbyname(...) (pthread_testcancel(), getnetbyname(__VA_ARGS__))
#define getnetent(...) (pthread_testcancel(), getnetent(__VA_ARGS__))
#define getopt(...) (pthread_testcancel(), getopt(__VA_ARGS__))
#define getprotobyname(...) (pthread_testcancel(), getprotobyname(__VA_ARGS__))
#define getprotobynumber(...) (pthread_testcancel(), getprotobynumber(__VA_ARGS__))
#define getprotoent(...) (pthread_testcancel(), getprotoent(__VA_ARGS__))
#define getpwent(...) (pthread_testcancel(), getpwent(__VA_ARGS__))
#define getpwnam(...) (pthread_testcancel(), getpwnam(__VA_ARGS__))
#define getpwnam_r(...) (pthread_testcancel(), getpwnam_r(__VA_ARGS__))
#define getpwuid(...) (pthread_testcancel(), getpwuid(__VA_ARGS__))
#define getpwuid_r(...) (pthread_testcancel(), getpwuid_r(__VA_ARGS__))
#define gets(...) (pthread_testcancel(), gets(__VA_ARGS__))
#define getservbyname(...) (pthread_testcancel(), getservbyname(__VA_ARGS__))
#define getservbyport(...) (pthread_testcancel(), getservbyport(__VA_ARGS__))
#define getservent(...) (pthread_testcancel(), getservent(__VA_ARGS__))
#define getutxent(...) (pthread_testcancel(), getutxent(__VA_ARGS__))
#define getutxid(...) (pthread_testcancel(), getutxid(__VA_ARGS__))
#define getutxline(...) (pthread_testcancel(), getutxline(__VA_ARGS__))
#undef getwc
#define getwc(...) (pthread_testcancel(), getwc(__VA_ARGS__))
#undef getwchar
#define getwchar(...) (pthread_testcancel(), getwchar(__VA_ARGS__))
#define getwd(...) (pthread_testcancel(), getwd(__VA_ARGS__))
#define glob(...) (pthread_testcancel(), glob(__VA_ARGS__))
#define iconv_close(...) (pthread_testcancel(), iconv_close(__VA_ARGS__))
#define iconv_open(...) (pthread_testcancel(), iconv_open(__VA_ARGS__))
#define ioctl(...) (pthread_testcancel(), ioctl(__VA_ARGS__))
#define link(...) (pthread_testcancel(), link(__VA_ARGS__))
#define localtime(...) (pthread_testcancel(), localtime(__VA_ARGS__))
#define localtime_r(...) (pthread_testcancel(), localtime_r(__VA_ARGS__))
#define lseek(...) (pthread_testcancel(), lseek(__VA_ARGS__))
#define lstat(...) (pthread_testcancel(), lstat(__VA_ARGS__))
#define mkstemp(...) (pthread_testcancel(), mkstemp(__VA_ARGS__))
#define nftw(...) (pthread_testcancel(), nftw(__VA_ARGS__))
#define opendir(...) (pthread_testcancel(), opendir(__VA_ARGS__))
#define openlog(...) (pthread_testcancel(), openlog(__VA_ARGS__))
#define pathconf(...) (pthread_testcancel(), pathconf(__VA_ARGS__))
#define pclose(...) (pthread_testcancel(), pclose(__VA_ARGS__))
#define perror(...) (pthread_testcancel(), perror(__VA_ARGS__))
#define popen(...) (pthread_testcancel(), popen(__VA_ARGS__))
#define posix_fadvise(...) (pthread_testcancel(), posix_fadvise(__VA_ARGS__))
#define posix_fallocate(...) (pthread_testcancel(), posix_fallocate(__VA_ARGS__))
#define posix_madvise(...) (pthread_testcancel(), posix_madvise(__VA_ARGS__))
#define posix_openpt(...) (pthread_testcancel(), posix_openpt(__VA_ARGS__))
#define posix_spawn(...) (pthread_testcancel(), posix_spawn(__VA_ARGS__))
#define posix_spawnp(...) (pthread_testcancel(), posix_spawnp(__VA_ARGS__))
#define posix_trace_clear(...) (pthread_testcancel(), posix_trace_clear(__VA_ARGS__))
#define posix_trace_close(...) (pthread_testcancel(), posix_trace_close(__VA_ARGS__))
#define posix_trace_create(...) (pthread_testcancel(), posix_trace_create(__VA_ARGS__))
#define posix_trace_create_withlog(...) (pthread_testcancel(), posix_trace_create_withlog(__VA_ARGS__))
#define posix_trace_eventtypelist_getne(...) (pthread_testcancel(), posix_trace_eventtypelist_getne(__VA_ARGS__))
#define posix_trace_eventtypelist_rewin(...) (pthread_testcancel(), posix_trace_eventtypelist_rewin(__VA_ARGS__))
#define posix_trace_flush(...) (pthread_testcancel(), posix_trace_flush(__VA_ARGS__))
#define posix_trace_get_attr(...) (pthread_testcancel(), posix_trace_get_attr(__VA_ARGS__))
#define posix_trace_get_filter(...) (pthread_testcancel(), posix_trace_get_filter(__VA_ARGS__))
#define posix_trace_get_status(...) (pthread_testcancel(), posix_trace_get_status(__VA_ARGS__))
#define posix_trace_getnext_event(...) (pthread_testcancel(), posix_trace_getnext_event(__VA_ARGS__))
#define posix_trace_open(...) (pthread_testcancel(), posix_trace_open(__VA_ARGS__))
#define posix_trace_rewind(...) (pthread_testcancel(), posix_trace_rewind(__VA_ARGS__))
#define posix_trace_setfilter(...) (pthread_testcancel(), posix_trace_setfilter(__VA_ARGS__))
#define posix_trace_shutdown(...) (pthread_testcancel(), posix_trace_shutdown(__VA_ARGS__))
#define posix_trace_timedgetnext_event(...) (pthread_testcancel(), posix_trace_timedgetnext_event(__VA_ARGS__))
#define posix_typed_mem_open(...) (pthread_testcancel(), posix_typed_mem_open(__VA_ARGS__))
#define printf(...) (pthread_testcancel(), printf(__VA_ARGS__))
#define putc(...) (pthread_testcancel(), putc(__VA_ARGS__))
#define putc_unlocked(...) (pthread_testcancel(), putc_unlocked(__VA_ARGS__))
#define putchar(...) (pthread_testcancel(), putchar(__VA_ARGS__))
#define putchar_unlocked(...) (pthread_testcancel(), putchar_unlocked(__VA_ARGS__))
#define puts(...) (pthread_testcancel(), puts(__VA_ARGS__))
#define pututxline(...) (pthread_testcancel(), pututxline(__VA_ARGS__))
#undef putwc
#define putwc(...) (pthread_testcancel(), putwc(__VA_ARGS__))
#undef putwchar
#define putwchar(...) (pthread_testcancel(), putwchar(__VA_ARGS__))
#define readdir(...) (pthread_testcancel(), readdir(__VA_ARSG__))
#define readdir_r(...) (pthread_testcancel(), readdir_r(__VA_ARGS__))
#define remove(...) (pthread_testcancel(), remove(__VA_ARGS__))
#define rename(...) (pthread_testcancel(), rename(__VA_ARGS__))
#define rewind(...) (pthread_testcancel(), rewind(__VA_ARGS__))
#define rewinddir(...) (pthread_testcancel(), rewinddir(__VA_ARGS__))
#define scanf(...) (pthread_testcancel(), scanf(__VA_ARGS__))
#define seekdir(...) (pthread_testcancel(), seekdir(__VA_ARGS__))
#define semop(...) (pthread_testcancel(), semop(__VA_ARGS__))
#define setgrent(...) (pthread_testcancel(), setgrent(__VA_ARGS__))
#define sethostent(...) (pthread_testcancel(), sethostemt(__VA_ARGS__))
#define setnetent(...) (pthread_testcancel(), setnetent(__VA_ARGS__))
#define setprotoent(...) (pthread_testcancel(), setprotoent(__VA_ARGS__))
#define setpwent(...) (pthread_testcancel(), setpwent(__VA_ARGS__))
#define setservent(...) (pthread_testcancel(), setservent(__VA_ARGS__))
#define setutxent(...) (pthread_testcancel(), setutxent(__VA_ARGS__))
#define stat(...) (pthread_testcancel(), stat(__VA_ARGS__))
#define strerror(...) (pthread_testcancel(), strerror(__VA_ARGS__))
#define strerror_r(...) (pthread_testcancel(), strerror_r(__VA_ARGS__))
#define strftime(...) (pthread_testcancel(), strftime(__VA_ARGS__))
#define symlink(...) (pthread_testcancel(), symlink(__VA_ARGS__))
#define sync(...) (pthread_testcancel(), sync(__VA_ARGS__))
#define syslog(...) (pthread_testcancel(), syslog(__VA_ARGS__))
#define tmpfile(...) (pthread_testcancel(), tmpfile(__VA_ARGS__))
#define tmpnam(...) (pthread_testcancel(), tmpnam(__VA_ARGS__))
#define ttyname(...) (pthread_testcancel(), ttyname(__VA_ARGS__))
#define ttyname_r(...) (pthread_testcancel(), ttyname_r(__VA_ARGS__))
#define tzset(...) (pthread_testcancel(), tzset(__VA_ARGS__))
#define ungetc(...) (pthread_testcancel(), ungetc(__VA_ARGS__))
#define ungetwc(...) (pthread_testcancel(), ungetwc(__VA_ARGS__))
#define unlink(...) (pthread_testcancel(), unlink(__VA_ARGS__))
#define vfprintf(...) (pthread_testcancel(), vfprintf(__VA_ARGS__))
#define vfwprintf(...) (pthread_testcancel(), vfwprintf(__VA_ARGS__))
#define vprintf(...) (pthread_testcancel(), vprintf(__VA_ARGS__))
#define vwprintf(...) (pthread_testcancel(), vwprintf(__VA_ARGS__))
#define wcsftime(...) (pthread_testcancel(), wcsftime(__VA_ARGS__))
#define wordexp(...) (pthread_testcancel(), wordexp(__VA_ARGS__))
#define wprintf(...) (pthread_testcancel(), wprintf(__VA_ARGS__))
#define wscanf(...) (pthread_testcancel(), wscanf(__VA_ARGS__))
*/
#endif /* WIN_PTHREADS */
#include "pthread.h"
volatile long _pthread_cancelling;
int _pthread_concur;
/* Will default to zero as needed */
pthread_once_t _pthread_tls_once;
DWORD _pthread_tls;
/* Note initializer is zero, so this works */
pthread_rwlock_t _pthread_key_lock;
long _pthread_key_max;
long _pthread_key_sch;
void (**_pthread_key_dest)(void *);
\ No newline at end of file
/* This is an implementation of the threads API of POSIX 1003.1-2001.
*
* --------------------------------------------------------------------------
/*
* Posix Threads library for Microsoft Windows
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
* Use at own risk, there is no implied warranty to this code.
* It uses undocumented features of Microsoft Windows that can change
* at any time in the future.
*
* Contact Email: rpj@callisto.canberra.edu.au
* (C) 2010 Lockless Inc.
* All rights reserved.
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * 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.
* * Neither the name of Lockless Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
* 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 HOLDER 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.
*/
#if !defined( PTHREAD_H )
#define PTHREAD_H
/*
* See the README file for an explanation of the pthreads-win32 version
* numbering scheme and how the DLL is named etc.
*/
#define PTW32_VERSION 2,8,0,0
#define PTW32_VERSION_STRING "2, 8, 0, 0\0"
/* There are three implementations of cancel cleanup.
* Note that pthread.h is included in both application
* compilation units and also internally for the library.
* The code here and within the library aims to work
* for all reasonable combinations of environments.
*
* The three implementations are:
*
* WIN32 SEH
* C
* C++
*
* Please note that exiting a push/pop block via
* "return", "exit", "break", or "continue" will
* lead to different behaviour amongst applications
* depending upon whether the library was built
* using SEH, C++, or C. For example, a library built
* with SEH will call the cleanup routine, while both
* C++ and C built versions will not.
* You may want to use the MingW64 winpthreads library instead.
* It is based on this, but adds error checking.
*/
/*
* Define defaults for cleanup code.
* Note: Unless the build explicitly defines one of the following, then
* we default to standard C style cleanup. This style uses setjmp/longjmp
* in the cancelation and thread exit implementations and therefore won't
* do stack unwinding if linked to applications that have it (e.g.
* C++ apps). This is currently consistent with most/all commercial Unix
* POSIX threads implementations.
* Version 1.0.1 Released 2 Feb 2012
* Fixes pthread_barrier_destroy() to wait for threads to exit the barrier.
*/
#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C )
# define __CLEANUP_C
#endif
#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC))
#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler.
#endif
#ifndef WIN_PTHREADS
#define WIN_PTHREADS
/*
* Stop here if we are being included by the resource compiler.
*/
#ifndef RC_INVOKED
#undef PTW32_LEVEL
#include <windows.h>
#include <intrin.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/timeb.h>
#include <process.h>
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#define ETIMEDOUT 110
#define ENOTSUP 134
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTHREAD_CANCEL_DISABLE 0
#define PTHREAD_CANCEL_ENABLE 0x01
#define PTW32_LEVEL_MAX 3
#define PTHREAD_CANCEL_DEFERRED 0
#define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#define PTHREAD_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 0x04
#ifdef _UWIN
# define HAVE_STRUCT_TIMESPEC 1
# define HAVE_SIGNAL_H 1
# undef HAVE_CONFIG_H
# pragma comment(lib, "pthread")
#endif
#define PTHREAD_EXPLICT_SCHED 0
#define PTHREAD_INHERIT_SCHED 0x08
/*
* -------------------------------------------------------------
*
*
* Module: pthread.h
*
* Purpose:
* Provides an implementation of PThreads based upon the
* standard:
*
* POSIX 1003.1-2001
* and
* The Single Unix Specification version 3
*
* (these two are equivalent)
*
* in order to enhance code portability between Windows,
* various commercial Unix implementations, and Linux.
*
* See the ANNOUNCE file for a full list of conforming
* routines and defined constants, and a list of missing
* routines and constants not defined in this implementation.
*
* Authors:
* There have been many contributors to this library.
* The initial implementation was contributed by
* John Bossom, and several others have provided major
* sections or revisions of parts of the implementation.
* Often significant effort has been contributed to
* find and fix important bugs and other problems to
* improve the reliability of the library, which sometimes
* is not reflected in the amount of code which changed as
* result.
* As much as possible, the contributors are acknowledged
* in the ChangeLog file in the source code distribution
* where their changes are noted in detail.
*
* Contributors are listed in the CONTRIBUTORS file.
*
* As usual, all bouquets go to the contributors, and all
* brickbats go to the project maintainer.
*
* Maintainer:
* The code base for this project is coordinated and
* eventually pre-tested, packaged, and made available by
*
* Ross Johnson <rpj@callisto.canberra.edu.au>
*
* QA Testers:
* Ultimately, the library is tested in the real world by
* a host of competent and demanding scientists and
* engineers who report bugs and/or provide solutions
* which are then fixed or incorporated into subsequent
* versions of the library. Each time a bug is fixed, a
* test case is written to prove the fix and ensure
* that later changes to the code don't reintroduce the
* same error. The number of test cases is slowly growing
* and therefore so is the code reliability.
*
* Compliance:
* See the file ANNOUNCE for the list of implemented
* and not-implemented routines and defined options.
* Of course, these are all defined is this file as well.
*
* Web site:
* The source code and other information about this library
* are available from
*
* http://sources.redhat.com/pthreads-win32/
*
* -------------------------------------------------------------
*/
#define PTHREAD_SCOPE_PROCESS 0
#define PTHREAD_SCOPE_SYSTEM 0x10
/* Try to avoid including windows.h */
#if defined(__MINGW32__) && defined(__cplusplus)
#define PTW32_INCLUDE_WINDOWS_H
#endif
#define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE)
#ifdef PTW32_INCLUDE_WINDOWS_H
#include <windows.h>
#define PTHREAD_CANCELED ((void *) 0xDEADBEEF)
#define PTHREAD_ONCE_INIT 0
#define PTHREAD_MUTEX_INITIALIZER {(void*)-1,-1,0,0,0,0}
#define PTHREAD_RWLOCK_INITIALIZER {0}
#define PTHREAD_COND_INITIALIZER {0}
#define PTHREAD_BARRIER_INITIALIZER \
{0,0,PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER}
#define PTHREAD_SPINLOCK_INITIALIZER 0
#define PTHREAD_DESTRUCTOR_ITERATIONS 256
#define PTHREAD_KEYS_MAX (1<<20)
#define PTHREAD_MUTEX_NORMAL 0
#define PTHREAD_MUTEX_ERRORCHECK 1
#define PTHREAD_MUTEX_RECURSIVE 2
#define PTHREAD_MUTEX_DEFAULT 3
#define PTHREAD_MUTEX_SHARED 4
#define PTHREAD_MUTEX_PRIVATE 0
#define PTHREAD_PRIO_NONE 0
#define PTHREAD_PRIO_INHERIT 8
#define PTHREAD_PRIO_PROTECT 16
#define PTHREAD_PRIO_MULT 32
#define PTHREAD_PROCESS_SHARED 0
#define PTHREAD_PROCESS_PRIVATE 1
#define PTHREAD_BARRIER_SERIAL_THREAD 1
#ifdef _X86_
#define INTERLOCKED_COMPARE_EXCHANGE(destination, exchange, comparand) _InterlockedCompareExchange((volatile long*) destination, (long) exchange, (long) comparand)
#else
#define INTERLOCKED_COMPARE_EXCHANGE(destination, exchange, comparand) _InterlockedCompareExchangePointer((volatile PVOID*) destination, (void*) exchange, (void*) comparand)
#endif
#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__)
/*
* VC++6.0 or early compiler's header has no DWORD_PTR type.
*/
typedef unsigned long DWORD_PTR;
#if defined(PTHREAD_BUILDING_SHARED_LIBRARY)
#define PTHREAD_EXPORT __declspec(dllexport)
#elif defined(PTHREAD_BUILDING_STATIC_LIBRARY)
#define PTHREAD_EXPORT
#else
#define PTHREAD_EXPORT __declspec(dllimport)
#endif
/*
* -----------------
* autoconf switches
* -----------------
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifndef NEED_FTIME
#include <time.h>
#else /* NEED_FTIME */
/* use native WIN32 time API */
#endif /* NEED_FTIME */
/* Windows doesn't have this, so declare it ourselves. */
struct timespec
{
/* long long in windows is the same as long in unix for 64bit */
long long tv_sec;
long long tv_nsec;
};
#if HAVE_SIGNAL_H
#include <signal.h>
#endif /* HAVE_SIGNAL_H */
typedef struct _pthread_cleanup _pthread_cleanup;
struct _pthread_cleanup
{
void (*func)(void *);
void *arg;
_pthread_cleanup *next;
};
#include <setjmp.h>
#include <limits.h>
struct _pthread_v
{
void *ret_arg;
void *(* func)(void *);
_pthread_cleanup *clean;
HANDLE h;
int cancelled;
unsigned p_state;
int keymax;
void **keyval;
jmp_buf jb;
};
/*
* Boolean values to make us independent of system includes.
*/
enum {
PTW32_FALSE = 0,
PTW32_TRUE = (! PTW32_FALSE)
typedef struct _pthread_v *pthread_t;
typedef struct pthread_barrier_t pthread_barrier_t;
struct pthread_barrier_t
{
int count;
int total;
CRITICAL_SECTION m;
CONDITION_VARIABLE cv;
};
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
typedef struct pthread_attr_t pthread_attr_t;
struct pthread_attr_t
{
unsigned p_state;
void *stack;
size_t s_size;
};
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
typedef long pthread_once_t;
typedef unsigned pthread_mutexattr_t;
typedef SRWLOCK pthread_rwlock_t;
typedef CRITICAL_SECTION pthread_mutex_t;
typedef unsigned pthread_key_t;
typedef void *pthread_barrierattr_t;
typedef long pthread_spinlock_t;
typedef int pthread_condattr_t;
typedef CONDITION_VARIABLE pthread_cond_t;
typedef int pthread_rwlockattr_t;
/*
*
*/
extern PTHREAD_EXPORT volatile long _pthread_cancelling;
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
extern PTHREAD_EXPORT int _pthread_concur;
/*
* Several systems don't define some error numbers.
*/
#ifndef ENOTSUP
# define ENOTSUP 48 /* This is the value in Solaris. */
#endif
/* Will default to zero as needed */
extern PTHREAD_EXPORT pthread_once_t _pthread_tls_once;
extern PTHREAD_EXPORT DWORD _pthread_tls;
#ifndef ETIMEDOUT
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif
/* Note initializer is zero, so this works */
extern PTHREAD_EXPORT pthread_rwlock_t _pthread_key_lock;
extern PTHREAD_EXPORT long _pthread_key_max;
extern PTHREAD_EXPORT long _pthread_key_sch;
extern PTHREAD_EXPORT void (**_pthread_key_dest)(void *);
#ifndef ENOSYS
# define ENOSYS 140 /* Semi-arbitrary value */
#endif
#ifndef EDEADLK
# ifdef EDEADLOCK
# define EDEADLK EDEADLOCK
# else
# define EDEADLK 36 /* This is the value in MSVC. */
# endif
#endif
#define pthread_cleanup_push(F, A)\
{\
const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\
_ReadWriteBarrier();\
pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\
_ReadWriteBarrier()
#include <sched.h>
/* Note that if async cancelling is used, then there is a race here */
#define pthread_cleanup_pop(E)\
(pthread_self()->clean = _pthread_cup.next, (E?_pthread_cup.func(_pthread_cup.arg):0));}
/*
* To avoid including windows.h we define only those things that we
* actually need from it.
*/
#ifndef PTW32_INCLUDE_WINDOWS_H
#ifndef HANDLE
# define PTW32__HANDLE_DEF
# define HANDLE void *
#endif
#ifndef DWORD
# define PTW32__DWORD_DEF
# define DWORD unsigned long
#endif
static void _pthread_once_cleanup(pthread_once_t *o)
{
*o = 0;
}
static pthread_t pthread_self(void);
static int pthread_once(pthread_once_t *o, void (*func)(void))
{
long state = *o;
_ReadWriteBarrier();
while (state != 1)
{
if (!state)
{
if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
#ifdef __cplusplus
pthread_cleanup_push(reinterpret_cast<void (__cdecl *)(void *)>(_pthread_once_cleanup), o);
#else
pthread_cleanup_push(_pthread_once_cleanup, o);
#endif
func();
pthread_cleanup_pop(0);
#ifndef HAVE_STRUCT_TIMESPEC
#define HAVE_STRUCT_TIMESPEC 1
struct timespec {
long tv_sec;
long tv_nsec;
};
#endif /* HAVE_STRUCT_TIMESPEC */
/* Mark as done */
*o = 1;
#ifndef SIG_BLOCK
#define SIG_BLOCK 0
#endif /* SIG_BLOCK */
return 0;
}
}
#ifndef SIG_UNBLOCK
#define SIG_UNBLOCK 1
#endif /* SIG_UNBLOCK */
YieldProcessor();
#ifndef SIG_SETMASK
#define SIG_SETMASK 2
#endif /* SIG_SETMASK */
_ReadWriteBarrier();
#ifdef __cplusplus
extern "C"
state = *o;
}
/* Done */
return 0;
}
static int _pthread_once_raw(pthread_once_t *o, void (*func)(void))
{
#endif /* __cplusplus */
long state = *o;
/*
* -------------------------------------------------------------
*
* POSIX 1003.1-2001 Options
* =========================
*
* Options are normally set in <unistd.h>, which is not provided
* with pthreads-win32.
*
* For conformance with the Single Unix Specification (version 3), all of the
* options below are defined, and have a value of either -1 (not supported)
* or 200112L (supported).
*
* These options can neither be left undefined nor have a value of 0, because
* either indicates that sysconf(), which is not implemented, may be used at
* runtime to check the status of the option.
*
* _POSIX_THREADS (== 200112L)
* If == 200112L, you can use threads
*
* _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
* If == 200112L, you can control the size of a thread's
* stack
* pthread_attr_getstacksize
* pthread_attr_setstacksize
*
* _POSIX_THREAD_ATTR_STACKADDR (== -1)
* If == 200112L, you can allocate and control a thread's
* stack. If not supported, the following functions
* will return ENOSYS, indicating they are not
* supported:
* pthread_attr_getstackaddr
* pthread_attr_setstackaddr
*
* _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
* If == 200112L, you can use realtime scheduling.
* This option indicates that the behaviour of some
* implemented functions conforms to the additional TPS
* requirements in the standard. E.g. rwlocks favour
* writers over readers when threads have equal priority.
*
* _POSIX_THREAD_PRIO_INHERIT (== -1)
* If == 200112L, you can create priority inheritance
* mutexes.
* pthread_mutexattr_getprotocol +
* pthread_mutexattr_setprotocol +
*
* _POSIX_THREAD_PRIO_PROTECT (== -1)
* If == 200112L, you can create priority ceiling mutexes
* Indicates the availability of:
* pthread_mutex_getprioceiling
* pthread_mutex_setprioceiling
* pthread_mutexattr_getprioceiling
* pthread_mutexattr_getprotocol +
* pthread_mutexattr_setprioceiling
* pthread_mutexattr_setprotocol +
*
* _POSIX_THREAD_PROCESS_SHARED (== -1)
* If set, you can create mutexes and condition
* variables that can be shared with another
* process.If set, indicates the availability
* of:
* pthread_mutexattr_getpshared
* pthread_mutexattr_setpshared
* pthread_condattr_getpshared
* pthread_condattr_setpshared
*
* _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
* If == 200112L you can use the special *_r library
* functions that provide thread-safe behaviour
*
* _POSIX_READER_WRITER_LOCKS (== 200112L)
* If == 200112L, you can use read/write locks
*
* _POSIX_SPIN_LOCKS (== 200112L)
* If == 200112L, you can use spin locks
*
* _POSIX_BARRIERS (== 200112L)
* If == 200112L, you can use barriers
*
* + These functions provide both 'inherit' and/or
* 'protect' protocol, based upon these macro
* settings.
*
* -------------------------------------------------------------
*/
_ReadWriteBarrier();
/*
* POSIX Options
*/
#undef _POSIX_THREADS
#define _POSIX_THREADS 200112L
while (state != 1)
{
if (!state)
{
if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
func();
/* Mark as done */
*o = 1;
#undef _POSIX_READER_WRITER_LOCKS
#define _POSIX_READER_WRITER_LOCKS 200112L
return 0;
}
}
#undef _POSIX_SPIN_LOCKS
#define _POSIX_SPIN_LOCKS 200112L
YieldProcessor();
#undef _POSIX_BARRIERS
#define _POSIX_BARRIERS 200112L
_ReadWriteBarrier();
#undef _POSIX_THREAD_SAFE_FUNCTIONS
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L
state = *o;
}
#undef _POSIX_THREAD_ATTR_STACKSIZE
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
/* Done */
return 0;
}
/*
* The following options are not supported
*/
#undef _POSIX_THREAD_ATTR_STACKADDR
#define _POSIX_THREAD_ATTR_STACKADDR -1
static int pthread_mutex_lock(pthread_mutex_t *m)
{
EnterCriticalSection(m);
return 0;
}
#undef _POSIX_THREAD_PRIO_INHERIT
#define _POSIX_THREAD_PRIO_INHERIT -1
static int pthread_mutex_unlock(pthread_mutex_t *m)
{
LeaveCriticalSection(m);
return 0;
}
#undef _POSIX_THREAD_PRIO_PROTECT
#define _POSIX_THREAD_PRIO_PROTECT -1
static int pthread_mutex_trylock(pthread_mutex_t *m)
{
return TryEnterCriticalSection(m) ? 0 : EBUSY;
}
/* TPS is not fully supported. */
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
{
(void) a;
InitializeCriticalSection(m);
#undef _POSIX_THREAD_PROCESS_SHARED
#define _POSIX_THREAD_PROCESS_SHARED -1
return 0;
}
static int pthread_mutex_destroy(pthread_mutex_t *m)
{
DeleteCriticalSection(m);
return 0;
}
/*
* POSIX 1003.1-2001 Limits
* ===========================
*
* These limits are normally set in <limits.h>, which is not provided with
* pthreads-win32.
*
* PTHREAD_DESTRUCTOR_ITERATIONS
* Maximum number of attempts to destroy
* a thread's thread-specific data on
* termination (must be at least 4)
*
* PTHREAD_KEYS_MAX
* Maximum number of thread-specific data keys
* available per process (must be at least 128)
*
* PTHREAD_STACK_MIN
* Minimum supported stack size for a thread
*
* PTHREAD_THREADS_MAX
* Maximum number of threads supported per
* process (must be at least 64).
*
* SEM_NSEMS_MAX
* The maximum number of semaphores a process can have.
* (must be at least 256)
*
* SEM_VALUE_MAX
* The maximum value a semaphore can have.
* (must be at least 32767)
*
*/
#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS
#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
#define pthread_mutex_getprioceiling(M, P) ENOTSUP
#define pthread_mutex_setprioceiling(M, P) ENOTSUP
#undef PTHREAD_DESTRUCTOR_ITERATIONS
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
static int pthread_equal(pthread_t t1, pthread_t t2)
{
return t1 == t2;
}
#undef _POSIX_THREAD_KEYS_MAX
#define _POSIX_THREAD_KEYS_MAX 128
static void pthread_testcancel(void);
#undef PTHREAD_KEYS_MAX
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
{
(void) a;
InitializeSRWLock(l);
#undef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN 0
return 0;
}
#undef _POSIX_THREAD_THREADS_MAX
#define _POSIX_THREAD_THREADS_MAX 64
static int pthread_rwlock_destroy(pthread_rwlock_t *l)
{
(void) *l;
return 0;
}
/* Arbitrary value */
#undef PTHREAD_THREADS_MAX
#define PTHREAD_THREADS_MAX 2019
static int pthread_rwlock_rdlock(pthread_rwlock_t *l)
{
pthread_testcancel();
AcquireSRWLockShared(l);
#undef _POSIX_SEM_NSEMS_MAX
#define _POSIX_SEM_NSEMS_MAX 256
return 0;
}
/* Arbitrary value */
#undef SEM_NSEMS_MAX
#define SEM_NSEMS_MAX 1024
static int pthread_rwlock_wrlock(pthread_rwlock_t *l)
{
pthread_testcancel();
AcquireSRWLockExclusive(l);
#undef _POSIX_SEM_VALUE_MAX
#define _POSIX_SEM_VALUE_MAX 32767
return 0;
}
#undef SEM_VALUE_MAX
#define SEM_VALUE_MAX INT_MAX
static void pthread_tls_init(void)
{
_pthread_tls = TlsAlloc();
/* Cannot continue if out of indexes */
if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
}
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
static int pthread_rwlock_unlock(pthread_rwlock_t *l)
{
void *state = *(void **)l;
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
if (state == (void *) 1)
{
/* Known to be an exclusive lock */
ReleaseSRWLockExclusive(l);
}
else
{
/* A shared unlock will work */
ReleaseSRWLockShared(l);
}
/*
* The Open Watcom C/C++ compiler uses a non-standard calling convention
* that passes function args in registers unless __cdecl is explicitly specified
* in exposed function prototypes.
*
* We force all calls to cdecl even though this could slow Watcom code down
* slightly. If you know that the Watcom compiler will be used to build both
* the DLL and application, then you can probably define this as a null string.
* Remember that pthread.h (this file) is used for both the DLL and application builds.
*/
#define PTW32_CDECL __cdecl
return 0;
}
#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX
# include <sys/types.h>
#else
/*
* Generic handle type - intended to extend uniqueness beyond
* that available with a simple pointer. It should scale for either
* IA-32 or IA-64.
*/
typedef struct {
void * p; /* Pointer to actual object */
unsigned int x; /* Extra information - reuse count etc */
} ptw32_handle_t;
typedef ptw32_handle_t pthread_t;
typedef struct pthread_attr_t_ * pthread_attr_t;
typedef struct pthread_once_t_ pthread_once_t;
typedef struct pthread_key_t_ * pthread_key_t;
typedef struct pthread_mutex_t_ * pthread_mutex_t;
typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t;
typedef struct pthread_cond_t_ * pthread_cond_t;
typedef struct pthread_condattr_t_ * pthread_condattr_t;
#endif
typedef struct pthread_rwlock_t_ * pthread_rwlock_t;
typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t;
typedef struct pthread_spinlock_t_ * pthread_spinlock_t;
typedef struct pthread_barrier_t_ * pthread_barrier_t;
typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t;
static void _pthread_cleanup_dest(pthread_t t)
{
int i, j;
/*
* ====================
* ====================
* POSIX Threads
* ====================
* ====================
*/
for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
{
int flag = 0;
enum {
/*
* pthread_attr_{get,set}detachstate
*/
PTHREAD_CREATE_JOINABLE = 0, /* Default */
PTHREAD_CREATE_DETACHED = 1,
for (i = 0; i < t->keymax; i++)
{
void *val = t->keyval[i];
/*
* pthread_attr_{get,set}inheritsched
*/
PTHREAD_INHERIT_SCHED = 0,
PTHREAD_EXPLICIT_SCHED = 1, /* Default */
if (val)
{
pthread_rwlock_rdlock(&_pthread_key_lock);
if ((uintptr_t) _pthread_key_dest[i] > 1)
{
/* Call destructor */
t->keyval[i] = NULL;
_pthread_key_dest[i](val);
flag = 1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
}
}
/*
* pthread_{get,set}scope
*/
PTHREAD_SCOPE_PROCESS = 0,
PTHREAD_SCOPE_SYSTEM = 1, /* Default */
/* Nothing to do? */
if (!flag) return;
}
}
/*
* pthread_setcancelstate paramters
*/
PTHREAD_CANCEL_ENABLE = 0, /* Default */
PTHREAD_CANCEL_DISABLE = 1,
static pthread_t pthread_self(void)
{
pthread_t t;
/*
* pthread_setcanceltype parameters
*/
PTHREAD_CANCEL_ASYNCHRONOUS = 0,
PTHREAD_CANCEL_DEFERRED = 1, /* Default */
_pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
/*
* pthread_mutexattr_{get,set}pshared
* pthread_condattr_{get,set}pshared
*/
PTHREAD_PROCESS_PRIVATE = 0,
PTHREAD_PROCESS_SHARED = 1,
t = (pthread_t) TlsGetValue(_pthread_tls);
/*
* pthread_barrier_wait
*/
PTHREAD_BARRIER_SERIAL_THREAD = -1
};
/* Main thread? */
if (!t)
{
t = (pthread_t) malloc(sizeof(struct _pthread_v));
/*
* ====================
* ====================
* Cancelation
* ====================
* ====================
*/
#define PTHREAD_CANCELED ((void *) -1)
/* If cannot initialize main thread, then the only thing we can do is abort */
if (!t) abort();
t->ret_arg = NULL;
t->func = NULL;
t->clean = NULL;
t->cancelled = 0;
t->p_state = PTHREAD_DEFAULT_ATTR;
t->keymax = 0;
t->keyval = NULL;
t->h = GetCurrentThread();
/*
* ====================
* ====================
* Once Key
* ====================
* ====================
*/
#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
/* Save for later */
TlsSetValue(_pthread_tls, t);
if (setjmp(t->jb))
{
/* Make sure we free ourselves if we are detached */
if (!t->h) free(t);
/* Time to die */
_endthreadex(0);
}
}
return t;
}
struct pthread_once_t_
static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
{
int done; /* indicates if user function has been executed */
void * lock;
int reserved1;
int reserved2;
};
/* Get the current state of the lock */
void *state = *(void **) l;
if (!state)
{
/* Unlocked to locked */
if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)0x11, NULL)) return 0;
return EBUSY;
}
/*
* ====================
* ====================
* Object initialisers
* ====================
* ====================
*/
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
/* A single writer exists */
if (state == (void *) 1) return EBUSY;
/*
* Compatibility with LinuxThreads
*/
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
/* Multiple writers exist? */
if ((uintptr_t) state & 14) return EBUSY;
#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
if ((void*) INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *) ((uintptr_t)state + 16), state) == state) return 0;
#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
return EBUSY;
}
#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
static int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
{
/* Try to grab lock if it has no users */
if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)1, NULL)) return 0;
return EBUSY;
}
/*
* Mutex types.
*/
enum
{
/* Compatibility with LinuxThreads */
PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP,
/* For compatibility with POSIX */
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP,
PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
};
static unsigned long long _pthread_time_in_ms(void)
{
struct __timeb64 tb;
_ftime64(&tb);
typedef struct ptw32_cleanup_t ptw32_cleanup_t;
return tb.time * 1000 + tb.millitm;
}
#if defined(_MSC_VER)
/* Disable MSVC 'anachronism used' warning */
#pragma warning( disable : 4229 )
#endif
static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
{
unsigned long long t = ts->tv_sec * 1000;
t += ts->tv_nsec / 1000000;
typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *);
return t;
}
#if defined(_MSC_VER)
#pragma warning( default : 4229 )
#endif
static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
{
unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
unsigned long long t2 = _pthread_time_in_ms();
/* Prevent underflow */
if (t1 < t2) return 0;
return t1 - t2;
}
struct ptw32_cleanup_t
static int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts)
{
ptw32_cleanup_callback_t routine;
void *arg;
struct ptw32_cleanup_t *prev;
};
unsigned long long ct = _pthread_time_in_ms();
unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
#ifdef __CLEANUP_SEH
/*
* WIN32 SEH version of cancel cleanup.
*/
pthread_testcancel();
#define pthread_cleanup_push( _rout, _arg ) \
{ \
ptw32_cleanup_t _cleanup; \
\
_cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \
_cleanup.arg = (_arg); \
__try \
{ \
#define pthread_cleanup_pop( _execute ) \
} \
__finally \
{ \
if( _execute || AbnormalTermination()) \
{ \
(*(_cleanup.routine))( _cleanup.arg ); \
} \
} \
/* Use a busy-loop */
while (1)
{
/* Try to grab lock */
if (!pthread_rwlock_tryrdlock(l)) return 0;
/* Get current time */
ct = _pthread_time_in_ms();
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
}
}
#else /* __CLEANUP_SEH */
static int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts)
{
unsigned long long ct = _pthread_time_in_ms();
unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
#ifdef __CLEANUP_C
pthread_testcancel();
/*
* C implementation of PThreads cancel cleanup
*/
/* Use a busy-loop */
while (1)
{
/* Try to grab lock */
if (!pthread_rwlock_trywrlock(l)) return 0;
#define pthread_cleanup_push( _rout, _arg ) \
{ \
ptw32_cleanup_t _cleanup; \
\
ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
/* Get current time */
ct = _pthread_time_in_ms();
#define pthread_cleanup_pop( _execute ) \
(void) ptw32_pop_cleanup( _execute ); \
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
}
}
#else /* __CLEANUP_C */
static int pthread_get_concurrency(int *val)
{
*val = _pthread_concur;
return 0;
}
#ifdef __CLEANUP_CXX
static int pthread_set_concurrency(int val)
{
_pthread_concur = val;
return 0;
}
/*
* C++ version of cancel cleanup.
* - John E. Bossom.
*/
#define pthread_getschedparam(T, P, S) ENOTSUP
#define pthread_setschedparam(T, P, S) ENOTSUP
#define pthread_getcpuclockid(T, C) ENOTSUP
class PThreadCleanup {
/*
* PThreadCleanup
*
* Purpose
* This class is a C++ helper class that is
* used to implement pthread_cleanup_push/
* pthread_cleanup_pop.
* The destructor of this class automatically
* pops the pushed cleanup routine regardless
* of how the code exits the scope
* (i.e. such as by an exception)
*/
ptw32_cleanup_callback_t cleanUpRout;
void * obj;
int executeIt;
public:
PThreadCleanup() :
cleanUpRout( 0 ),
obj( 0 ),
executeIt( 0 )
/*
* No cleanup performed
*/
{
}
static int pthread_exit(void *res)
{
pthread_t t = pthread_self();
PThreadCleanup(
ptw32_cleanup_callback_t routine,
void * arg ) :
cleanUpRout( routine ),
obj( arg ),
executeIt( 1 )
/*
* Registers a cleanup routine for 'arg'
*/
t->ret_arg = res;
_pthread_cleanup_dest(t);
longjmp(t->jb, 1);
}
static void _pthread_invoke_cancel(void)
{
_pthread_cleanup *pcup;
_InterlockedDecrement(&_pthread_cancelling);
/* Call cancel queue */
for (pcup = pthread_self()->clean; pcup; pcup = pcup->next)
{
pcup->func(pcup->arg);
}
~PThreadCleanup()
pthread_exit(PTHREAD_CANCELED);
}
static void pthread_testcancel(void)
{
if (_pthread_cancelling)
{
if ( executeIt && ((void *) cleanUpRout != (void *) 0) )
pthread_t t = pthread_self();
if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
{
(void) (*cleanUpRout)( obj );
_pthread_invoke_cancel();
}
}
}
void execute( int exec )
static int pthread_cancel(pthread_t t)
{
if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS)
{
executeIt = exec;
}
};
/* Dangerous asynchronous cancelling */
CONTEXT ctxt;
/*
* C++ implementation of PThreads cancel cleanup;
* This implementation takes advantage of a helper
* class who's destructor automatically calls the
* cleanup routine if we exit our scope weirdly
*/
#define pthread_cleanup_push( _rout, _arg ) \
{ \
PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \
(void *) (_arg) );
/* Already done? */
if (t->cancelled) return ESRCH;
#define pthread_cleanup_pop( _execute ) \
cleanup.execute( _execute ); \
}
ctxt.ContextFlags = CONTEXT_CONTROL;
SuspendThread(t->h);
GetThreadContext(t->h, &ctxt);
#ifdef _M_X64
ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
#else
ctxt.Eip = (uintptr_t) _pthread_invoke_cancel;
#endif
SetThreadContext(t->h, &ctxt);
#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
/* Also try deferred Cancelling */
t->cancelled = 1;
#endif /* __CLEANUP_CXX */
/* Notify everyone to look */
_InterlockedIncrement(&_pthread_cancelling);
#endif /* __CLEANUP_C */
ResumeThread(t->h);
}
else
{
/* Safe deferred Cancelling */
t->cancelled = 1;
#endif /* __CLEANUP_SEH */
/* Notify everyone to look */
_InterlockedIncrement(&_pthread_cancelling);
}
/*
* ===============
* ===============
* Methods
* ===============
* ===============
*/
return 0;
}
/*
* PThread Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr);
static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag)
{
return attr->p_state & flag;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr);
static int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val)
{
if (~flag & val) return EINVAL;
attr->p_state &= ~flag;
attr->p_state |= val;
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr,
int *detachstate);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr,
void **stackaddr);
static int pthread_attr_init(pthread_attr_t *attr)
{
attr->p_state = PTHREAD_DEFAULT_ATTR;
attr->stack = NULL;
attr->s_size = 0;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr,
size_t * stacksize);
static int pthread_attr_destroy(pthread_attr_t *attr)
{
/* No need to do anything */
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr,
int detachstate);
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr,
void *stackaddr);
static int pthread_attr_setdetachstate(pthread_attr_t *a, int flag)
{
return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr,
size_t stacksize);
static int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag)
{
*flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr,
struct sched_param *param);
static int pthread_attr_setinheritsched(pthread_attr_t *a, int flag)
{
return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr,
const struct sched_param *param);
static int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag)
{
*flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *,
int);
static int pthread_attr_setscope(pthread_attr_t *a, int flag)
{
return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *,
int *);
static int pthread_attr_getscope(pthread_attr_t *a, int *flag)
{
*flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr,
int inheritsched);
static int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack)
{
*stack = attr->stack;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr,
int * inheritsched);
static int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack)
{
attr->stack = stack;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *,
int);
static int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size)
{
*size = attr->s_size;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *,
int *);
static int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
{
attr->s_size = size;
return 0;
}
/*
* PThread Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid,
const pthread_attr_t * attr,
void *(*start) (void *),
void *arg);
#define pthread_attr_getguardsize(A, S) ENOTSUP
#define pthread_attr_setgaurdsize(A, S) ENOTSUP
#define pthread_attr_getschedparam(A, S) ENOTSUP
#define pthread_attr_setschedparam(A, S) ENOTSUP
#define pthread_attr_getschedpolicy(A, S) ENOTSUP
#define pthread_attr_setschedpolicy(A, S) ENOTSUP
PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1,
pthread_t t2);
static int pthread_setcancelstate(int state, int *oldstate)
{
pthread_t t = pthread_self();
PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr);
if ((state & PTHREAD_CANCEL_ENABLE) != state) return EINVAL;
if (oldstate) *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE;
t->p_state &= ~PTHREAD_CANCEL_ENABLE;
t->p_state |= state;
PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread,
void **value_ptr);
return 0;
}
PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void);
static int pthread_setcanceltype(int type, int *oldtype)
{
pthread_t t = pthread_self();
PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread);
if ((type & PTHREAD_CANCEL_ASYNCHRONOUS) != type) return EINVAL;
if (oldtype) *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS;
t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
t->p_state |= type;
PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state,
int *oldstate);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type,
int *oldtype);
static int pthread_create_wrapper(void *args)
{
struct _pthread_v *tv = (_pthread_v*) args;
int i, j;
PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void);
_pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control,
void (*init_routine) (void));
TlsSetValue(_pthread_tls, tv);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute);
if (!setjmp(tv->jb))
{
/* Call function and save return value */
tv->ret_arg = tv->func(tv->ret_arg);
PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup,
void (*routine) (void *),
void *arg);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/* Clean up destructors */
_pthread_cleanup_dest(tv);
}
/*
* Thread Specific Data Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key,
void (*destructor) (void *));
/* If we exit too early, then we can race with create */
while (tv->h == (HANDLE) -1)
{
YieldProcessor();
_ReadWriteBarrier();
}
PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key);
/* Make sure we free ourselves if we are detached */
if (!tv->h) free(tv);
PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key,
const void *value);
return 0;
}
PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key);
static int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(* func)(void *), void *arg)
{
struct _pthread_v *tv = (_pthread_v*) malloc(sizeof(struct _pthread_v));
unsigned ssize = 0;
if (!tv) return 1;
/*
* Mutex Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
*th = tv;
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
/* Save data in pthread_t */
tv->ret_arg = arg;
tv->func = func;
tv->clean = NULL;
tv->cancelled = 0;
tv->p_state = PTHREAD_DEFAULT_ATTR;
tv->keymax = 0;
tv->keyval = NULL;
tv->h = (HANDLE) -1;
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t
* attr,
int *pshared);
if (attr)
{
tv->p_state = attr->p_state;
ssize = attr->s_size;
}
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr,
int pshared);
/* Make sure tv->h has value of -1 */
_ReadWriteBarrier();
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind);
#ifdef __cplusplus
tv->h = (HANDLE) _beginthreadex(NULL, ssize, reinterpret_cast<unsigned int (__stdcall *)(void *)>(pthread_create_wrapper), tv, 0, NULL);
#else
tv->h = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL);
#endif
/*
* Barrier Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
/* Failed */
if (!tv->h) return 1;
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr);
if (tv->p_state & PTHREAD_CREATE_DETACHED)
{
CloseHandle(tv->h);
_ReadWriteBarrier();
tv->h = 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t
* attr,
int *pshared);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr,
int pshared);
static int pthread_join(pthread_t t, void **res)
{
struct _pthread_v *tv = t;
/*
* Mutex Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr);
pthread_testcancel();
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex);
WaitForSingleObject(tv->h, INFINITE);
CloseHandle(tv->h);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex);
/* Obtain return value */
if (res) *res = tv->ret_arg;
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex,
const struct timespec *abstime);
free(tv);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex);
static int pthread_detach(pthread_t t)
{
struct _pthread_v *tv = t;
/*
* Spinlock Functions
/*
* This can't race with thread exit because
* our call would be undefined if called on a dead thread.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock);
CloseHandle(tv->h);
_ReadWriteBarrier();
tv->h = 0;
PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock);
static int pthread_mutexattr_init(pthread_mutexattr_t *a)
{
*a = 0;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock);
static int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
{
(void) a;
return 0;
}
/*
* Barrier Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
const pthread_barrierattr_t * attr,
unsigned int count);
static int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type)
{
*type = *a & 3;
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier);
static int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
{
if ((unsigned) type > 3) return EINVAL;
*a &= ~3;
*a |= type;
/*
* Condition Variable Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr);
static int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type)
{
*type = *a & 4;
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr,
int *pshared);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr,
int pshared);
static int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type)
{
if ((type & 4) != type) return EINVAL;
/*
* Condition Variable Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
const pthread_condattr_t * attr);
*a &= ~4;
*a |= type;
PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond,
pthread_mutex_t * mutex);
static int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type)
{
*type = *a & (8 + 16);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond,
pthread_mutex_t * mutex,
const struct timespec *abstime);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond);
static int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type)
{
if ((type & (8 + 16)) != 8 + 16) return EINVAL;
PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond);
*a &= ~(8 + 16);
*a |= type;
/*
* Scheduling
*/
PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
int policy,
const struct sched_param *param);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread,
int *policy,
struct sched_param *param);
static int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio)
{
*prio = *a / PTHREAD_PRIO_MULT;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int);
static int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
{
*a &= (PTHREAD_PRIO_MULT - 1);
*a += prio * PTHREAD_PRIO_MULT;
PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void);
return 0;
}
/*
* Read-Write Lock Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
const pthread_rwlockattr_t *attr);
static int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts)
{
unsigned long long t, ct;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock);
struct _pthread_crit_t
{
void *debug;
LONG count;
LONG r_count;
HANDLE owner;
HANDLE sem;
ULONG_PTR spin;
};
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *);
/* Try to lock it without waiting */
if (!pthread_mutex_trylock(m)) return 0;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *);
ct = _pthread_time_in_ms();
t = _pthread_time_in_ms_from_timespec(ts);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock);
while (1)
{
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock,
const struct timespec *abstime);
/* Wait on semaphore within critical section */
WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, t - ct);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock);
/* Try to grab lock */
if (!pthread_mutex_trylock(m)) return 0;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock,
const struct timespec *abstime);
/* Get current time */
ct = _pthread_time_in_ms();
}
}
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock);
#define _PTHREAD_BARRIER_FLAG (1<<30)
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr);
static int pthread_barrier_destroy(pthread_barrier_t *b)
{
EnterCriticalSection(&b->m);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr);
while (b->total > _PTHREAD_BARRIER_FLAG)
{
/* Wait until everyone exits the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr,
int *pshared);
LeaveCriticalSection(&b->m);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr,
int pshared);
DeleteCriticalSection(&b->m);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
return 0;
}
/*
* Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32
* already have signal.h that don't define these.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count)
{
/* Ignore attr */
(void) attr;
/*
* Non-portable functions
*/
b->count = count;
b->total = 0;
/*
* Compatibility with Linux.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
int kind);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
int *kind);
InitializeCriticalSection(&b->m);
InitializeConditionVariable(&b->cv);
/*
* Possibly supported by other POSIX threads implementations
*/
PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
return 0;
}
/*
* Useful if an application wants to statically link
* the lib rather than load the DLL at run-time.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
static int pthread_barrier_wait(pthread_barrier_t *b)
{
EnterCriticalSection(&b->m);
/*
* Features that are auto-detected at load/run time.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
enum ptw32_features {
PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
};
while (b->total > _PTHREAD_BARRIER_FLAG)
{
/* Wait until everyone exits the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
/*
* Register a system time change with the library.
* Causes the library to perform various functions
* in response to the change. Should be called whenever
* the application's top level window receives a
* WM_TIMECHANGE message. It can be passed directly to
* pthread_create() as a new thread if desired.
*/
PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
/* Are we the first to enter? */
if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0;
#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
b->total++;
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
if (b->total == b->count)
{
b->total += _PTHREAD_BARRIER_FLAG - 1;
WakeAllConditionVariable(&b->cv);
/*
* Returns the Win32 HANDLE for the POSIX thread.
*/
PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
LeaveCriticalSection(&b->m);
return 1;
}
else
{
while (b->total < _PTHREAD_BARRIER_FLAG)
{
/* Wait until enough threads enter the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
/*
* Protected Methods
*
* This function blocks until the given WIN32 handle
* is signaled or pthread_cancel had been called.
* This function allows the caller to hook into the
* PThreads cancel mechanism. It is implemented using
*
* WaitForMultipleObjects
*
* on 'waitHandle' and a manually reset WIN32 Event
* used to implement pthread_cancel. The 'timeout'
* argument to TimedWait is simply passed to
* WaitForMultipleObjects.
*/
PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
DWORD timeout);
b->total--;
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/* Get entering threads to wake up */
if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
/*
* Thread-Safe C Runtime Library Mappings.
*/
#ifndef _UWIN
# if defined(NEED_ERRNO)
PTW32_DLLPORT int * PTW32_CDECL _errno( void );
# else
# ifndef errno
# if (defined(_MT) || defined(_DLL))
__declspec(dllimport) extern int * __cdecl _errno(void);
# define errno (*_errno())
# endif
# endif
# endif
#endif
LeaveCriticalSection(&b->m);
/*
* WIN32 C runtime library had been made thread-safe
* without affecting the user interface. Provide
* mappings from the UNIX thread-safe versions to
* the standard C runtime library calls.
* Only provide function mappings for functions that
* actually exist on WIN32.
*/
return 0;
}
}
#if !defined(__MINGW32__)
#define strtok_r( _s, _sep, _lasts ) \
( *(_lasts) = strtok( (_s), (_sep) ) )
#endif /* !__MINGW32__ */
static int pthread_barrierattr_init(void **attr)
{
*attr = NULL;
return 0;
}
#define asctime_r( _tm, _buf ) \
( strcpy( (_buf), asctime( (_tm) ) ), \
(_buf) )
static int pthread_barrierattr_destroy(void **attr)
{
/* Ignore attr */
(void) attr;
#define ctime_r( _clock, _buf ) \
( strcpy( (_buf), ctime( (_clock) ) ), \
(_buf) )
return 0;
}
#define gmtime_r( _clock, _result ) \
( *(_result) = *gmtime( (_clock) ), \
(_result) )
static int pthread_barrierattr_setpshared(void **attr, int s)
{
*attr = (void *) s;
return 0;
}
#define localtime_r( _clock, _result ) \
( *(_result) = *localtime( (_clock) ), \
(_result) )
static int pthread_barrierattr_getpshared(void **attr, int *s)
{
*s = (int) (size_t) *attr;
#define rand_r( _seed ) \
( _seed == _seed? rand() : rand() )
return 0;
}
static int pthread_key_create(pthread_key_t *key, void (* dest)(void *))
{
int i;
long nmax;
void (**d)(void *);
/*
* Some compiler environments don't define some things.
*/
#if defined(__BORLANDC__)
# define _ftime ftime
# define _timeb timeb
#endif
if (!key) return EINVAL;
#ifdef __cplusplus
pthread_rwlock_wrlock(&_pthread_key_lock);
/*
* Internal exceptions
*/
class ptw32_exception {};
class ptw32_exception_cancel : public ptw32_exception {};
class ptw32_exception_exit : public ptw32_exception {};
for (i = _pthread_key_sch; i < _pthread_key_max; i++)
{
if (!_pthread_key_dest[i])
{
*key = i;
if (dest)
{
_pthread_key_dest[i] = dest;
}
else
{
_pthread_key_dest[i] = (void(*)(void *))1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
return 0;
}
}
for (i = 0; i < _pthread_key_sch; i++)
{
if (!_pthread_key_dest[i])
{
*key = i;
if (dest)
{
_pthread_key_dest[i] = dest;
}
else
{
_pthread_key_dest[i] = (void(*)(void *))1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
return 0;
}
}
if (!_pthread_key_max) _pthread_key_max = 1;
if (_pthread_key_max == PTHREAD_KEYS_MAX)
{
pthread_rwlock_unlock(&_pthread_key_lock);
return ENOMEM;
}
nmax = _pthread_key_max * 2;
if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX;
/* No spare room anywhere */
#ifdef __cplusplus
d = reinterpret_cast<void (__cdecl **)(void *)>(realloc(_pthread_key_dest, nmax * sizeof(*d)));
#else
d = realloc(_pthread_key_dest, nmax * sizeof(*d));
#endif
if (!d)
{
pthread_rwlock_unlock(&_pthread_key_lock);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
return ENOMEM;
}
/* FIXME: This is only required if the library was built using SEH */
/*
* Get internal SEH tag
*/
PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
/* Clear new region */
memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/* Use new region */
_pthread_key_dest = d;
_pthread_key_sch = _pthread_key_max + 1;
*key = _pthread_key_max;
_pthread_key_max = nmax;
#ifndef PTW32_BUILD
if (dest)
{
_pthread_key_dest[*key] = dest;
}
else
{
_pthread_key_dest[*key] = (void(*)(void *))1;
}
#ifdef __CLEANUP_SEH
pthread_rwlock_unlock(&_pthread_key_lock);
/*
* Redefine the SEH __except keyword to ensure that applications
* propagate our internal exceptions up to the library's internal handlers.
*/
#define __except( E ) \
__except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
? EXCEPTION_CONTINUE_SEARCH : ( E ) )
return 0;
}
#endif /* __CLEANUP_SEH */
static int pthread_key_delete(pthread_key_t key)
{
if (key > _pthread_key_max) return EINVAL;
if (!_pthread_key_dest) return EINVAL;
#ifdef __CLEANUP_CXX
pthread_rwlock_wrlock(&_pthread_key_lock);
_pthread_key_dest[key] = NULL;
/*
* Redefine the C++ catch keyword to ensure that applications
* propagate our internal exceptions up to the library's internal handlers.
*/
#ifdef _MSC_VER
/*
* WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
* if you want Pthread-Win32 cancelation and pthread_exit to work.
*/
/* Start next search from our location */
if (_pthread_key_sch > key) _pthread_key_sch = key;
#ifndef PtW32NoCatchWarn
#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.")
#pragma message("------------------------------------------------------------------")
#pragma message("When compiling applications with MSVC++ and C++ exception handling:")
#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads")
#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread")
#pragma message(" cancelation and pthread_exit to work. For example:")
#pragma message("")
#pragma message(" #ifdef PtW32CatchAll")
#pragma message(" PtW32CatchAll")
#pragma message(" #else")
#pragma message(" catch(...)")
#pragma message(" #endif")
#pragma message(" {")
#pragma message(" /* Catchall block processing */")
#pragma message(" }")
#pragma message("------------------------------------------------------------------")
pthread_rwlock_unlock(&_pthread_key_lock);
#endif
return 0;
}
#define PtW32CatchAll \
catch( ptw32_exception & ) { throw; } \
catch( ... )
static void *pthread_getspecific(pthread_key_t key)
{
pthread_t t = pthread_self();
#else /* _MSC_VER */
if (key >= t->keymax) return NULL;
#define catch( E ) \
catch( ptw32_exception & ) { throw; } \
catch( E )
return t->keyval[key];
#endif /* _MSC_VER */
}
#endif /* __CLEANUP_CXX */
static int pthread_setspecific(pthread_key_t key, const void *value)
{
pthread_t t = pthread_self();
#endif /* ! PTW32_BUILD */
if (key > t->keymax)
{
int keymax = (key + 1) * 2;
void **kv = (void**) realloc(t->keyval, keymax * sizeof(void *));
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
if (!kv) return ENOMEM;
#ifdef PTW32__HANDLE_DEF
# undef HANDLE
#endif
#ifdef PTW32__DWORD_DEF
# undef DWORD
#endif
/* Clear new region */
memset(&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void*));
t->keyval = kv;
t->keymax = keymax;
}
t->keyval[key] = (void *) value;
return 0;
}
static int pthread_spin_init(pthread_spinlock_t *l, int pshared)
{
(void) pshared;
*l = 0;
return 0;
}
static int pthread_spin_destroy(pthread_spinlock_t *l)
{
(void) l;
return 0;
}
/* No-fair spinlock due to lack of knowledge of thread number */
static int pthread_spin_lock(pthread_spinlock_t *l)
{
while (_InterlockedExchange(l, EBUSY))
{
/* Don't lock the bus whilst waiting */
while (*l)
{
YieldProcessor();
/* Compiler barrier. Prevent caching of *l */
_ReadWriteBarrier();
}
}
return 0;
}
static int pthread_spin_trylock(pthread_spinlock_t *l)
{
return _InterlockedExchange(l, EBUSY);
}
static int pthread_spin_unlock(pthread_spinlock_t *l)
{
/* Compiler barrier. The store below acts with release symmantics */
_ReadWriteBarrier();
*l = 0;
return 0;
}
static int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a)
{
(void) a;
InitializeConditionVariable(c);
return 0;
}
static int pthread_cond_signal(pthread_cond_t *c)
{
WakeConditionVariable(c);
return 0;
}
static int pthread_cond_broadcast(pthread_cond_t *c)
{
WakeAllConditionVariable(c);
return 0;
}
static int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
{
pthread_testcancel();
SleepConditionVariableCS(c, m, INFINITE);
return 0;
}
static int pthread_cond_destroy(pthread_cond_t *c)
{
(void) c;
return 0;
}
static int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t)
{
unsigned long long tm = _pthread_rel_time_in_ms(t);
pthread_testcancel();
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
if (!SleepConditionVariableCS(c, m, tm)) return ETIMEDOUT;
#endif /* ! RC_INVOKED */
/* We can have a spurious wakeup after the timeout */
if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT;
return 0;
}
static int pthread_condattr_destroy(pthread_condattr_t *a)
{
(void) a;
return 0;
}
#define pthread_condattr_getclock(A, C) ENOTSUP
#define pthread_condattr_setclock(A, C) ENOTSUP
static int pthread_condattr_init(pthread_condattr_t *a)
{
*a = 0;
return 0;
}
static int pthread_condattr_getpshared(pthread_condattr_t *a, int *s)
{
*s = *a;
return 0;
}
#endif /* PTHREAD_H */
static int pthread_condattr_setpshared(pthread_condattr_t *a, int s)
{
*a = s;
return 0;
}
static int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
{
(void) a;
return 0;
}
static int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
{
*a = 0;
}
static int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s)
{
*s = *a;
return 0;
}
static int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s)
{
*a = s;
return 0;
}
/* No fork() in windows - so ignore this */
#define pthread_atfork(F1,F2,F3) 0
/* Windows has rudimentary signals support */
#define pthread_kill(T, S) 0
#define pthread_sigmask(H, S1, S2) 0
/* Wrap cancellation points */
/*
#define accept(...) (pthread_testcancel(), accept(__VA_ARGS__))
#define aio_suspend(...) (pthread_testcancel(), aio_suspend(__VA_ARGS__))
#define clock_nanosleep(...) (pthread_testcancel(), clock_nanosleep(__VA_ARGS__))
#define close(...) (pthread_testcancel(), close(__VA_ARGS__))
#define connect(...) (pthread_testcancel(), connect(__VA_ARGS__))
#define creat(...) (pthread_testcancel(), creat(__VA_ARGS__))
#define fcntl(...) (pthread_testcancel(), fcntl(__VA_ARGS__))
#define fdatasync(...) (pthread_testcancel(), fdatasync(__VA_ARGS__))
#define fsync(...) (pthread_testcancel(), fsync(__VA_ARGS__))
#define getmsg(...) (pthread_testcancel(), getmsg(__VA_ARGS__))
#define getpmsg(...) (pthread_testcancel(), getpmsg(__VA_ARGS__))
#define lockf(...) (pthread_testcancel(), lockf(__VA_ARGS__))
#define mg_receive(...) (pthread_testcancel(), mg_receive(__VA_ARGS__))
#define mg_send(...) (pthread_testcancel(), mg_send(__VA_ARGS__))
#define mg_timedreceive(...) (pthread_testcancel(), mg_timedreceive(__VA_ARGS__))
#define mg_timessend(...) (pthread_testcancel(), mg_timedsend(__VA_ARGS__))
#define msgrcv(...) (pthread_testcancel(), msgrecv(__VA_ARGS__))
#define msgsnd(...) (pthread_testcancel(), msgsnd(__VA_ARGS__))
#define msync(...) (pthread_testcancel(), msync(__VA_ARGS__))
#define nanosleep(...) (pthread_testcancel(), nanosleep(__VA_ARGS__))
#define open(...) (pthread_testcancel(), open(__VA_ARGS__))
#define pause(...) (pthread_testcancel(), pause(__VA_ARGS__))
#define poll(...) (pthread_testcancel(), poll(__VA_ARGS__))
#define pread(...) (pthread_testcancel(), pread(__VA_ARGS__))
#define pselect(...) (pthread_testcancel(), pselect(__VA_ARGS__))
#define putmsg(...) (pthread_testcancel(), putmsg(__VA_ARGS__))
#define putpmsg(...) (pthread_testcancel(), putpmsg(__VA_ARGS__))
#define pwrite(...) (pthread_testcancel(), pwrite(__VA_ARGS__))
#define read(...) (pthread_testcancel(), read(__VA_ARGS__))
#define readv(...) (pthread_testcancel(), readv(__VA_ARGS__))
#define recv(...) (pthread_testcancel(), recv(__VA_ARGS__))
#define recvfrom(...) (pthread_testcancel(), recvfrom(__VA_ARGS__))
#define recvmsg(...) (pthread_testcancel(), recvmsg(__VA_ARGS__))
#define select(...) (pthread_testcancel(), select(__VA_ARGS__))
#define sem_timedwait(...) (pthread_testcancel(), sem_timedwait(__VA_ARGS__))
#define sem_wait(...) (pthread_testcancel(), sem_wait(__VA_ARGS__))
#define send(...) (pthread_testcancel(), send(__VA_ARGS__))
#define sendmsg(...) (pthread_testcancel(), sendmsg(__VA_ARGS__))
#define sendto(...) (pthread_testcancel(), sendto(__VA_ARGS__))
#define sigpause(...) (pthread_testcancel(), sigpause(__VA_ARGS__))
#define sigsuspend(...) (pthread_testcancel(), sigsuspend(__VA_ARGS__))
#define sigwait(...) (pthread_testcancel(), sigwait(__VA_ARGS__))
#define sigwaitinfo(...) (pthread_testcancel(), sigwaitinfo(__VA_ARGS__))
#define sleep(...) (pthread_testcancel(), sleep(__VA_ARGS__))
//#define Sleep(...) (pthread_testcancel(), Sleep(__VA_ARGS__))
#define system(...) (pthread_testcancel(), system(__VA_ARGS__))
#define access(...) (pthread_testcancel(), access(__VA_ARGS__))
#define asctime(...) (pthread_testcancel(), asctime(__VA_ARGS__))
#define asctime_r(...) (pthread_testcancel(), asctime_r(__VA_ARGS__))
#define catclose(...) (pthread_testcancel(), catclose(__VA_ARGS__))
#define catgets(...) (pthread_testcancel(), catgets(__VA_ARGS__))
#define catopen(...) (pthread_testcancel(), catopen(__VA_ARGS__))
#define closedir(...) (pthread_testcancel(), closedir(__VA_ARGS__))
#define closelog(...) (pthread_testcancel(), closelog(__VA_ARGS__))
#define ctermid(...) (pthread_testcancel(), ctermid(__VA_ARGS__))
#define ctime(...) (pthread_testcancel(), ctime(__VA_ARGS__))
#define ctime_r(...) (pthread_testcancel(), ctime_r(__VA_ARGS__))
#define dbm_close(...) (pthread_testcancel(), dbm_close(__VA_ARGS__))
#define dbm_delete(...) (pthread_testcancel(), dbm_delete(__VA_ARGS__))
#define dbm_fetch(...) (pthread_testcancel(), dbm_fetch(__VA_ARGS__))
#define dbm_nextkey(...) (pthread_testcancel(), dbm_nextkey(__VA_ARGS__))
#define dbm_open(...) (pthread_testcancel(), dbm_open(__VA_ARGS__))
#define dbm_store(...) (pthread_testcancel(), dbm_store(__VA_ARGS__))
#define dlclose(...) (pthread_testcancel(), dlclose(__VA_ARGS__))
#define dlopen(...) (pthread_testcancel(), dlopen(__VA_ARGS__))
#define endgrent(...) (pthread_testcancel(), endgrent(__VA_ARGS__))
#define endhostent(...) (pthread_testcancel(), endhostent(__VA_ARGS__))
#define endnetent(...) (pthread_testcancel(), endnetent(__VA_ARGS__))
#define endprotoent(...) (pthread_testcancel(), endprotoend(__VA_ARGS__))
#define endpwent(...) (pthread_testcancel(), endpwent(__VA_ARGS__))
#define endservent(...) (pthread_testcancel(), endservent(__VA_ARGS__))
#define endutxent(...) (pthread_testcancel(), endutxent(__VA_ARGS__))
#define fclose(...) (pthread_testcancel(), fclose(__VA_ARGS__))
#define fflush(...) (pthread_testcancel(), fflush(__VA_ARGS__))
#define fgetc(...) (pthread_testcancel(), fgetc(__VA_ARGS__))
#define fgetpos(...) (pthread_testcancel(), fgetpos(__VA_ARGS__))
#define fgets(...) (pthread_testcancel(), fgets(__VA_ARGS__))
#define fgetwc(...) (pthread_testcancel(), fgetwc(__VA_ARGS__))
#define fgetws(...) (pthread_testcancel(), fgetws(__VA_ARGS__))
#define fmtmsg(...) (pthread_testcancel(), fmtmsg(__VA_ARGS__))
#define fopen(...) (pthread_testcancel(), fopen(__VA_ARGS__))
#define fpathconf(...) (pthread_testcancel(), fpathconf(__VA_ARGS__))
#define fprintf(...) (pthread_testcancel(), fprintf(__VA_ARGS__))
#define fputc(...) (pthread_testcancel(), fputc(__VA_ARGS__))
#define fputs(...) (pthread_testcancel(), fputs(__VA_ARGS__))
#define fputwc(...) (pthread_testcancel(), fputwc(__VA_ARGS__))
#define fputws(...) (pthread_testcancel(), fputws(__VA_ARGS__))
#define fread(...) (pthread_testcancel(), fread(__VA_ARGS__))
#define freopen(...) (pthread_testcancel(), freopen(__VA_ARGS__))
#define fscanf(...) (pthread_testcancel(), fscanf(__VA_ARGS__))
#define fseek(...) (pthread_testcancel(), fseek(__VA_ARGS__))
#define fseeko(...) (pthread_testcancel(), fseeko(__VA_ARGS__))
#define fsetpos(...) (pthread_testcancel(), fsetpos(__VA_ARGS__))
#define fstat(...) (pthread_testcancel(), fstat(__VA_ARGS__))
#define ftell(...) (pthread_testcancel(), ftell(__VA_ARGS__))
#define ftello(...) (pthread_testcancel(), ftello(__VA_ARGS__))
#define ftw(...) (pthread_testcancel(), ftw(__VA_ARGS__))
#define fwprintf(...) (pthread_testcancel(), fwprintf(__VA_ARGS__))
#define fwrite(...) (pthread_testcancel(), fwrite(__VA_ARGS__))
#define fwscanf(...) (pthread_testcancel(), fwscanf(__VA_ARGS__))
#define getaddrinfo(...) (pthread_testcancel(), getaddrinfo(__VA_ARGS__))
#define getc(...) (pthread_testcancel(), getc(__VA_ARGS__))
#define getc_unlocked(...) (pthread_testcancel(), getc_unlocked(__VA_ARGS__))
#define getchar(...) (pthread_testcancel(), getchar(__VA_ARGS__))
#define getchar_unlocked(...) (pthread_testcancel(), getchar_unlocked(__VA_ARGS__))
#define getcwd(...) (pthread_testcancel(), getcwd(__VA_ARGS__))
#define getdate(...) (pthread_testcancel(), getdate(__VA_ARGS__))
#define getgrent(...) (pthread_testcancel(), getgrent(__VA_ARGS__))
#define getgrgid(...) (pthread_testcancel(), getgrgid(__VA_ARGS__))
#define getgrgid_r(...) (pthread_testcancel(), getgrgid_r(__VA_ARGS__))
#define gergrnam(...) (pthread_testcancel(), getgrnam(__VA_ARGS__))
#define getgrnam_r(...) (pthread_testcancel(), getgrnam_r(__VA_ARGS__))
#define gethostbyaddr(...) (pthread_testcancel(), gethostbyaddr(__VA_ARGS__))
#define gethostbyname(...) (pthread_testcancel(), gethostbyname(__VA_ARGS__))
#define gethostent(...) (pthread_testcancel(), gethostent(__VA_ARGS__))
#define gethostid(...) (pthread_testcancel(), gethostid(__VA_ARGS__))
#define gethostname(...) (pthread_testcancel(), gethostname(__VA_ARGS__))
#define getlogin(...) (pthread_testcancel(), getlogin(__VA_ARGS__))
#define getlogin_r(...) (pthread_testcancel(), getlogin_r(__VA_ARGS__))
#define getnameinfo(...) (pthread_testcancel(), getnameinfo(__VA_ARGS__))
#define getnetbyaddr(...) (pthread_testcancel(), getnetbyaddr(__VA_ARGS__))
#define getnetbyname(...) (pthread_testcancel(), getnetbyname(__VA_ARGS__))
#define getnetent(...) (pthread_testcancel(), getnetent(__VA_ARGS__))
#define getopt(...) (pthread_testcancel(), getopt(__VA_ARGS__))
#define getprotobyname(...) (pthread_testcancel(), getprotobyname(__VA_ARGS__))
#define getprotobynumber(...) (pthread_testcancel(), getprotobynumber(__VA_ARGS__))
#define getprotoent(...) (pthread_testcancel(), getprotoent(__VA_ARGS__))
#define getpwent(...) (pthread_testcancel(), getpwent(__VA_ARGS__))
#define getpwnam(...) (pthread_testcancel(), getpwnam(__VA_ARGS__))
#define getpwnam_r(...) (pthread_testcancel(), getpwnam_r(__VA_ARGS__))
#define getpwuid(...) (pthread_testcancel(), getpwuid(__VA_ARGS__))
#define getpwuid_r(...) (pthread_testcancel(), getpwuid_r(__VA_ARGS__))
#define gets(...) (pthread_testcancel(), gets(__VA_ARGS__))
#define getservbyname(...) (pthread_testcancel(), getservbyname(__VA_ARGS__))
#define getservbyport(...) (pthread_testcancel(), getservbyport(__VA_ARGS__))
#define getservent(...) (pthread_testcancel(), getservent(__VA_ARGS__))
#define getutxent(...) (pthread_testcancel(), getutxent(__VA_ARGS__))
#define getutxid(...) (pthread_testcancel(), getutxid(__VA_ARGS__))
#define getutxline(...) (pthread_testcancel(), getutxline(__VA_ARGS__))
#undef getwc
#define getwc(...) (pthread_testcancel(), getwc(__VA_ARGS__))
#undef getwchar
#define getwchar(...) (pthread_testcancel(), getwchar(__VA_ARGS__))
#define getwd(...) (pthread_testcancel(), getwd(__VA_ARGS__))
#define glob(...) (pthread_testcancel(), glob(__VA_ARGS__))
#define iconv_close(...) (pthread_testcancel(), iconv_close(__VA_ARGS__))
#define iconv_open(...) (pthread_testcancel(), iconv_open(__VA_ARGS__))
#define ioctl(...) (pthread_testcancel(), ioctl(__VA_ARGS__))
#define link(...) (pthread_testcancel(), link(__VA_ARGS__))
#define localtime(...) (pthread_testcancel(), localtime(__VA_ARGS__))
#define localtime_r(...) (pthread_testcancel(), localtime_r(__VA_ARGS__))
#define lseek(...) (pthread_testcancel(), lseek(__VA_ARGS__))
#define lstat(...) (pthread_testcancel(), lstat(__VA_ARGS__))
#define mkstemp(...) (pthread_testcancel(), mkstemp(__VA_ARGS__))
#define nftw(...) (pthread_testcancel(), nftw(__VA_ARGS__))
#define opendir(...) (pthread_testcancel(), opendir(__VA_ARGS__))
#define openlog(...) (pthread_testcancel(), openlog(__VA_ARGS__))
#define pathconf(...) (pthread_testcancel(), pathconf(__VA_ARGS__))
#define pclose(...) (pthread_testcancel(), pclose(__VA_ARGS__))
#define perror(...) (pthread_testcancel(), perror(__VA_ARGS__))
#define popen(...) (pthread_testcancel(), popen(__VA_ARGS__))
#define posix_fadvise(...) (pthread_testcancel(), posix_fadvise(__VA_ARGS__))
#define posix_fallocate(...) (pthread_testcancel(), posix_fallocate(__VA_ARGS__))
#define posix_madvise(...) (pthread_testcancel(), posix_madvise(__VA_ARGS__))
#define posix_openpt(...) (pthread_testcancel(), posix_openpt(__VA_ARGS__))
#define posix_spawn(...) (pthread_testcancel(), posix_spawn(__VA_ARGS__))
#define posix_spawnp(...) (pthread_testcancel(), posix_spawnp(__VA_ARGS__))
#define posix_trace_clear(...) (pthread_testcancel(), posix_trace_clear(__VA_ARGS__))
#define posix_trace_close(...) (pthread_testcancel(), posix_trace_close(__VA_ARGS__))
#define posix_trace_create(...) (pthread_testcancel(), posix_trace_create(__VA_ARGS__))
#define posix_trace_create_withlog(...) (pthread_testcancel(), posix_trace_create_withlog(__VA_ARGS__))
#define posix_trace_eventtypelist_getne(...) (pthread_testcancel(), posix_trace_eventtypelist_getne(__VA_ARGS__))
#define posix_trace_eventtypelist_rewin(...) (pthread_testcancel(), posix_trace_eventtypelist_rewin(__VA_ARGS__))
#define posix_trace_flush(...) (pthread_testcancel(), posix_trace_flush(__VA_ARGS__))
#define posix_trace_get_attr(...) (pthread_testcancel(), posix_trace_get_attr(__VA_ARGS__))
#define posix_trace_get_filter(...) (pthread_testcancel(), posix_trace_get_filter(__VA_ARGS__))
#define posix_trace_get_status(...) (pthread_testcancel(), posix_trace_get_status(__VA_ARGS__))
#define posix_trace_getnext_event(...) (pthread_testcancel(), posix_trace_getnext_event(__VA_ARGS__))
#define posix_trace_open(...) (pthread_testcancel(), posix_trace_open(__VA_ARGS__))
#define posix_trace_rewind(...) (pthread_testcancel(), posix_trace_rewind(__VA_ARGS__))
#define posix_trace_setfilter(...) (pthread_testcancel(), posix_trace_setfilter(__VA_ARGS__))
#define posix_trace_shutdown(...) (pthread_testcancel(), posix_trace_shutdown(__VA_ARGS__))
#define posix_trace_timedgetnext_event(...) (pthread_testcancel(), posix_trace_timedgetnext_event(__VA_ARGS__))
#define posix_typed_mem_open(...) (pthread_testcancel(), posix_typed_mem_open(__VA_ARGS__))
#define printf(...) (pthread_testcancel(), printf(__VA_ARGS__))
#define putc(...) (pthread_testcancel(), putc(__VA_ARGS__))
#define putc_unlocked(...) (pthread_testcancel(), putc_unlocked(__VA_ARGS__))
#define putchar(...) (pthread_testcancel(), putchar(__VA_ARGS__))
#define putchar_unlocked(...) (pthread_testcancel(), putchar_unlocked(__VA_ARGS__))
#define puts(...) (pthread_testcancel(), puts(__VA_ARGS__))
#define pututxline(...) (pthread_testcancel(), pututxline(__VA_ARGS__))
#undef putwc
#define putwc(...) (pthread_testcancel(), putwc(__VA_ARGS__))
#undef putwchar
#define putwchar(...) (pthread_testcancel(), putwchar(__VA_ARGS__))
#define readdir(...) (pthread_testcancel(), readdir(__VA_ARSG__))
#define readdir_r(...) (pthread_testcancel(), readdir_r(__VA_ARGS__))
#define remove(...) (pthread_testcancel(), remove(__VA_ARGS__))
#define rename(...) (pthread_testcancel(), rename(__VA_ARGS__))
#define rewind(...) (pthread_testcancel(), rewind(__VA_ARGS__))
#define rewinddir(...) (pthread_testcancel(), rewinddir(__VA_ARGS__))
#define scanf(...) (pthread_testcancel(), scanf(__VA_ARGS__))
#define seekdir(...) (pthread_testcancel(), seekdir(__VA_ARGS__))
#define semop(...) (pthread_testcancel(), semop(__VA_ARGS__))
#define setgrent(...) (pthread_testcancel(), setgrent(__VA_ARGS__))
#define sethostent(...) (pthread_testcancel(), sethostemt(__VA_ARGS__))
#define setnetent(...) (pthread_testcancel(), setnetent(__VA_ARGS__))
#define setprotoent(...) (pthread_testcancel(), setprotoent(__VA_ARGS__))
#define setpwent(...) (pthread_testcancel(), setpwent(__VA_ARGS__))
#define setservent(...) (pthread_testcancel(), setservent(__VA_ARGS__))
#define setutxent(...) (pthread_testcancel(), setutxent(__VA_ARGS__))
#define stat(...) (pthread_testcancel(), stat(__VA_ARGS__))
#define strerror(...) (pthread_testcancel(), strerror(__VA_ARGS__))
#define strerror_r(...) (pthread_testcancel(), strerror_r(__VA_ARGS__))
#define strftime(...) (pthread_testcancel(), strftime(__VA_ARGS__))
#define symlink(...) (pthread_testcancel(), symlink(__VA_ARGS__))
#define sync(...) (pthread_testcancel(), sync(__VA_ARGS__))
#define syslog(...) (pthread_testcancel(), syslog(__VA_ARGS__))
#define tmpfile(...) (pthread_testcancel(), tmpfile(__VA_ARGS__))
#define tmpnam(...) (pthread_testcancel(), tmpnam(__VA_ARGS__))
#define ttyname(...) (pthread_testcancel(), ttyname(__VA_ARGS__))
#define ttyname_r(...) (pthread_testcancel(), ttyname_r(__VA_ARGS__))
#define tzset(...) (pthread_testcancel(), tzset(__VA_ARGS__))
#define ungetc(...) (pthread_testcancel(), ungetc(__VA_ARGS__))
#define ungetwc(...) (pthread_testcancel(), ungetwc(__VA_ARGS__))
#define unlink(...) (pthread_testcancel(), unlink(__VA_ARGS__))
#define vfprintf(...) (pthread_testcancel(), vfprintf(__VA_ARGS__))
#define vfwprintf(...) (pthread_testcancel(), vfwprintf(__VA_ARGS__))
#define vprintf(...) (pthread_testcancel(), vprintf(__VA_ARGS__))
#define vwprintf(...) (pthread_testcancel(), vwprintf(__VA_ARGS__))
#define wcsftime(...) (pthread_testcancel(), wcsftime(__VA_ARGS__))
#define wordexp(...) (pthread_testcancel(), wordexp(__VA_ARGS__))
#define wprintf(...) (pthread_testcancel(), wprintf(__VA_ARGS__))
#define wscanf(...) (pthread_testcancel(), wscanf(__VA_ARGS__))
*/
#endif /* WIN_PTHREADS */
/*
* Module: sched.h
*
* Purpose:
* Provides an implementation of POSIX realtime extensions
* as defined in
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _SCHED_H
#define _SCHED_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#if defined(__MINGW32__) || defined(_UWIN)
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
/* For pid_t */
# include <sys/types.h>
/* Required by Unix 98 */
# include <time.h>
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#else
typedef int pid_t;
#endif
/* Thread scheduling policies */
enum {
SCHED_OTHER = 0,
SCHED_FIFO,
SCHED_RR,
SCHED_MIN = SCHED_OTHER,
SCHED_MAX = SCHED_RR
};
struct sched_param {
int sched_priority;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
PTW32_DLLPORT int __cdecl sched_yield (void);
PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
/*
* Note that this macro returns ENOTSUP rather than
* ENOSYS as might be expected. However, returning ENOSYS
* should mean that sched_get_priority_{min,max} are
* not implemented as well as sched_rr_get_interval.
* This is not the case, since we just don't support
* round-robin scheduling. Therefore I have chosen to
* return the same value as sched_setscheduler when
* SCHED_RR is passed to it.
*/
#define sched_rr_get_interval(_pid, _interval) \
( errno = ENOTSUP, (int) -1 )
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !_SCHED_H */
/*
* Module: semaphore.h
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
* They are defined by the POSIX Standard:
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined( SEMAPHORE_H )
#define SEMAPHORE_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#define _POSIX_SEMAPHORES
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef HAVE_MODE_T
typedef unsigned int mode_t;
#endif
typedef struct sem_t_ * sem_t;
PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
int pshared,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
const struct timespec * abstime);
PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
int count);
PTW32_DLLPORT int __cdecl sem_open (const char * name,
int oflag,
mode_t mode,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
int * sval);
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !SEMAPHORE_H */
#include "pthread.h"
PTHREAD_EXPORT volatile long _pthread_cancelling;
PTHREAD_EXPORT int _pthread_concur;
/* Will default to zero as needed */
PTHREAD_EXPORT pthread_once_t _pthread_tls_once;
PTHREAD_EXPORT DWORD _pthread_tls;
/* Note initializer is zero, so this works */
PTHREAD_EXPORT pthread_rwlock_t _pthread_key_lock;
PTHREAD_EXPORT long _pthread_key_max;
PTHREAD_EXPORT long _pthread_key_sch;
PTHREAD_EXPORT void (**_pthread_key_dest)(void *);
......@@ -64,6 +64,7 @@
#include <stdio.h>
#define NOMINMAX
#include <pthread.h>
#ifdef __cplusplus
......
......@@ -30,12 +30,12 @@
#include <map>
#include <queue>
#include <string>
#include <pthread.h>
#define __CL_ENABLE_EXCEPTIONS
#ifdef _MSC_VER
// Prevent Windows from defining macros that interfere with other code.
#define NOMINMAX
#endif
#include <pthread.h>
#include <cuda.h>
#include <builtin_types.h>
#include <vector_functions.h>
......
......@@ -30,13 +30,13 @@
#include <map>
#include <queue>
#include <string>
#include <pthread.h>
#define __CL_ENABLE_EXCEPTIONS
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#ifdef _MSC_VER
// Prevent Windows from defining macros that interfere with other code.
#define NOMINMAX
#endif
#include <pthread.h>
#include <cl.hpp>
#include "windowsExportOpenCL.h"
#include "OpenCLPlatform.h"
......
......@@ -32,6 +32,7 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE. *
* -------------------------------------------------------------------------- */
#define NOMINMAX
#include "internal/windowsExportPme.h"
#include "openmm/kernels.h"
#include "openmm/Vec3.h"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment