Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
6cf75568
Commit
6cf75568
authored
May 15, 2015
by
peastman
Browse files
Switched over to new Windows pthreads library
parent
08945326
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1409 additions
and
3127 deletions
+1409
-3127
CMakeLists.txt
CMakeLists.txt
+2
-19
libraries/pthreads-2/include/pthread.h
libraries/pthreads-2/include/pthread.h
+0
-1625
libraries/pthreads-2/src/pthread.c
libraries/pthreads-2/src/pthread.c
+0
-15
libraries/pthreads/include/pthread.h
libraries/pthreads/include/pthread.h
+1388
-1122
libraries/pthreads/include/sched.h
libraries/pthreads/include/sched.h
+0
-178
libraries/pthreads/include/semaphore.h
libraries/pthreads/include/semaphore.h
+0
-166
libraries/pthreads/lib/pthreadVC2.dll
libraries/pthreads/lib/pthreadVC2.dll
+0
-0
libraries/pthreads/lib/pthreadVC2.lib
libraries/pthreads/lib/pthreadVC2.lib
+0
-0
libraries/pthreads/lib/pthreadVC2_static_mt.lib
libraries/pthreads/lib/pthreadVC2_static_mt.lib
+0
-0
libraries/pthreads/lib/pthreadVC2_x64.dll
libraries/pthreads/lib/pthreadVC2_x64.dll
+0
-0
libraries/pthreads/lib/pthreadVC2_x64.lib
libraries/pthreads/lib/pthreadVC2_x64.lib
+0
-0
libraries/pthreads/src/pthread.cpp
libraries/pthreads/src/pthread.cpp
+15
-0
platforms/cpu/src/gmx_atomic.h
platforms/cpu/src/gmx_atomic.h
+1
-0
platforms/cuda/include/CudaContext.h
platforms/cuda/include/CudaContext.h
+1
-1
platforms/opencl/include/OpenCLContext.h
platforms/opencl/include/OpenCLContext.h
+1
-1
plugins/cpupme/src/CpuPmeKernels.h
plugins/cpupme/src/CpuPmeKernels.h
+1
-0
No files found.
CMakeLists.txt
View file @
6cf75568
...
...
@@ -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
)
...
...
libraries/pthreads-2/include/pthread.h
deleted
100644 → 0
View file @
08945326
/*
* 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 */
libraries/pthreads-2/src/pthread.c
deleted
100644 → 0
View file @
08945326
#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
libraries/pthreads/include/pthread.h
View file @
6cf75568
/* This is an implementation of the threads API of POSIX 1003.1-2001.
/*
* 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.
*
* 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( 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.
* (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:
*
* The three implementations are:
*
* WIN32 SEH
* C
* C++
* * 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.
*
* 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.
* 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.
*/
/*
* 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.
* You may want to use the MingW64 winpthreads library instead.
* It is based on this, but adds error checking.
*/
#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
/*
* Stop here if we are being included by the resource compiler.
* Version 1.0.1 Released 2 Feb 2012
* Fixes pthread_barrier_destroy() to wait for threads to exit the barrier.
*/
#ifndef RC_INVOKED
#undef PTW32_LEVEL
#ifndef WIN_PTHREADS
#define WIN_PTHREADS
#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
#include <windows.h>
#include <intrin.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/timeb.h>
#include <process.h>
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define ETIMEDOUT 110
#define ENOTSUP 134
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#define PTHREAD_CANCEL_DISABLE 0
#define PTHREAD_CANCEL_ENABLE 0x01
#ifdef _UWIN
# define HAVE_STRUCT_TIMESPEC 1
# define HAVE_SIGNAL_H 1
# undef HAVE_CONFIG_H
# pragma comment(lib, "pthread")
#endif
#define PTHREAD_CANCEL_DEFERRED 0
#define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
/*
* -------------------------------------------------------------
*
*
* 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_CREATE_JOINABLE 0
#define PTHREAD_CREATE_DETACHED 0x04
/* Try to avoid including windows.h */
#if defined(__MINGW32__) && defined(__cplusplus)
#define PTW32_INCLUDE_WINDOWS_H
#endif
#define PTHREAD_EXPLICT_SCHED 0
#define PTHREAD_INHERIT_SCHED 0x08
#ifdef PTW32_INCLUDE_WINDOWS_H
#include <windows.h>
#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
#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
;
extern
PTHREAD_EXPORT
int
_pthread_concur
;
/* Will default to zero as needed */
extern
PTHREAD_EXPORT
pthread_once_t
_pthread_tls_once
;
extern
PTHREAD_EXPORT
DWORD
_pthread_tls
;
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
/* 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
*
);
#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
#include <errno.h>
pthread_cleanup_push
(
_pthread_once_cleanup
,
o
);
#endif
#endif
/* PTW32_LEVEL >= PTW32_LEVEL_MAX */
func
();
pthread_cleanup_pop
(
0
);
/*
* Several systems don't define some error numbers.
*/
#ifndef ENOTSUP
# define ENOTSUP 48
/* This is the value in Solaris. */
#endif
/* Mark as done */
*
o
=
1
;
#ifndef ETIMEDOUT
# define ETIMEDOUT 10060
/* This is the value in winsock.h. */
#endif
return
0
;
}
}
#ifndef ENOSYS
# define ENOSYS 140
/* Semi-arbitrary value */
#endif
YieldProcessor
();
#ifndef EDEADLK
# ifdef EDEADLOCK
# define EDEADLK EDEADLOCK
# else
# define EDEADLK 36
/* This is the value in MSVC. */
# endif
#endif
_ReadWriteBarrier
();
#include <sched.h>
state
=
*
o
;
}
/*
* 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
#endif
/* Done */
return
0
;
}
#ifndef HAVE_STRUCT_TIMESPEC
#define HAVE_STRUCT_TIMESPEC 1
struct
timespec
{
long
tv_sec
;
long
tv_nsec
;
};
#endif
/* HAVE_STRUCT_TIMESPEC */
static
int
_pthread_once_raw
(
pthread_once_t
*
o
,
void
(
*
func
)(
void
))
{
long
state
=
*
o
;
#ifndef SIG_BLOCK
#define SIG_BLOCK 0
#endif
/* SIG_BLOCK */
_ReadWriteBarrier
();
#ifndef SIG_UNBLOCK
#define SIG_UNBLOCK 1
#endif
/* SIG_UNBLOCK */
while
(
state
!=
1
)
{
if
(
!
state
)
{
if
(
!
_InterlockedCompareExchange
(
o
,
2
,
0
))
{
/* Success */
func
();
#ifndef SIG_SETMASK
#define SIG_SETMASK 2
#endif
/* SIG_SETMASK */
/* Mark as done */
*
o
=
1
;
#ifdef __cplusplus
extern
"C"
return
0
;
}
}
YieldProcessor
();
_ReadWriteBarrier
();
state
=
*
o
;
}
/* Done */
return
0
;
}
static
int
pthread_mutex_lock
(
pthread_mutex_t
*
m
)
{
#endif
/* __cplusplus */
EnterCriticalSection
(
m
);
return
0
;
}
/*
* -------------------------------------------------------------
*
* 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.
*
* -------------------------------------------------------------
*/
static
int
pthread_mutex_unlock
(
pthread_mutex_t
*
m
)
{
LeaveCriticalSection
(
m
);
return
0
;
}
/*
* POSIX Options
*/
#undef _POSIX_THREADS
#define _POSIX_THREADS 200112L
static
int
pthread_mutex_trylock
(
pthread_mutex_t
*
m
)
{
return
TryEnterCriticalSection
(
m
)
?
0
:
EBUSY
;
}
#undef _POSIX_READER_WRITER_LOCKS
#define _POSIX_READER_WRITER_LOCKS 200112L
static
int
pthread_mutex_init
(
pthread_mutex_t
*
m
,
pthread_mutexattr_t
*
a
)
{
(
void
)
a
;
InitializeCriticalSection
(
m
);
#undef _POSIX_SPIN_LOCKS
#define _POSIX_SPIN_LOCKS 200112L
return
0
;
}
#undef _POSIX_BARRIERS
#define _POSIX_BARRIERS 200112L
static
int
pthread_mutex_destroy
(
pthread_mutex_t
*
m
)
{
DeleteCriticalSection
(
m
);
return
0
;
}
#
un
def
_POSIX_THREAD_SAFE_FUNCTIONS
#define
_POSIX_THREAD_SAFE_FUNCTIONS 200112L
#def
ine pthread_mutex_getprioceiling(M, P) ENOTSUP
#define
pthread_mutex_setprioceiling(M, P) ENOTSUP
#undef _POSIX_THREAD_ATTR_STACKSIZE
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L
static
int
pthread_equal
(
pthread_t
t1
,
pthread_t
t2
)
{
return
t1
==
t2
;
}
/*
* The following options are not supported
*/
#undef _POSIX_THREAD_ATTR_STACKADDR
#define _POSIX_THREAD_ATTR_STACKADDR -1
static
void
pthread_testcancel
(
void
);
#undef _POSIX_THREAD_PRIO_INHERIT
#define _POSIX_THREAD_PRIO_INHERIT -1
static
int
pthread_rwlock_init
(
pthread_rwlock_t
*
l
,
pthread_rwlockattr_t
*
a
)
{
(
void
)
a
;
InitializeSRWLock
(
l
);
#undef _POSIX_THREAD_PRIO_PROTECT
#define _POSIX_THREAD_PRIO_PROTECT -1
return
0
;
}
/* TPS is not fully supported. */
#undef _POSIX_THREAD_PRIORITY_SCHEDULING
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1
static
int
pthread_rwlock_destroy
(
pthread_rwlock_t
*
l
)
{
(
void
)
*
l
;
return
0
;
}
#undef _POSIX_THREAD_PROCESS_SHARED
#define _POSIX_THREAD_PROCESS_SHARED -1
static
int
pthread_rwlock_rdlock
(
pthread_rwlock_t
*
l
)
{
pthread_testcancel
();
AcquireSRWLockShared
(
l
);
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
static
int
pthread_rwlock_wrlock
(
pthread_rwlock_t
*
l
)
{
pthread_testcancel
();
AcquireSRWLockExclusive
(
l
);
#undef PTHREAD_DESTRUCTOR_ITERATIONS
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS
return
0
;
}
#undef _POSIX_THREAD_KEYS_MAX
#define _POSIX_THREAD_KEYS_MAX 128
static
void
pthread_tls_init
(
void
)
{
_pthread_tls
=
TlsAlloc
();
#undef PTHREAD_KEYS_MAX
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX
/* Cannot continue if out of indexes */
if
(
_pthread_tls
==
TLS_OUT_OF_INDEXES
)
abort
();
}
#undef PTHREAD_STACK_MIN
#define PTHREAD_STACK_MIN 0
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
;
#undef _POSIX_THREAD_THREADS_MAX
#define _POSIX_THREAD_THREADS_MAX 64
_pthread_once_raw
(
&
_pthread_tls_once
,
pthread_tls_init
);
/* Arbitrary value */
#undef PTHREAD_THREADS_MAX
#define PTHREAD_THREADS_MAX 2019
t
=
(
pthread_t
)
TlsGetValue
(
_pthread_tls
);
#undef _POSIX_SEM_NSEMS_MAX
#define _POSIX_SEM_NSEMS_MAX 256
/* Main thread? */
if
(
!
t
)
{
t
=
(
pthread_t
)
malloc
(
sizeof
(
struct
_pthread_v
));
/* Arbitrary value */
#undef SEM_NSEMS_MAX
#define SEM_NSEMS_MAX 1024
/* If cannot initialize main thread, then the only thing we can do is abort */
if
(
!
t
)
abort
();
#undef _POSIX_SEM_VALUE_MAX
#define _POSIX_SEM_VALUE_MAX 32767
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
();
#undef SEM_VALUE_MAX
#define SEM_VALUE_MAX INT_MAX
/* 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
);
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/* Time to die */
_endthreadex
(
0
);
}
}
/*
* 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
return
t
;
}
/*
* 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
#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
int
pthread_rwlock_tryrdlock
(
pthread_rwlock_t
*
l
)
{
/* Get the current state of the lock */
void
*
state
=
*
(
void
**
)
l
;
/*
* ====================
* ====================
* POSIX Threads
* ====================
* ====================
*/
if
(
!
state
)
{
/* Unlocked to locked */
if
(
!
INTERLOCKED_COMPARE_EXCHANGE
((
volatile
PVOID
*
)
l
,
(
void
*
)
0x11
,
NULL
))
return
0
;
return
EBUSY
;
}
enum
{
/*
* pthread_attr_{get,set}detachstate
*/
PTHREAD_CREATE_JOINABLE
=
0
,
/* Default */
PTHREAD_CREATE_DETACHED
=
1
,
/* A single writer exists */
if
(
state
==
(
void
*
)
1
)
return
EBUSY
;
/*
* pthread_attr_{get,set}inheritsched
*/
PTHREAD_INHERIT_SCHED
=
0
,
PTHREAD_EXPLICIT_SCHED
=
1
,
/* Default */
/* Multiple writers exist? */
if
((
uintptr_t
)
state
&
14
)
return
EBUSY
;
/*
* pthread_{get,set}scope
*/
PTHREAD_SCOPE_PROCESS
=
0
,
PTHREAD_SCOPE_SYSTEM
=
1
,
/* Default */
if
((
void
*
)
INTERLOCKED_COMPARE_EXCHANGE
((
volatile
PVOID
*
)
l
,
(
void
*
)
((
uintptr_t
)
state
+
16
),
state
)
==
state
)
return
0
;
/*
* pthread_setcancelstate paramters
*/
PTHREAD_CANCEL_ENABLE
=
0
,
/* Default */
PTHREAD_CANCEL_DISABLE
=
1
,
return
EBUSY
;
}
/*
* pthread_setcanceltype parameters
*/
PTHREAD_CANCEL_ASYNCHRONOUS
=
0
,
PTHREAD_CANCEL_DEFERRED
=
1
,
/* Default */
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
;
/*
* pthread_mutexattr_{get,set}pshared
* pthread_condattr_{get,set}pshared
*/
PTHREAD_PROCESS_PRIVATE
=
0
,
PTHREAD_PROCESS_SHARED
=
1
,
return
EBUSY
;
}
/*
* pthread_barrier_wait
*/
PTHREAD_BARRIER_SERIAL_THREAD
=
-
1
};
static
unsigned
long
long
_pthread_time_in_ms
(
void
)
{
struct
__timeb64
tb
;
/*
* ====================
* ====================
* Cancelation
* ====================
* ====================
*/
#define PTHREAD_CANCELED ((void *) -1)
_ftime64
(
&
tb
);
return
tb
.
time
*
1000
+
tb
.
millitm
;
}
/*
* ====================
* ====================
* Once Key
* ====================
* ====================
*/
#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
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
;
}
st
ruct
pthread_once_t_
st
atic
unsigned
long
long
_pthread_rel_time_in_ms
(
const
struct
timespec
*
ts
)
{
int
done
;
/* indicates if user function has been executed */
void
*
lock
;
int
reserved1
;
int
reserved2
;
};
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
;
}
/*
* ====================
* ====================
* 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)
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
);
/*
* Compatibility with LinuxThreads
*/
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
pthread_testcancel
();
#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1)
/* Use a busy-loop */
while
(
1
)
{
/* Try to grab lock */
if
(
!
pthread_rwlock_tryrdlock
(
l
))
return
0
;
#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1)
/* Get current time */
ct
=
_pthread_time_in_ms
();
#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1)
/* 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
);
/*
* 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
};
pthread_testcancel
();
/* Use a busy-loop */
while
(
1
)
{
/* Try to grab lock */
if
(
!
pthread_rwlock_trywrlock
(
l
))
return
0
;
typedef
struct
ptw32_cleanup_t
ptw32_cleanup_t
;
/* Get current time */
ct
=
_pthread_time_in_ms
();
#if defined(_MSC_VER)
/* Disable MSVC 'anachronism used' warning */
#pragma warning( disable : 4229 )
#endif
/* Have we waited long enough? */
if
(
ct
>
t
)
return
ETIMEDOUT
;
}
}
typedef
void
(
*
PTW32_CDECL
ptw32_cleanup_callback_t
)(
void
*
);
static
int
pthread_get_concurrency
(
int
*
val
)
{
*
val
=
_pthread_concur
;
return
0
;
}
#if defined(_MSC_VER)
#pragma warning( default : 4229 )
#endif
static
int
pthread_set_concurrency
(
int
val
)
{
_pthread_concur
=
val
;
return
0
;
}
struct
ptw32_cleanup_t
#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
)
{
ptw32_cleanup_callback_t
routine
;
void
*
arg
;
struct
ptw32_cleanup_t
*
prev
;
};
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
;
#ifdef __CLEANUP_SEH
/*
* WIN32 SEH version of cancel cleanup.
*/
#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 ); \
} \
} \
}
#else
/* __CLEANUP_SEH */
#ifdef __CLEANUP_C
/*
* C implementation of PThreads cancel cleanup
*/
#define pthread_cleanup_push( _rout, _arg ) \
{ \
ptw32_cleanup_t _cleanup; \
\
ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
#define pthread_cleanup_pop( _execute ) \
(void) ptw32_pop_cleanup( _execute ); \
}
#else
/* __CLEANUP_C */
#ifdef __CLEANUP_CXX
/*
* C++ version of cancel cleanup.
* - John E. Bossom.
*/
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
*/
{
}
PThreadCleanup
(
ptw32_cleanup_callback_t
routine
,
void
*
arg
)
:
cleanUpRout
(
routine
),
obj
(
arg
),
executeIt
(
1
)
/*
* Registers a cleanup routine for 'arg'
*/
{
}
~
PThreadCleanup
()
{
if
(
executeIt
&&
((
void
*
)
cleanUpRout
!=
(
void
*
)
0
)
)
{
(
void
)
(
*
cleanUpRout
)(
obj
);
}
}
void
execute
(
int
exec
)
{
executeIt
=
exec
;
}
};
/*
* 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) );
#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
*
/
PTW32_DLLPORT
int
PTW32_CDECL
pthread_spin_init
(
pthread_spinlock_t
*
lock
,
int
pshared
);
/*
*
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_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
);
PTW32_DLLPORT
int
PTW32_CDECL
pthread_getconcurrency
(
void
);
static
int
pthread_mutexattr_setprioceiling
(
pthread_mutexattr_t
*
a
,
int
prio
)
{
*
a
&=
(
PTHREAD_PRIO_MULT
-
1
);
*
a
+=
prio
*
PTHREAD_PRIO_MULT
;
/*
* Read-Write Lock Functions
*/
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_init
(
pthread_rwlock_t
*
lock
,
const
pthread_rwlockattr_t
*
attr
);
return
0
;
}
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_destroy
(
pthread_rwlock_t
*
lock
);
static
int
pthread_mutex_timedlock
(
pthread_mutex_t
*
m
,
struct
timespec
*
ts
)
{
unsigned
long
long
t
,
ct
;
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_tryrdlock
(
pthread_rwlock_t
*
);
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_trywrlock
(
pthread_rwlock_t
*
);
/* Try to lock it without waiting */
if
(
!
pthread_mutex_trylock
(
m
))
return
0
;
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_rdlock
(
pthread_rwlock_t
*
lock
);
ct
=
_pthread_time_in_ms
();
t
=
_pthread_time_in_ms_from_timespec
(
ts
);
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_timedrdlock
(
pthread_rwlock_t
*
lock
,
const
struct
timespec
*
abstime
);
while
(
1
)
{
/* Have we waited long enough? */
if
(
ct
>
t
)
return
ETIMEDOUT
;
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_wrlock
(
pthread_rwlock_t
*
lock
);
/* Wait on semaphore within critical section */
WaitForSingleObject
(((
struct
_pthread_crit_t
*
)
m
)
->
sem
,
t
-
ct
);
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_timedwrlock
(
pthread_rwlock_t
*
lock
,
const
struct
timespec
*
abstime
)
;
/* Try to grab lock */
if
(
!
pthread_mutex_trylock
(
m
))
return
0
;
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlock_unlock
(
pthread_rwlock_t
*
lock
);
/* Get current time */
ct
=
_pthread_time_in_ms
();
}
}
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlockattr_init
(
pthread_rwlockattr_t
*
attr
);
#define _PTHREAD_BARRIER_FLAG (1<<30)
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlockattr_destroy
(
pthread_rwlockattr_t
*
attr
);
static
int
pthread_barrier_destroy
(
pthread_barrier_t
*
b
)
{
EnterCriticalSection
(
&
b
->
m
);
PTW32_DLLPORT
int
PTW32_CDECL
pthread_rwlockattr_getpshared
(
const
pthread_rwlockattr_t
*
attr
,
int
*
pshared
);
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_setpshared
(
pthread_rwlockattr_t
*
attr
,
int
pshared
);
LeaveCriticalSection
(
&
b
->
m
);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1
DeleteCriticalSection
(
&
b
->
m
);
/*
* 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
);
return
0
;
}
/*
* Non-portable functions
*/
static
int
pthread_barrier_init
(
pthread_barrier_t
*
b
,
void
*
attr
,
int
count
)
{
/* Ignore attr */
(
void
)
attr
;
/*
* 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
);
b
->
count
=
count
;
b
->
total
=
0
;
/*
* 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
);
InitializeCriticalSection
(
&
b
->
m
);
InitializeConditionVariable
(
&
b
->
cv
);
/*
* 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
);
return
0
;
}
/*
* 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. */
};
static
int
pthread_barrier_wait
(
pthread_barrier_t
*
b
)
{
EnterCriticalSection
(
&
b
->
m
);
/*
* 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
*
);
while
(
b
->
total
>
_PTHREAD_BARRIER_FLAG
)
{
/* Wait until everyone exits the barrier */
SleepConditionVariableCS
(
&
b
->
cv
,
&
b
->
m
,
INFINITE
);
}
#endif
/*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */
/* Are we the first to enter? */
if
(
b
->
total
==
_PTHREAD_BARRIER_FLAG
)
b
->
total
=
0
;
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
b
->
total
++
;
/*
* Returns the Win32 HANDLE for the POSIX thread.
*/
PTW32_DLLPORT
HANDLE
PTW32_CDECL
pthread_getw32threadhandle_np
(
pthread_t
thread
);
if
(
b
->
total
==
b
->
count
)
{
b
->
total
+=
_PTHREAD_BARRIER_FLAG
-
1
;
WakeAllConditionVariable
(
&
b
->
cv
);
LeaveCriticalSection
(
&
b
->
m
);
/*
* 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
);
return
1
;
}
else
{
while
(
b
->
total
<
_PTHREAD_BARRIER_FLAG
)
{
/* Wait until enough threads enter the barrier */
SleepConditionVariableCS
(
&
b
->
cv
,
&
b
->
m
,
INFINITE
);
}
#endif
/* PTW32_LEVEL >= PTW32_LEVEL_MAX */
b
->
total
--
;
/*
* 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
/* Get entering threads to wake up */
if
(
b
->
total
==
_PTHREAD_BARRIER_FLAG
)
WakeAllConditionVariable
(
&
b
->
cv
);
/*
* 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.
*/
LeaveCriticalSection
(
&
b
->
m
);
#if !defined(__MINGW32__)
#define strtok_r( _s, _sep, _lasts ) \
( *(_lasts) = strtok( (_s), (_sep) ) )
#endif
/* !__MINGW32__ */
return
0
;
}
}
#define asctime_r( _tm, _buf ) \
( strcpy( (_buf), asctime( (_tm) ) ), \
(_buf) )
static
int
pthread_barrierattr_init
(
void
**
attr
)
{
*
attr
=
NULL
;
return
0
;
}
#define ctime_r( _clock, _buf ) \
( strcpy( (_buf), ctime( (_clock) ) ), \
(_buf) )
static
int
pthread_barrierattr_destroy
(
void
**
attr
)
{
/* Ignore attr */
(
void
)
attr
;
#define gmtime_r( _clock, _result ) \
( *(_result) = *gmtime( (_clock) ), \
(_result) )
return
0
;
}
#define localtime_r( _clock, _result ) \
( *(_result) = *localtime( (_clock) ), \
(_result) )
static
int
pthread_barrierattr_setpshared
(
void
**
attr
,
int
s
)
{
*
attr
=
(
void
*
)
s
;
return
0
;
}
#define rand_r( _seed ) \
( _seed == _seed? rand() : rand() )
static
int
pthread_barrierattr_getpshared
(
void
**
attr
,
int
*
s
)
{
*
s
=
(
int
)
(
size_t
)
*
attr
;
return
0
;
}
/*
* Some compiler environments don't define some things.
*/
#if defined(__BORLANDC__)
# define _ftime ftime
# define _timeb timeb
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
);
#ifdef __cplusplus
return
ENOMEM
;
}
/*
* Internal exceptions
*/
class
ptw32_exception
{};
class
ptw32_exception_cancel
:
public
ptw32_exception
{};
class
ptw32_exception_exit
:
public
ptw32_exception
{};
/* Clear new region */
memset
((
void
*
)
&
d
[
_pthread_key_max
],
0
,
(
nmax
-
_pthread_key_max
)
*
sizeof
(
void
*
));
#endif
/* Use new region */
_pthread_key_dest
=
d
;
_pthread_key_sch
=
_pthread_key_max
+
1
;
*
key
=
_pthread_key_max
;
_pthread_key_max
=
nmax
;
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
if
(
dest
)
{
_pthread_key_dest
[
*
key
]
=
dest
;
}
else
{
_pthread_key_dest
[
*
key
]
=
(
void
(
*
)(
void
*
))
1
;
}
/* 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
);
pthread_rwlock_unlock
(
&
_pthread_key_lock
);
#endif
/* PTW32_LEVEL >= PTW32_LEVEL_MAX */
return
0
;
}
#ifndef PTW32_BUILD
static
int
pthread_key_delete
(
pthread_key_t
key
)
{
if
(
key
>
_pthread_key_max
)
return
EINVAL
;
if
(
!
_pthread_key_dest
)
return
EINVAL
;
#ifdef __CLEANUP_SEH
pthread_rwlock_wrlock
(
&
_pthread_key_lock
);
_pthread_key_dest
[
key
]
=
NULL
;
/*
* 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 ) )
/* Start next search from our location */
if
(
_pthread_key_sch
>
key
)
_pthread_key_sch
=
key
;
#endif
/* __CLEANUP_SEH */
pthread_rwlock_unlock
(
&
_pthread_key_lock
);
#ifdef __CLEANUP_CXX
return
0
;
}
/*
* 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.
*/
#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("------------------------------------------------------------------")
static
void
*
pthread_getspecific
(
pthread_key_t
key
)
{
pthread_t
t
=
pthread_self
();
#endif
if
(
key
>=
t
->
keymax
)
return
NULL
;
return
t
->
keyval
[
key
];
#define PtW32CatchAll \
catch( ptw32_exception & ) { throw; } \
catch( ... )
}
#else
/* _MSC_VER */
static
int
pthread_setspecific
(
pthread_key_t
key
,
const
void
*
value
)
{
pthread_t
t
=
pthread_self
();
#define catch( E ) \
catch( ptw32_exception & ) { throw; } \
catch( E )
if
(
key
>
t
->
keymax
)
{
int
keymax
=
(
key
+
1
)
*
2
;
void
**
kv
=
(
void
**
)
realloc
(
t
->
keyval
,
keymax
*
sizeof
(
void
*
));
#endif
/* _MSC_VER */
if
(
!
kv
)
return
ENOMEM
;
#endif
/* __CLEANUP_CXX */
/* Clear new region */
memset
(
&
kv
[
t
->
keymax
],
0
,
(
keymax
-
t
->
keymax
)
*
sizeof
(
void
*
));
#endif
/* ! PTW32_BUILD */
t
->
keyval
=
kv
;
t
->
keymax
=
keymax
;
}
#ifdef __cplusplus
}
/* End of extern "C" */
#endif
/* __cplusplus */
t
->
keyval
[
key
]
=
(
void
*
)
value
;
#ifdef PTW32__HANDLE_DEF
# undef HANDLE
#endif
#ifdef PTW32__DWORD_DEF
# undef DWORD
#endif
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
);
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
pthread_testcancel
();
#endif
/* ! RC_INVOKED */
if
(
!
SleepConditionVariableCS
(
c
,
m
,
tm
))
return
ETIMEDOUT
;
#endif
/* PTHREAD_H */
/* 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 */
libraries/pthreads/include/sched.h
deleted
100644 → 0
View file @
08945326
/*
* 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 */
libraries/pthreads/include/semaphore.h
deleted
100644 → 0
View file @
08945326
/*
* 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 */
libraries/pthreads/lib/pthreadVC2.dll
deleted
100644 → 0
View file @
08945326
File deleted
libraries/pthreads/lib/pthreadVC2.lib
deleted
100644 → 0
View file @
08945326
File deleted
libraries/pthreads/lib/pthreadVC2_static_mt.lib
deleted
100644 → 0
View file @
08945326
File deleted
libraries/pthreads/lib/pthreadVC2_x64.dll
deleted
100644 → 0
View file @
08945326
File deleted
libraries/pthreads/lib/pthreadVC2_x64.lib
deleted
100644 → 0
View file @
08945326
File deleted
libraries/pthreads/src/pthread.cpp
0 → 100644
View file @
6cf75568
#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
*
);
platforms/cpu/src/gmx_atomic.h
View file @
6cf75568
...
...
@@ -64,6 +64,7 @@
#include <stdio.h>
#define NOMINMAX
#include <pthread.h>
#ifdef __cplusplus
...
...
platforms/cuda/include/CudaContext.h
View file @
6cf75568
...
...
@@ -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>
...
...
platforms/opencl/include/OpenCLContext.h
View file @
6cf75568
...
...
@@ -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"
...
...
plugins/cpupme/src/CpuPmeKernels.h
View file @
6cf75568
...
...
@@ -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"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment