Commit bf6d95c2 authored by John Chodera (MSKCC)'s avatar John Chodera (MSKCC)
Browse files

Merge remote-tracking branch 'upstream/master'

parents 896413aa 227c86bf
...@@ -81,20 +81,6 @@ ENDIF(${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT}) ...@@ -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) 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) IF(WIN32)
SET(OPENMM_SOURCE_SUBDIRS ${OPENMM_SOURCE_SUBDIRS} libraries/pthreads) 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) ELSE(WIN32)
IF (NOT ANDROID) IF (NOT ANDROID)
SET(PTHREADS_LIB pthread) SET(PTHREADS_LIB pthread)
...@@ -303,17 +289,14 @@ ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux") ...@@ -303,17 +289,14 @@ ENDIF (CMAKE_SYSTEM_NAME MATCHES "Linux")
IF(OPENMM_BUILD_SHARED_LIB) IF(OPENMM_BUILD_SHARED_LIB)
ADD_LIBRARY(${SHARED_TARGET} SHARED ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES}) 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") 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")
IF(WIN32)
ADD_DEPENDENCIES(${SHARED_TARGET} PthreadsLibraries)
ENDIF(WIN32)
ENDIF(OPENMM_BUILD_SHARED_LIB) ENDIF(OPENMM_BUILD_SHARED_LIB)
SET(OPENMM_BUILD_STATIC_LIB OFF CACHE BOOL "Whether to build static OpenMM libraries") SET(OPENMM_BUILD_STATIC_LIB OFF CACHE BOOL "Whether to build static OpenMM libraries")
IF(OPENMM_BUILD_STATIC_LIB) IF(OPENMM_BUILD_STATIC_LIB)
ADD_LIBRARY(${STATIC_TARGET} STATIC ${SOURCE_FILES} ${SOURCE_INCLUDE_FILES} ${API_ABS_INCLUDE_FILES}) 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(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) ENDIF(OPENMM_BUILD_STATIC_LIB)
IF(OPENMM_BUILD_C_AND_FORTRAN_WRAPPERS) IF(OPENMM_BUILD_C_AND_FORTRAN_WRAPPERS)
......
...@@ -33,6 +33,7 @@ find_path(OPENCL_INCLUDE_DIR ...@@ -33,6 +33,7 @@ find_path(OPENCL_INCLUDE_DIR
"/usr/local/cuda" "/usr/local/cuda"
"/usr/local/streamsdk" "/usr/local/streamsdk"
"/usr" "/usr"
"${CUDA_TOOLKIT_ROOT_DIR}"
PATH_SUFFIXES "include" PATH_SUFFIXES "include"
) )
......
...@@ -1121,6 +1121,25 @@ integrator is: ...@@ -1121,6 +1121,25 @@ integrator is:
The parameter is the integration error tolerance (0.001), whose meaning is the The parameter is the integration error tolerance (0.001), whose meaning is the
same as for the Langevin integrator. same as for the Langevin integrator.
Multiple Time Step Integrator
-----------------------------
The :class:`MTSIntegrator` class implements the rRESPA multiple time step
algorithm\ :cite:`Tuckerman1992`. This allows some forces in the system to be evaluated more
frequently than others. For details on how to use it, consult the API
documentation.
aMD Integrator
--------------
There are three different integrator types that implement variations of the
aMD\ :cite:`Hamelberg2007` accelerated sampling algorithm: :class:`AMDIntegrator`,
:class:`AMDForceGroupIntegrator`, and :class:`DualAMDIntegrator`. They
perform integration on a modified potential energy surface to allow much faster
sampling of conformations. For details on how to use them, consult the API
documentation.
Temperature Coupling Temperature Coupling
==================== ====================
......
...@@ -90,6 +90,17 @@ ...@@ -90,6 +90,17 @@
type = {Journal Article} type = {Journal Article}
} }
@article{Hamelberg2007,
author={Hamelberg, Donald and de Oliveira, Cesar Augusto F. and McCammon, J. Andrew},
title={Sampling of slow diffusive conformational transitions with accelerated molecular dynamics},
journal={Journal of Chemical Physics},
volume={127},
number={15},
pages={155102},
year={2007},
type = {Journal Article}
}
@article{Hawkins1995 @article{Hawkins1995
author = {Hawkins, Gregory D. and Cramer, Christopher J. and Truhlar, Donald G.}, author = {Hawkins, Gregory D. and Cramer, Christopher J. and Truhlar, Donald G.},
title = {Pairwise solute descreening of solute charges from a dielectric medium}, title = {Pairwise solute descreening of solute charges from a dielectric medium},
...@@ -440,6 +451,17 @@ ...@@ -440,6 +451,17 @@
type = {Journal Article} type = {Journal Article}
} }
@article{Tuckerman1992,
author={Tuckerman, M. and Berne, Bruce J. and Martyna, Glenn J.},
title={Reversible multiple time scale molecular dynamics},
journal = {Journal of Chemical Physics},
volume={97},
number={3},
pages={1990-2001},
year={1992},
type = {Journal Article}
}
@article{Uberuaga2004, @article{Uberuaga2004,
author = {Blas P. Uberuaga and Marian Anghel and Arthur author = {Blas P. Uberuaga and Marian Anghel and Arthur
F. Voter}, F. Voter},
......
/* 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 * (C) 2010 Lockless Inc.
* Copyright(C) 1998 John E. Bossom * All rights reserved.
* Copyright(C) 1999,2005 Pthreads-win32 contributors *
* * Redistribution and use in source and binary forms, with or without modification,
* Contact Email: rpj@callisto.canberra.edu.au * are permitted provided that the following conditions are met:
*
* 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.
* *
* The three implementations are:
* *
* WIN32 SEH * * Redistributions of source code must retain the above copyright notice,
* C * this list of conditions and the following disclaimer.
* C++ * * 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 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
* "return", "exit", "break", or "continue" will * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* lead to different behaviour amongst applications * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* depending upon whether the library was built * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* using SEH, C++, or C. For example, a library built * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* with SEH will call the cleanup routine, while both * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* C++ and C built versions will not. * 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. * You may want to use the MingW64 winpthreads library instead.
* Note: Unless the build explicitly defines one of the following, then * It is based on this, but adds error checking.
* 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.
*/ */
#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 #include <windows.h>
#undef PTW32_LEVEL #include <intrin.h>
#define PTW32_LEVEL 1 #include <setjmp.h>
/* Include 1b, 1c and 1d */ #include <errno.h>
#endif #include <sys/timeb.h>
#include <process.h>
#if defined(INCLUDE_NP) #define ETIMEDOUT 110
#undef PTW32_LEVEL #define ENOTSUP 134
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL) #define PTHREAD_CANCEL_DISABLE 0
#define PTW32_LEVEL PTW32_LEVEL_MAX #define PTHREAD_CANCEL_ENABLE 0x01
/* Include everything */
#endif
#if defined(_UWIN) #define PTHREAD_CANCEL_DEFERRED 0
# define HAVE_STRUCT_TIMESPEC 1 #define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
# define HAVE_SIGNAL_H 1
# undef HAVE_CONFIG_H
# pragma comment(lib, "pthread")
#elif defined(__MINGW32__)
# define HAVE_STRUCT_TIMESPEC 1
# define HAVE_SIGNAL_H 1
#endif
/* #define PTHREAD_CREATE_JOINABLE 0
* ------------------------------------------------------------- #define PTHREAD_CREATE_DETACHED 0x04
*
*
* 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/
*
* -------------------------------------------------------------
*/
/* Try to avoid including windows.h */ #define PTHREAD_EXPLICT_SCHED 0
#if defined(__MINGW32__) && defined(__cplusplus) #define PTHREAD_INHERIT_SCHED 0x08
#define PTW32_INCLUDE_WINDOWS_H
#endif
#ifdef PTW32_INCLUDE_WINDOWS_H #define PTHREAD_SCOPE_PROCESS 0
#include <windows.h> #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 #endif
#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) #if defined(PTHREAD_BUILDING_SHARED_LIBRARY)
/* #define PTHREAD_EXPORT __declspec(dllexport)
* VC++6.0 or early compiler's header has no DWORD_PTR type. #elif defined(PTHREAD_BUILDING_STATIC_LIBRARY)
*/ #define PTHREAD_EXPORT
typedef unsigned long DWORD_PTR; #else
#define PTHREAD_EXPORT __declspec(dllimport)
#endif #endif
/*
* -----------------
* autoconf switches
* -----------------
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#ifndef NEED_FTIME /* Windows doesn't have this, so declare it ourselves. */
#include <time.h> struct timespec
#else /* NEED_FTIME */ {
/* use native WIN32 time API */ /* long long in windows is the same as long in unix for 64bit */
#endif /* NEED_FTIME */ long long tv_sec;
long long tv_nsec;
};
#if HAVE_SIGNAL_H typedef struct _pthread_cleanup _pthread_cleanup;
#include <signal.h> struct _pthread_cleanup
#endif /* HAVE_SIGNAL_H */ {
void (*func)(void *);
void *arg;
_pthread_cleanup *next;
};
#include <setjmp.h> struct _pthread_v
#include <limits.h> {
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;
* Boolean values to make us independent of system includes.
*/ typedef struct pthread_barrier_t pthread_barrier_t;
enum { struct pthread_barrier_t
PTW32_FALSE = 0, {
PTW32_TRUE = (! PTW32_FALSE) int count;
int total;
CRITICAL_SECTION m;
CONDITION_VARIABLE cv;
}; };
/* typedef struct pthread_attr_t pthread_attr_t;
* This is a duplicate of what is in the autoconf config.h, struct pthread_attr_t
* which is only used when building the pthread-win32 libraries. {
*/ unsigned p_state;
void *stack;
size_t s_size;
};
#ifndef PTW32_CONFIG_H typedef long pthread_once_t;
# if defined(WINCE) typedef unsigned pthread_mutexattr_t;
# define NEED_ERRNO typedef SRWLOCK pthread_rwlock_t;
# define NEED_SEM typedef CRITICAL_SECTION pthread_mutex_t;
# endif typedef unsigned pthread_key_t;
# if defined(_UWIN) || defined(__MINGW32__) typedef void *pthread_barrierattr_t;
# define HAVE_MODE_T typedef long pthread_spinlock_t;
# endif typedef int pthread_condattr_t;
#endif 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 /* Note initializer is zero, so this works */
#ifdef NEED_ERRNO extern PTHREAD_EXPORT pthread_rwlock_t _pthread_key_lock;
#include "need_errno.h" 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 #else
#include <errno.h> pthread_cleanup_push(_pthread_once_cleanup, o);
#endif #endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ func();
pthread_cleanup_pop(0);
/* /* Mark as done */
* Several systems don't define some error numbers. *o = 1;
*/
#ifndef ENOTSUP
# define ENOTSUP 48 /* This is the value in Solaris. */
#endif
#ifndef ETIMEDOUT return 0;
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ }
#endif }
#ifndef ENOSYS YieldProcessor();
# define ENOSYS 140 /* Semi-arbitrary value */
#endif
#ifndef EDEADLK _ReadWriteBarrier();
# ifdef EDEADLOCK
# define EDEADLK EDEADLOCK
# else
# define EDEADLK 36 /* This is the value in MSVC. */
# endif
#endif
#include <sched.h> state = *o;
}
/* /* Done */
* To avoid including windows.h we define only those things that we return 0;
* 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
#ifndef HAVE_STRUCT_TIMESPEC static int _pthread_once_raw(pthread_once_t *o, void (*func)(void))
#define HAVE_STRUCT_TIMESPEC 1 {
struct timespec { long state = *o;
long tv_sec;
long tv_nsec;
};
#endif /* HAVE_STRUCT_TIMESPEC */
#ifndef SIG_BLOCK _ReadWriteBarrier();
#define SIG_BLOCK 0
#endif /* SIG_BLOCK */
#ifndef SIG_UNBLOCK while (state != 1)
#define SIG_UNBLOCK 1 {
#endif /* SIG_UNBLOCK */ if (!state)
{
if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
func();
#ifndef SIG_SETMASK /* Mark as done */
#define SIG_SETMASK 2 *o = 1;
#endif /* SIG_SETMASK */
#ifdef __cplusplus return 0;
extern "C" }
}
YieldProcessor();
_ReadWriteBarrier();
state = *o;
}
/* Done */
return 0;
}
static int pthread_mutex_lock(pthread_mutex_t *m)
{ {
#endif /* __cplusplus */ EnterCriticalSection(m);
return 0;
}
/* static int pthread_mutex_unlock(pthread_mutex_t *m)
* ------------------------------------------------------------- {
* LeaveCriticalSection(m);
* POSIX 1003.1-2001 Options return 0;
* ========================= }
*
* 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_trylock(pthread_mutex_t *m)
* POSIX Options {
*/ return TryEnterCriticalSection(m) ? 0 : EBUSY;
#undef _POSIX_THREADS }
#define _POSIX_THREADS 200112L
#undef _POSIX_READER_WRITER_LOCKS static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
#define _POSIX_READER_WRITER_LOCKS 200112L {
(void) a;
InitializeCriticalSection(m);
#undef _POSIX_SPIN_LOCKS return 0;
#define _POSIX_SPIN_LOCKS 200112L }
#undef _POSIX_BARRIERS static int pthread_mutex_destroy(pthread_mutex_t *m)
#define _POSIX_BARRIERS 200112L {
DeleteCriticalSection(m);
return 0;
}
#undef _POSIX_THREAD_SAFE_FUNCTIONS #define pthread_mutex_getprioceiling(M, P) ENOTSUP
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L #define pthread_mutex_setprioceiling(M, P) ENOTSUP
#undef _POSIX_THREAD_ATTR_STACKSIZE static int pthread_equal(pthread_t t1, pthread_t t2)
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L {
return t1 == t2;
}
/* static void pthread_testcancel(void);
* The following options are not supported
*/
#undef _POSIX_THREAD_ATTR_STACKADDR
#define _POSIX_THREAD_ATTR_STACKADDR -1
#undef _POSIX_THREAD_PRIO_INHERIT static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
#define _POSIX_THREAD_PRIO_INHERIT -1 {
(void) a;
InitializeSRWLock(l);
#undef _POSIX_THREAD_PRIO_PROTECT return 0;
#define _POSIX_THREAD_PRIO_PROTECT -1 }
/* TPS is not fully supported. */ static int pthread_rwlock_destroy(pthread_rwlock_t *l)
#undef _POSIX_THREAD_PRIORITY_SCHEDULING {
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 (void) *l;
return 0;
}
#undef _POSIX_THREAD_PROCESS_SHARED static int pthread_rwlock_rdlock(pthread_rwlock_t *l)
#define _POSIX_THREAD_PROCESS_SHARED -1 {
pthread_testcancel();
AcquireSRWLockShared(l);
return 0;
}
/* static int pthread_rwlock_wrlock(pthread_rwlock_t *l)
* POSIX 1003.1-2001 Limits {
* =========================== pthread_testcancel();
* AcquireSRWLockExclusive(l);
* 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
#undef PTHREAD_DESTRUCTOR_ITERATIONS return 0;
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS }
#undef _POSIX_THREAD_KEYS_MAX static void pthread_tls_init(void)
#define _POSIX_THREAD_KEYS_MAX 128 {
_pthread_tls = TlsAlloc();
#undef PTHREAD_KEYS_MAX /* Cannot continue if out of indexes */
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
}
#undef PTHREAD_STACK_MIN static int pthread_rwlock_unlock(pthread_rwlock_t *l)
#define PTHREAD_STACK_MIN 0 {
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 _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
#define _POSIX_THREAD_THREADS_MAX 64
/* Arbitrary value */ t = (pthread_t) TlsGetValue(_pthread_tls);
#undef PTHREAD_THREADS_MAX
#define PTHREAD_THREADS_MAX 2019
#undef _POSIX_SEM_NSEMS_MAX /* Main thread? */
#define _POSIX_SEM_NSEMS_MAX 256 if (!t)
{
t = (pthread_t) malloc(sizeof(struct _pthread_v));
/* Arbitrary value */ /* If cannot initialize main thread, then the only thing we can do is abort */
#undef SEM_NSEMS_MAX if (!t) abort();
#define SEM_NSEMS_MAX 1024
#undef _POSIX_SEM_VALUE_MAX t->ret_arg = NULL;
#define _POSIX_SEM_VALUE_MAX 32767 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 /* Save for later */
#define SEM_VALUE_MAX INT_MAX 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) /* Time to die */
# error Please upgrade your GNU compiler to one that supports __declspec. _endthreadex(0);
#endif }
}
/* return t;
* 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
/*
* 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 static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
# include <sys/types.h> {
#else /* Get the current state of the lock */
/* void *state = *(void **) l;
* 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;
/* if (!state)
* ==================== {
* ==================== /* Unlocked to locked */
* POSIX Threads if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)0x11, NULL)) return 0;
* ==================== return EBUSY;
* ==================== }
*/
enum { /* A single writer exists */
/* if (state == (void *) 1) return EBUSY;
* pthread_attr_{get,set}detachstate
*/
PTHREAD_CREATE_JOINABLE = 0, /* Default */
PTHREAD_CREATE_DETACHED = 1,
/* /* Multiple writers exist? */
* pthread_attr_{get,set}inheritsched if ((uintptr_t) state & 14) return EBUSY;
*/
PTHREAD_INHERIT_SCHED = 0,
PTHREAD_EXPLICIT_SCHED = 1, /* Default */
/* if ((void*) INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *) ((uintptr_t)state + 16), state) == state) return 0;
* pthread_{get,set}scope
*/
PTHREAD_SCOPE_PROCESS = 0,
PTHREAD_SCOPE_SYSTEM = 1, /* Default */
/* return EBUSY;
* pthread_setcancelstate paramters }
*/
PTHREAD_CANCEL_ENABLE = 0, /* Default */
PTHREAD_CANCEL_DISABLE = 1,
/* static int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
* pthread_setcanceltype parameters {
*/ /* Try to grab lock if it has no users */
PTHREAD_CANCEL_ASYNCHRONOUS = 0, if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)1, NULL)) return 0;
PTHREAD_CANCEL_DEFERRED = 1, /* Default */
/* return EBUSY;
* pthread_mutexattr_{get,set}pshared }
* pthread_condattr_{get,set}pshared
*/
PTHREAD_PROCESS_PRIVATE = 0,
PTHREAD_PROCESS_SHARED = 1,
/* static unsigned long long _pthread_time_in_ms(void)
* pthread_barrier_wait {
*/ struct __timeb64 tb;
PTHREAD_BARRIER_SERIAL_THREAD = -1
};
/* _ftime64(&tb);
* ====================
* ====================
* Cancelation
* ====================
* ====================
*/
#define PTHREAD_CANCELED ((void *) -1)
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;
* Once Key t += ts->tv_nsec / 1000000;
* ====================
* ==================== return t;
*/ }
#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
struct pthread_once_t_ static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
{ {
int done; /* indicates if user function has been executed */ unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
void * lock; unsigned long long t2 = _pthread_time_in_ms();
int reserved1;
int reserved2;
};
/* 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();
* Object initialisers unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
* ====================
* ====================
*/
#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)
/* pthread_testcancel();
* Compatibility with LinuxThreads
*/
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
#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);
/* pthread_testcancel();
* 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
};
/* 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) /* Have we waited long enough? */
/* Disable MSVC 'anachronism used' warning */ if (ct > t) return ETIMEDOUT;
#pragma warning( disable : 4229 ) }
#endif }
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) static int pthread_set_concurrency(int val)
#pragma warning( default : 4229 ) {
#endif _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; pthread_t t = pthread_self();
void *arg;
struct ptw32_cleanup_t *prev; 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 ctxt.ContextFlags = CONTEXT_CONTROL;
/*
* 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 ); \
}
SuspendThread(t->h);
GetThreadContext(t->h, &ctxt);
#ifdef _M_X64
ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
#else #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);
}
/* return 0;
* =============== }
* ===============
* Methods
* ===============
* ===============
*/
/* static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag)
* PThread Attribute Functions {
*/ return attr->p_state & flag;
PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); }
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, return 0;
int *detachstate); }
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, static int pthread_attr_init(pthread_attr_t *attr)
void **stackaddr); {
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, static int pthread_attr_destroy(pthread_attr_t *attr)
size_t * stacksize); {
/* 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, static int pthread_attr_setdetachstate(pthread_attr_t *a, int flag)
void *stackaddr); {
return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, static int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag)
size_t stacksize); {
*flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, static int pthread_attr_setinheritsched(pthread_attr_t *a, int flag)
struct sched_param *param); {
return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, static int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag)
const struct sched_param *param); {
*flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, static int pthread_attr_setscope(pthread_attr_t *a, int flag)
int); {
return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, static int pthread_attr_getscope(pthread_attr_t *a, int *flag)
int *); {
*flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, static int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack)
int inheritsched); {
*stack = attr->stack;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, static int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack)
int * inheritsched); {
attr->stack = stack;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, static int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size)
int); {
*size = attr->s_size;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, static int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
int *); {
attr->s_size = size;
return 0;
}
/* #define pthread_attr_getguardsize(A, S) ENOTSUP
* PThread Functions #define pthread_attr_setgaurdsize(A, S) ENOTSUP
*/ #define pthread_attr_getschedparam(A, S) ENOTSUP
PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, #define pthread_attr_setschedparam(A, S) ENOTSUP
const pthread_attr_t * attr, #define pthread_attr_getschedpolicy(A, S) ENOTSUP
void *(*start) (void *), #define pthread_attr_setschedpolicy(A, S) ENOTSUP
void *arg);
PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid);
PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, static int pthread_setcancelstate(int state, int *oldstate)
pthread_t t2); {
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, return 0;
void **value_ptr); }
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, return 0;
int *oldstate); }
PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, static int pthread_create_wrapper(void *args)
int *oldtype); {
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, TlsSetValue(_pthread_tls, tv);
void (*init_routine) (void));
#if PTW32_LEVEL >= PTW32_LEVEL_MAX if (!setjmp(tv->jb))
PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); {
/* 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, /* Clean up destructors */
void (*routine) (void *), _pthread_cleanup_dest(tv);
void *arg); }
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/* /* If we exit too early, then we can race with create */
* Thread Specific Data Functions while (tv->h == (HANDLE) -1)
*/ {
PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, YieldProcessor();
void (*destructor) (void *)); _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, return 0;
const void *value); }
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;
/* *th = tv;
* Mutex Attribute Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr);
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 if (attr)
* attr, {
int *pshared); tv->p_state = attr->p_state;
ssize = attr->s_size;
}
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, /* Make sure tv->h has value of -1 */
int pshared); _ReadWriteBarrier();
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); #ifdef __cplusplus
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); 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 */
* Barrier Attribute Functions if (!tv->h) return 1;
*/
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr);
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 return 0;
* attr, }
int *pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, static int pthread_join(pthread_t t, void **res)
int pshared); {
struct _pthread_v *tv = t;
/* pthread_testcancel();
* Mutex Functions
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr);
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, free(tv);
const struct timespec *abstime);
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); static int pthread_detach(pthread_t t)
{
struct _pthread_v *tv = t;
/* /*
* Spinlock Functions * This can't race with thread exit because
*/ * our call would be undefined if called on a dead thread.
PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); */
PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); CloseHandle(tv->h);
_ReadWriteBarrier();
tv->h = 0;
PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); static int pthread_mutexattr_init(pthread_mutexattr_t *a)
{
*a = 0;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); static int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
{
(void) a;
return 0;
}
/* static int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type)
* Barrier Functions {
*/ *type = *a & 3;
PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier,
const pthread_barrierattr_t * attr,
unsigned int count);
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;
/* return 0;
* Condition Variable Attribute Functions }
*/
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr);
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, return 0;
int *pshared); }
PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, static int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type)
int pshared); {
if ((type & 4) != type) return EINVAL;
/* *a &= ~4;
* Condition Variable Functions *a |= type;
*/
PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond,
const pthread_condattr_t * attr);
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, static int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type)
pthread_mutex_t * mutex); {
*type = *a & (8 + 16);
PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, return 0;
pthread_mutex_t * mutex, }
const struct timespec *abstime);
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;
/* return 0;
* Scheduling }
*/
PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread,
int policy,
const struct sched_param *param);
PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, static int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio)
int *policy, {
struct sched_param *param); *prio = *a / PTHREAD_PRIO_MULT;
return 0;
}
PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); static int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
{
PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); *a &= (PTHREAD_PRIO_MULT - 1);
*a += prio * PTHREAD_PRIO_MULT;
/* return 0;
* Read-Write Lock Functions }
*/
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock,
const pthread_rwlockattr_t *attr);
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, while (1)
const struct timespec *abstime); {
/* 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, /* Try to grab lock */
const struct timespec *abstime); 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, while (b->total > _PTHREAD_BARRIER_FLAG)
int *pshared); {
/* Wait until everyone exits the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, LeaveCriticalSection(&b->m);
int pshared);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 DeleteCriticalSection(&b->m);
/* return 0;
* Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32 }
* already have signal.h that don't define these.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
/* static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count)
* Non-portable functions {
*/ /* Ignore attr */
(void) attr;
/* b->count = count;
* Compatibility with Linux. b->total = 0;
*/
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr,
int kind);
PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr,
int *kind);
/* InitializeCriticalSection(&b->m);
* Possibly supported by other POSIX threads implementations InitializeConditionVariable(&b->cv);
*/
PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
/* return 0;
* Useful if an application wants to statically link }
* the lib rather than load the DLL at run-time.
*/
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void);
/* static int pthread_barrier_wait(pthread_barrier_t *b)
* Features that are auto-detected at load/run time. {
*/ EnterCriticalSection(&b->m);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int);
enum ptw32_features {
PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
};
/* while (b->total > _PTHREAD_BARRIER_FLAG)
* Register a system time change with the library. {
* Causes the library to perform various functions /* Wait until everyone exits the barrier */
* in response to the change. Should be called whenever SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
* 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 *);
#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++;
/* if (b->total == b->count)
* Returns the Win32 HANDLE for the POSIX thread. {
*/ b->total += _PTHREAD_BARRIER_FLAG - 1;
PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); WakeAllConditionVariable(&b->cv);
LeaveCriticalSection(&b->m);
/* return 1;
* Protected Methods }
* else
* This function blocks until the given WIN32 handle {
* is signaled or pthread_cancel had been called. while (b->total < _PTHREAD_BARRIER_FLAG)
* This function allows the caller to hook into the {
* PThreads cancel mechanism. It is implemented using /* Wait until enough threads enter the barrier */
* SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
* 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);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ b->total--;
/* /* Get entering threads to wake up */
* Thread-Safe C Runtime Library Mappings. if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
*/
#ifndef _UWIN
# if defined(NEED_ERRNO)
PTW32_DLLPORT int * PTW32_CDECL _errno( void );
# else
# ifndef errno
# if (defined(_MT) || defined(_DLL))
__declspec(dllimport) extern int * __cdecl _errno(void);
# define errno (*_errno())
# endif
# endif
# endif
#endif
/* LeaveCriticalSection(&b->m);
* WIN32 C runtime library had been made thread-safe
* without affecting the user interface. Provide
* mappings from the UNIX thread-safe versions to
* the standard C runtime library calls.
* Only provide function mappings for functions that
* actually exist on WIN32.
*/
#if !defined(__MINGW32__) return 0;
#define strtok_r( _s, _sep, _lasts ) \ }
( *(_lasts) = strtok( (_s), (_sep) ) ) }
#endif /* !__MINGW32__ */
#define asctime_r( _tm, _buf ) \ static int pthread_barrierattr_init(void **attr)
( strcpy( (_buf), asctime( (_tm) ) ), \ {
(_buf) ) *attr = NULL;
return 0;
}
#define ctime_r( _clock, _buf ) \ static int pthread_barrierattr_destroy(void **attr)
( strcpy( (_buf), ctime( (_clock) ) ), \ {
(_buf) ) /* Ignore attr */
(void) attr;
#define gmtime_r( _clock, _result ) \ return 0;
( *(_result) = *gmtime( (_clock) ), \ }
(_result) )
#define localtime_r( _clock, _result ) \ static int pthread_barrierattr_setpshared(void **attr, int s)
( *(_result) = *localtime( (_clock) ), \ {
(_result) ) *attr = (void *) s;
return 0;
}
#define rand_r( _seed ) \ static int pthread_barrierattr_getpshared(void **attr, int *s)
( _seed == _seed? rand() : rand() ) {
*s = (int) (size_t) *attr;
return 0;
}
/* static int pthread_key_create(pthread_key_t *key, void (* dest)(void *))
* Some compiler environments don't define some things. {
*/ int i;
#if defined(__BORLANDC__) long nmax;
# define _ftime ftime void (**d)(void *);
# define _timeb timeb
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 #endif
if (!d)
{
pthread_rwlock_unlock(&_pthread_key_lock);
#ifdef __cplusplus return ENOMEM;
}
/* /* Clear new region */
* Internal exceptions memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
*/
class ptw32_exception {};
class ptw32_exception_cancel : public ptw32_exception {};
class ptw32_exception_exit : public ptw32_exception {};
#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 */ pthread_rwlock_unlock(&_pthread_key_lock);
/*
* Get internal SEH tag
*/
PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
#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;
/* /* Start next search from our location */
* Redefine the SEH __except keyword to ensure that applications if (_pthread_key_sch > key) _pthread_key_sch = key;
* 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 ) )
#endif /* __CLEANUP_SEH */ pthread_rwlock_unlock(&_pthread_key_lock);
#ifdef __CLEANUP_CXX return 0;
}
/* static void *pthread_getspecific(pthread_key_t key)
* Redefine the C++ catch keyword to ensure that applications {
* propagate our internal exceptions up to the library's internal handlers. pthread_t t = pthread_self();
*/
#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("------------------------------------------------------------------")
#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 ) \ if (key > t->keymax)
catch( ptw32_exception & ) { throw; } \ {
catch( E ) 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 t->keyval[key] = (void *) value;
} /* End of extern "C" */
#endif /* __cplusplus */
#ifdef PTW32__HANDLE_DEF return 0;
# undef HANDLE }
#endif
#ifdef PTW32__DWORD_DEF
# undef DWORD static int pthread_spin_init(pthread_spinlock_t *l, int pshared)
#endif {
(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 pthread_testcancel();
#undef PTW32_LEVEL_MAX
#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 */
/*
* Module: sched.h
*
* Purpose:
* Provides an implementation of POSIX realtime extensions
* as defined in
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _SCHED_H
#define _SCHED_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#if defined(__MINGW32__) || defined(_UWIN)
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
/* For pid_t */
# include <sys/types.h>
/* Required by Unix 98 */
# include <time.h>
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#else
typedef int pid_t;
#endif
/* Thread scheduling policies */
enum {
SCHED_OTHER = 0,
SCHED_FIFO,
SCHED_RR,
SCHED_MIN = SCHED_OTHER,
SCHED_MAX = SCHED_RR
};
struct sched_param {
int sched_priority;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
PTW32_DLLPORT int __cdecl sched_yield (void);
PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
/*
* Note that this macro returns ENOTSUP rather than
* ENOSYS as might be expected. However, returning ENOSYS
* should mean that sched_get_priority_{min,max} are
* not implemented as well as sched_rr_get_interval.
* This is not the case, since we just don't support
* round-robin scheduling. Therefore I have chosen to
* return the same value as sched_setscheduler when
* SCHED_RR is passed to it.
*/
#define sched_rr_get_interval(_pid, _interval) \
( errno = ENOTSUP, (int) -1 )
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !_SCHED_H */
/*
* Module: semaphore.h
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
* They are defined by the POSIX Standard:
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined( SEMAPHORE_H )
#define SEMAPHORE_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#define _POSIX_SEMAPHORES
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef HAVE_MODE_T
typedef unsigned int mode_t;
#endif
typedef struct sem_t_ * sem_t;
PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
int pshared,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
const struct timespec * abstime);
PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
int count);
PTW32_DLLPORT int __cdecl sem_open (const char * name,
int oflag,
mode_t mode,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
int * sval);
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !SEMAPHORE_H */
#include "pthread.h"
PTHREAD_EXPORT volatile long _pthread_cancelling;
PTHREAD_EXPORT int _pthread_concur;
/* Will default to zero as needed */
PTHREAD_EXPORT pthread_once_t _pthread_tls_once;
PTHREAD_EXPORT DWORD _pthread_tls;
/* Note initializer is zero, so this works */
PTHREAD_EXPORT pthread_rwlock_t _pthread_key_lock;
PTHREAD_EXPORT long _pthread_key_max;
PTHREAD_EXPORT long _pthread_key_sch;
PTHREAD_EXPORT void (**_pthread_key_dest)(void *);
/* Portions copyright (c) 2006-2013 Stanford University and Simbios. /* Portions copyright (c) 2006-2015 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -174,8 +174,8 @@ protected: ...@@ -174,8 +174,8 @@ protected:
float alphaEwald; float alphaEwald;
int numRx, numRy, numRz; int numRx, numRy, numRz;
int meshDim[3]; int meshDim[3];
std::vector<float> ewaldScaleTable; std::vector<float> erfcTable, ewaldScaleTable;
float ewaldDX, ewaldDXInv; float ewaldDX, ewaldDXInv, erfcDXInv;
std::vector<double> threadEnergy; std::vector<double> threadEnergy;
// The following variables are used to make information accessible to the individual threads. // The following variables are used to make information accessible to the individual threads.
int numberOfAtoms; int numberOfAtoms;
...@@ -241,7 +241,7 @@ protected: ...@@ -241,7 +241,7 @@ protected:
/** /**
* Compute a fast approximation to erfc(x). * Compute a fast approximation to erfc(x).
*/ */
static float erfcApprox(float x); float erfcApprox(float x);
}; };
} // namespace OpenMM } // namespace OpenMM
......
/* Portions copyright (c) 2006-2014 Stanford University and Simbios. /* Portions copyright (c) 2006-2015 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -87,7 +87,7 @@ protected: ...@@ -87,7 +87,7 @@ protected:
/** /**
* Compute a fast approximation to erfc(x). * Compute a fast approximation to erfc(x).
*/ */
static fvec4 erfcApprox(const fvec4& x); fvec4 erfcApprox(const fvec4& x);
/** /**
* Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI) * Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
......
/* Portions copyright (c) 2006-2014 Stanford University and Simbios. /* Portions copyright (c) 2006-2015 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -86,7 +86,7 @@ protected: ...@@ -86,7 +86,7 @@ protected:
/** /**
* Compute a fast approximation to erfc(x). * Compute a fast approximation to erfc(x).
*/ */
static fvec8 erfcApprox(const fvec8& x); fvec8 erfcApprox(const fvec8& x);
/** /**
* Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI) * Evaluate the scale factor used with Ewald and PME: erfc(alpha*r) + 2*alpha*r*exp(-alpha*alpha*r*r)/sqrt(PI)
......
...@@ -171,17 +171,20 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) { ...@@ -171,17 +171,20 @@ void CpuNonbondedForce::setUseSwitchingFunction(float distance) {
} }
void CpuNonbondedForce::tabulateEwaldScaleFactor() { void CpuNonbondedForce::tabulateEwaldScaleFactor() {
if (tableIsValid) if (tableIsValid)
return; return;
tableIsValid = true; tableIsValid = true;
ewaldDX = cutoffDistance/NUM_TABLE_POINTS; ewaldDX = cutoffDistance/NUM_TABLE_POINTS;
ewaldDXInv = 1.0f/ewaldDX; ewaldDXInv = 1.0f/ewaldDX;
erfcDXInv = 1.0f/(ewaldDX*alphaEwald);
erfcTable.resize(NUM_TABLE_POINTS+4);
ewaldScaleTable.resize(NUM_TABLE_POINTS+4); ewaldScaleTable.resize(NUM_TABLE_POINTS+4);
for (int i = 0; i < NUM_TABLE_POINTS+4; i++) { for (int i = 0; i < NUM_TABLE_POINTS+4; i++) {
double r = i*ewaldDX; double r = i*ewaldDX;
double alphaR = alphaEwald*r; double alphaR = alphaEwald*r;
ewaldScaleTable[i] = erfc(alphaR) + TWO_OVER_SQRT_PI*alphaR*exp(-alphaR*alphaR); erfcTable[i] = erfc(alphaR);
ewaldScaleTable[i] = erfcTable[i] + TWO_OVER_SQRT_PI*alphaR*exp(-alphaR*alphaR);
} }
} }
...@@ -473,14 +476,10 @@ void CpuNonbondedForce::getDeltaR(const fvec4& posI, const fvec4& posJ, fvec4& d ...@@ -473,14 +476,10 @@ void CpuNonbondedForce::getDeltaR(const fvec4& posI, const fvec4& posJ, fvec4& d
} }
float CpuNonbondedForce::erfcApprox(float x) { float CpuNonbondedForce::erfcApprox(float x) {
// This approximation for erfc is from Abramowitz and Stegun (1964) p. 299. They cite the following as float x1 = x*erfcDXInv;
// the original source: C. Hastings, Jr., Approximations for Digital Computers (1955). It has a maximum int index = min((int) floor(x1), NUM_TABLE_POINTS);
// error of 3e-7. float coeff2 = x1-index;
float coeff1 = 1.0f-coeff2;
float t = 1.0f+(0.0705230784f+(0.0422820123f+(0.0092705272f+(0.0001520143f+(0.0002765672f+0.0000430638f*x)*x)*x)*x)*x)*x; return coeff1*erfcTable[index] + coeff2*erfcTable[index+1];
t *= t;
t *= t;
t *= t;
return 1.0f/(t*t);
} }
/* Portions copyright (c) 2006-2014 Stanford University and Simbios. /* Portions copyright (c) 2006-2015 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -393,15 +393,16 @@ void CpuNonbondedForceVec4::getDeltaR(const fvec4& posI, const fvec4& x, const f ...@@ -393,15 +393,16 @@ void CpuNonbondedForceVec4::getDeltaR(const fvec4& posI, const fvec4& x, const f
} }
fvec4 CpuNonbondedForceVec4::erfcApprox(const fvec4& x) { fvec4 CpuNonbondedForceVec4::erfcApprox(const fvec4& x) {
// This approximation for erfc is from Abramowitz and Stegun (1964) p. 299. They cite the following as fvec4 x1 = x*erfcDXInv;
// the original source: C. Hastings, Jr., Approximations for Digital Computers (1955). It has a maximum ivec4 index = min(floor(x1), NUM_TABLE_POINTS);
// error of 3e-7. fvec4 coeff2 = x1-index;
fvec4 coeff1 = 1.0f-coeff2;
fvec4 t = 1.0f+(0.0705230784f+(0.0422820123f+(0.0092705272f+(0.0001520143f+(0.0002765672f+0.0000430638f*x)*x)*x)*x)*x)*x; fvec4 t1(&erfcTable[index[0]]);
t *= t; fvec4 t2(&erfcTable[index[1]]);
t *= t; fvec4 t3(&erfcTable[index[2]]);
t *= t; fvec4 t4(&erfcTable[index[3]]);
return 1.0f/(t*t); transpose(t1, t2, t3, t4);
return coeff1*t1 + coeff2*t2;
} }
fvec4 CpuNonbondedForceVec4::ewaldScaleFunction(const fvec4& x) { fvec4 CpuNonbondedForceVec4::ewaldScaleFunction(const fvec4& x) {
......
/* Portions copyright (c) 2006-2014 Stanford University and Simbios. /* Portions copyright (c) 2006-2015 Stanford University and Simbios.
* Contributors: Pande Group * Contributors: Pande Group
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
...@@ -423,15 +423,23 @@ void CpuNonbondedForceVec8::getDeltaR(const fvec4& posI, const fvec8& x, const f ...@@ -423,15 +423,23 @@ void CpuNonbondedForceVec8::getDeltaR(const fvec4& posI, const fvec8& x, const f
} }
fvec8 CpuNonbondedForceVec8::erfcApprox(const fvec8& x) { fvec8 CpuNonbondedForceVec8::erfcApprox(const fvec8& x) {
// This approximation for erfc is from Abramowitz and Stegun (1964) p. 299. They cite the following as fvec8 x1 = x*erfcDXInv;
// the original source: C. Hastings, Jr., Approximations for Digital Computers (1955). It has a maximum ivec8 index = min(floor(x1), NUM_TABLE_POINTS);
// error of 3e-7. fvec8 coeff2 = x1-index;
fvec8 coeff1 = 1.0f-coeff2;
fvec8 t = 1.0f+(0.0705230784f+(0.0422820123f+(0.0092705272f+(0.0001520143f+(0.0002765672f+0.0000430638f*x)*x)*x)*x)*x)*x; ivec4 indexLower = index.lowerVec();
t *= t; ivec4 indexUpper = index.upperVec();
t *= t; fvec4 t1(&erfcTable[indexLower[0]]);
t *= t; fvec4 t2(&erfcTable[indexLower[1]]);
return 1.0f/(t*t); fvec4 t3(&erfcTable[indexLower[2]]);
fvec4 t4(&erfcTable[indexLower[3]]);
fvec4 t5(&erfcTable[indexUpper[0]]);
fvec4 t6(&erfcTable[indexUpper[1]]);
fvec4 t7(&erfcTable[indexUpper[2]]);
fvec4 t8(&erfcTable[indexUpper[3]]);
fvec8 s1, s2, s3, s4;
transpose(t1, t2, t3, t4, t5, t6, t7, t8, s1, s2, s3, s4);
return coeff1*s1 + coeff2*s2;
} }
fvec8 CpuNonbondedForceVec8::ewaldScaleFunction(const fvec8& x) { fvec8 CpuNonbondedForceVec8::ewaldScaleFunction(const fvec8& x) {
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#include <stdio.h> #include <stdio.h>
#define NOMINMAX
#include <pthread.h> #include <pthread.h>
#ifdef __cplusplus #ifdef __cplusplus
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment