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
* --------------------------------------------------------------------------
* *
* Pthreads-win32 - POSIX Threads Library for Win32 * Use at own risk, there is no implied warranty to this code.
* Copyright(C) 1998 John E. Bossom * It uses undocumented features of Microsoft Windows that can change
* Copyright(C) 1999,2005 Pthreads-win32 contributors * at any time in the future.
* *
* Contact Email: rpj@callisto.canberra.edu.au * (C) 2010 Lockless Inc.
* All rights reserved.
* *
* The current list of contributors is contained * Redistribution and use in source and binary forms, with or without modification,
* in the file CONTRIBUTORS included with the source * are permitted provided that the following conditions are met:
* 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, * * Redistributions of source code must retain the above copyright notice,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * this list of conditions and the following disclaimer.
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Redistributions in binary form must reproduce the above copyright notice,
* Lesser General Public License for more details. * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Lockless Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
* *
* You should have received a copy of the GNU Lesser General Public * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
* License along with this library in the file COPYING.LIB; * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* if not, write to the Free Software Foundation, Inc., * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#if !defined( PTHREAD_H )
#define PTHREAD_H
/* /*
* See the README file for an explanation of the pthreads-win32 version * You may want to use the MingW64 winpthreads library instead.
* numbering scheme and how the DLL is named etc. * It is based on this, but adds error checking.
*/
#define PTW32_VERSION 2,8,0,0
#define PTW32_VERSION_STRING "2, 8, 0, 0\0"
/* There are three implementations of cancel cleanup.
* Note that pthread.h is included in both application
* compilation units and also internally for the library.
* The code here and within the library aims to work
* for all reasonable combinations of environments.
*
* The three implementations are:
*
* WIN32 SEH
* C
* C++
*
* Please note that exiting a push/pop block via
* "return", "exit", "break", or "continue" will
* lead to different behaviour amongst applications
* depending upon whether the library was built
* using SEH, C++, or C. For example, a library built
* with SEH will call the cleanup routine, while both
* C++ and C built versions will not.
*/ */
/* /*
* Define defaults for cleanup code. * Version 1.0.1 Released 2 Feb 2012
* Note: Unless the build explicitly defines one of the following, then * Fixes pthread_barrier_destroy() to wait for threads to exit the barrier.
* 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)) #ifndef WIN_PTHREADS
#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. #define WIN_PTHREADS
#endif
/*
* Stop here if we are being included by the resource compiler.
*/
#ifndef RC_INVOKED
#undef PTW32_LEVEL #include <windows.h>
#include <intrin.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/timeb.h>
#include <process.h>
#if defined(_POSIX_SOURCE) #define ETIMEDOUT 110
#define PTW32_LEVEL 0 #define ENOTSUP 134
/* 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) #define PTHREAD_CANCEL_DISABLE 0
#undef PTW32_LEVEL #define PTHREAD_CANCEL_ENABLE 0x01
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3 #define PTHREAD_CANCEL_DEFERRED 0
#define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
#if !defined(PTW32_LEVEL) #define PTHREAD_CREATE_JOINABLE 0
#define PTW32_LEVEL PTW32_LEVEL_MAX #define PTHREAD_CREATE_DETACHED 0x04
/* Include everything */
#endif
#if defined(_UWIN) #define PTHREAD_EXPLICT_SCHED 0
# define HAVE_STRUCT_TIMESPEC 1 #define PTHREAD_INHERIT_SCHED 0x08
# 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_SCOPE_PROCESS 0
* ------------------------------------------------------------- #define PTHREAD_SCOPE_SYSTEM 0x10
*
*
* 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_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE)
#if defined(__MINGW32__) && defined(__cplusplus)
#define PTW32_INCLUDE_WINDOWS_H
#endif
#ifdef PTW32_INCLUDE_WINDOWS_H #define PTHREAD_CANCELED ((void *) 0xDEADBEEF)
#include <windows.h>
#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;
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX extern PTHREAD_EXPORT int _pthread_concur;
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
/* /* Will default to zero as needed */
* Several systems don't define some error numbers. extern PTHREAD_EXPORT pthread_once_t _pthread_tls_once;
*/ extern PTHREAD_EXPORT DWORD _pthread_tls;
#ifndef ENOTSUP
# define ENOTSUP 48 /* This is the value in Solaris. */
#endif
#ifndef ETIMEDOUT /* Note initializer is zero, so this works */
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ extern PTHREAD_EXPORT pthread_rwlock_t _pthread_key_lock;
#endif extern PTHREAD_EXPORT long _pthread_key_max;
extern PTHREAD_EXPORT long _pthread_key_sch;
extern PTHREAD_EXPORT void (**_pthread_key_dest)(void *);
#ifndef ENOSYS
# define ENOSYS 140 /* Semi-arbitrary value */
#endif
#ifndef EDEADLK #define pthread_cleanup_push(F, A)\
# ifdef EDEADLOCK {\
# define EDEADLK EDEADLOCK const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\
# else _ReadWriteBarrier();\
# define EDEADLK 36 /* This is the value in MSVC. */ pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\
# endif _ReadWriteBarrier()
#endif
#include <sched.h> /* Note that if async cancelling is used, then there is a race here */
#define pthread_cleanup_pop(E)\
(pthread_self()->clean = _pthread_cup.next, (E?_pthread_cup.func(_pthread_cup.arg):0));}
/* static void _pthread_once_cleanup(pthread_once_t *o)
* To avoid including windows.h we define only those things that we {
* actually need from it. *o = 0;
*/ }
#ifndef PTW32_INCLUDE_WINDOWS_H
#ifndef HANDLE static pthread_t pthread_self(void);
# define PTW32__HANDLE_DEF static int pthread_once(pthread_once_t *o, void (*func)(void))
# define HANDLE void * {
#endif long state = *o;
#ifndef DWORD
# define PTW32__DWORD_DEF _ReadWriteBarrier();
# define DWORD unsigned long
#endif while (state != 1)
{
if (!state)
{
if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
#ifdef __cplusplus
pthread_cleanup_push(reinterpret_cast<void (__cdecl *)(void *)>(_pthread_once_cleanup), o);
#else
pthread_cleanup_push(_pthread_once_cleanup, o);
#endif #endif
func();
pthread_cleanup_pop(0);
#ifndef HAVE_STRUCT_TIMESPEC /* Mark as done */
#define HAVE_STRUCT_TIMESPEC 1 *o = 1;
struct timespec {
long tv_sec;
long tv_nsec;
};
#endif /* HAVE_STRUCT_TIMESPEC */
#ifndef SIG_BLOCK return 0;
#define SIG_BLOCK 0 }
#endif /* SIG_BLOCK */ }
#ifndef SIG_UNBLOCK YieldProcessor();
#define SIG_UNBLOCK 1
#endif /* SIG_UNBLOCK */
#ifndef SIG_SETMASK _ReadWriteBarrier();
#define SIG_SETMASK 2
#endif /* SIG_SETMASK */
#ifdef __cplusplus state = *o;
extern "C" }
/* Done */
return 0;
}
static int _pthread_once_raw(pthread_once_t *o, void (*func)(void))
{ {
#endif /* __cplusplus */ long state = *o;
/* _ReadWriteBarrier();
* -------------------------------------------------------------
*
* POSIX 1003.1-2001 Options
* =========================
*
* Options are normally set in <unistd.h>, which is not provided
* with pthreads-win32.
*
* For conformance with the Single Unix Specification (version 3), all of the
* options below are defined, and have a value of either -1 (not supported)
* or 200112L (supported).
*
* These options can neither be left undefined nor have a value of 0, because
* either indicates that sysconf(), which is not implemented, may be used at
* runtime to check the status of the option.
*
* _POSIX_THREADS (== 200112L)
* If == 200112L, you can use threads
*
* _POSIX_THREAD_ATTR_STACKSIZE (== 200112L)
* If == 200112L, you can control the size of a thread's
* stack
* pthread_attr_getstacksize
* pthread_attr_setstacksize
*
* _POSIX_THREAD_ATTR_STACKADDR (== -1)
* If == 200112L, you can allocate and control a thread's
* stack. If not supported, the following functions
* will return ENOSYS, indicating they are not
* supported:
* pthread_attr_getstackaddr
* pthread_attr_setstackaddr
*
* _POSIX_THREAD_PRIORITY_SCHEDULING (== -1)
* If == 200112L, you can use realtime scheduling.
* This option indicates that the behaviour of some
* implemented functions conforms to the additional TPS
* requirements in the standard. E.g. rwlocks favour
* writers over readers when threads have equal priority.
*
* _POSIX_THREAD_PRIO_INHERIT (== -1)
* If == 200112L, you can create priority inheritance
* mutexes.
* pthread_mutexattr_getprotocol +
* pthread_mutexattr_setprotocol +
*
* _POSIX_THREAD_PRIO_PROTECT (== -1)
* If == 200112L, you can create priority ceiling mutexes
* Indicates the availability of:
* pthread_mutex_getprioceiling
* pthread_mutex_setprioceiling
* pthread_mutexattr_getprioceiling
* pthread_mutexattr_getprotocol +
* pthread_mutexattr_setprioceiling
* pthread_mutexattr_setprotocol +
*
* _POSIX_THREAD_PROCESS_SHARED (== -1)
* If set, you can create mutexes and condition
* variables that can be shared with another
* process.If set, indicates the availability
* of:
* pthread_mutexattr_getpshared
* pthread_mutexattr_setpshared
* pthread_condattr_getpshared
* pthread_condattr_setpshared
*
* _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L)
* If == 200112L you can use the special *_r library
* functions that provide thread-safe behaviour
*
* _POSIX_READER_WRITER_LOCKS (== 200112L)
* If == 200112L, you can use read/write locks
*
* _POSIX_SPIN_LOCKS (== 200112L)
* If == 200112L, you can use spin locks
*
* _POSIX_BARRIERS (== 200112L)
* If == 200112L, you can use barriers
*
* + These functions provide both 'inherit' and/or
* 'protect' protocol, based upon these macro
* settings.
*
* -------------------------------------------------------------
*/
/* while (state != 1)
* POSIX Options {
*/ if (!state)
#undef _POSIX_THREADS {
#define _POSIX_THREADS 200112L if (!_InterlockedCompareExchange(o, 2, 0))
{
/* Success */
func();
/* Mark as done */
*o = 1;
#undef _POSIX_READER_WRITER_LOCKS return 0;
#define _POSIX_READER_WRITER_LOCKS 200112L }
}
#undef _POSIX_SPIN_LOCKS YieldProcessor();
#define _POSIX_SPIN_LOCKS 200112L
#undef _POSIX_BARRIERS _ReadWriteBarrier();
#define _POSIX_BARRIERS 200112L
#undef _POSIX_THREAD_SAFE_FUNCTIONS state = *o;
#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L }
#undef _POSIX_THREAD_ATTR_STACKSIZE /* Done */
#define _POSIX_THREAD_ATTR_STACKSIZE 200112L return 0;
}
/* static int pthread_mutex_lock(pthread_mutex_t *m)
* The following options are not supported {
*/ EnterCriticalSection(m);
#undef _POSIX_THREAD_ATTR_STACKADDR return 0;
#define _POSIX_THREAD_ATTR_STACKADDR -1 }
#undef _POSIX_THREAD_PRIO_INHERIT static int pthread_mutex_unlock(pthread_mutex_t *m)
#define _POSIX_THREAD_PRIO_INHERIT -1 {
LeaveCriticalSection(m);
return 0;
}
#undef _POSIX_THREAD_PRIO_PROTECT static int pthread_mutex_trylock(pthread_mutex_t *m)
#define _POSIX_THREAD_PRIO_PROTECT -1 {
return TryEnterCriticalSection(m) ? 0 : EBUSY;
}
/* TPS is not fully supported. */ static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
#undef _POSIX_THREAD_PRIORITY_SCHEDULING {
#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 (void) a;
InitializeCriticalSection(m);
#undef _POSIX_THREAD_PROCESS_SHARED return 0;
#define _POSIX_THREAD_PROCESS_SHARED -1 }
static int pthread_mutex_destroy(pthread_mutex_t *m)
{
DeleteCriticalSection(m);
return 0;
}
/* #define pthread_mutex_getprioceiling(M, P) ENOTSUP
* POSIX 1003.1-2001 Limits #define pthread_mutex_setprioceiling(M, P) ENOTSUP
* ===========================
*
* 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 static int pthread_equal(pthread_t t1, pthread_t t2)
#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS {
return t1 == t2;
}
#undef _POSIX_THREAD_KEYS_MAX static void pthread_testcancel(void);
#define _POSIX_THREAD_KEYS_MAX 128
#undef PTHREAD_KEYS_MAX static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX {
(void) a;
InitializeSRWLock(l);
#undef PTHREAD_STACK_MIN return 0;
#define PTHREAD_STACK_MIN 0 }
#undef _POSIX_THREAD_THREADS_MAX static int pthread_rwlock_destroy(pthread_rwlock_t *l)
#define _POSIX_THREAD_THREADS_MAX 64 {
(void) *l;
return 0;
}
/* Arbitrary value */ static int pthread_rwlock_rdlock(pthread_rwlock_t *l)
#undef PTHREAD_THREADS_MAX {
#define PTHREAD_THREADS_MAX 2019 pthread_testcancel();
AcquireSRWLockShared(l);
#undef _POSIX_SEM_NSEMS_MAX return 0;
#define _POSIX_SEM_NSEMS_MAX 256 }
/* Arbitrary value */ static int pthread_rwlock_wrlock(pthread_rwlock_t *l)
#undef SEM_NSEMS_MAX {
#define SEM_NSEMS_MAX 1024 pthread_testcancel();
AcquireSRWLockExclusive(l);
#undef _POSIX_SEM_VALUE_MAX return 0;
#define _POSIX_SEM_VALUE_MAX 32767 }
#undef SEM_VALUE_MAX static void pthread_tls_init(void)
#define SEM_VALUE_MAX INT_MAX {
_pthread_tls = TlsAlloc();
/* Cannot continue if out of indexes */
if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
}
#if __GNUC__ && ! defined (__declspec) static int pthread_rwlock_unlock(pthread_rwlock_t *l)
# error Please upgrade your GNU compiler to one that supports __declspec. {
#endif void *state = *(void **)l;
/* if (state == (void *) 1)
* When building the DLL code, you should define PTW32_BUILD so that {
* the variables/functions are exported correctly. When using the DLL, /* Known to be an exclusive lock */
* do NOT define PTW32_BUILD, and then the variables/functions will ReleaseSRWLockExclusive(l);
* be imported correctly. }
*/ else
#ifndef PTW32_STATIC_LIB {
# ifdef PTW32_BUILD /* A shared unlock will work */
# define PTW32_DLLPORT __declspec (dllexport) ReleaseSRWLockShared(l);
# else }
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/* return 0;
* 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 void _pthread_cleanup_dest(pthread_t t)
# include <sys/types.h> {
#else int i, j;
/*
* 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;
/* for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
* ==================== {
* ==================== int flag = 0;
* POSIX Threads
* ====================
* ====================
*/
enum { for (i = 0; i < t->keymax; i++)
/* {
* pthread_attr_{get,set}detachstate void *val = t->keyval[i];
*/
PTHREAD_CREATE_JOINABLE = 0, /* Default */
PTHREAD_CREATE_DETACHED = 1,
/* if (val)
* pthread_attr_{get,set}inheritsched {
*/ pthread_rwlock_rdlock(&_pthread_key_lock);
PTHREAD_INHERIT_SCHED = 0, if ((uintptr_t) _pthread_key_dest[i] > 1)
PTHREAD_EXPLICIT_SCHED = 1, /* Default */ {
/* Call destructor */
t->keyval[i] = NULL;
_pthread_key_dest[i](val);
flag = 1;
}
pthread_rwlock_unlock(&_pthread_key_lock);
}
}
/* /* Nothing to do? */
* pthread_{get,set}scope if (!flag) return;
*/ }
PTHREAD_SCOPE_PROCESS = 0, }
PTHREAD_SCOPE_SYSTEM = 1, /* Default */
/* static pthread_t pthread_self(void)
* pthread_setcancelstate paramters {
*/ pthread_t t;
PTHREAD_CANCEL_ENABLE = 0, /* Default */
PTHREAD_CANCEL_DISABLE = 1,
/* _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
* pthread_setcanceltype parameters
*/
PTHREAD_CANCEL_ASYNCHRONOUS = 0,
PTHREAD_CANCEL_DEFERRED = 1, /* Default */
/* t = (pthread_t) TlsGetValue(_pthread_tls);
* pthread_mutexattr_{get,set}pshared
* pthread_condattr_{get,set}pshared
*/
PTHREAD_PROCESS_PRIVATE = 0,
PTHREAD_PROCESS_SHARED = 1,
/* /* Main thread? */
* pthread_barrier_wait if (!t)
*/ {
PTHREAD_BARRIER_SERIAL_THREAD = -1 t = (pthread_t) malloc(sizeof(struct _pthread_v));
};
/* /* If cannot initialize main thread, then the only thing we can do is abort */
* ==================== if (!t) abort();
* ====================
* Cancelation
* ====================
* ====================
*/
#define PTHREAD_CANCELED ((void *) -1)
t->ret_arg = NULL;
t->func = NULL;
t->clean = NULL;
t->cancelled = 0;
t->p_state = PTHREAD_DEFAULT_ATTR;
t->keymax = 0;
t->keyval = NULL;
t->h = GetCurrentThread();
/* /* Save for later */
* ==================== TlsSetValue(_pthread_tls, t);
* ====================
* Once Key if (setjmp(t->jb))
* ==================== {
* ==================== /* Make sure we free ourselves if we are detached */
*/ if (!t->h) free(t);
#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0}
/* Time to die */
_endthreadex(0);
}
}
return t;
}
struct pthread_once_t_
static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
{ {
int done; /* indicates if user function has been executed */ /* Get the current state of the lock */
void * lock; void *state = *(void **) l;
int reserved1;
int reserved2;
};
if (!state)
{
/* Unlocked to locked */
if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)0x11, NULL)) return 0;
return EBUSY;
}
/* /* A single writer exists */
* ==================== if (state == (void *) 1) return EBUSY;
* ====================
* Object initialisers
* ====================
* ====================
*/
#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1)
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2)
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3)
/* /* Multiple writers exist? */
* Compatibility with LinuxThreads if ((uintptr_t) state & 14) return EBUSY;
*/
#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) if ((void*) INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *) ((uintptr_t)state + 16), state) == state) return 0;
#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) return EBUSY;
}
#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) static int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
{
/* Try to grab lock if it has no users */
if (!INTERLOCKED_COMPARE_EXCHANGE((volatile PVOID *) l, (void *)1, NULL)) return 0;
return EBUSY;
}
/* static unsigned long long _pthread_time_in_ms(void)
* Mutex types. {
*/ struct __timeb64 tb;
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
};
_ftime64(&tb);
typedef struct ptw32_cleanup_t ptw32_cleanup_t; return tb.time * 1000 + tb.millitm;
}
#if defined(_MSC_VER) static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
/* Disable MSVC 'anachronism used' warning */ {
#pragma warning( disable : 4229 ) unsigned long long t = ts->tv_sec * 1000;
#endif t += ts->tv_nsec / 1000000;
typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); return t;
}
#if defined(_MSC_VER) static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
#pragma warning( default : 4229 ) {
#endif unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
unsigned long long t2 = _pthread_time_in_ms();
/* Prevent underflow */
if (t1 < t2) return 0;
return t1 - t2;
}
struct ptw32_cleanup_t static int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts)
{ {
ptw32_cleanup_callback_t routine; unsigned long long ct = _pthread_time_in_ms();
void *arg; unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
struct ptw32_cleanup_t *prev;
};
#ifdef __CLEANUP_SEH pthread_testcancel();
/*
* WIN32 SEH version of cancel cleanup.
*/
#define pthread_cleanup_push( _rout, _arg ) \ /* Use a busy-loop */
{ \ while (1)
ptw32_cleanup_t _cleanup; \ {
\ /* Try to grab lock */
_cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ if (!pthread_rwlock_tryrdlock(l)) return 0;
_cleanup.arg = (_arg); \
__try \ /* Get current time */
{ \ ct = _pthread_time_in_ms();
#define pthread_cleanup_pop( _execute ) \ /* Have we waited long enough? */
} \ if (ct > t) return ETIMEDOUT;
__finally \
{ \
if( _execute || AbnormalTermination()) \
{ \
(*(_cleanup.routine))( _cleanup.arg ); \
} \
} \
} }
}
#else /* __CLEANUP_SEH */ static int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts)
{
unsigned long long ct = _pthread_time_in_ms();
unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
#ifdef __CLEANUP_C pthread_testcancel();
/* /* Use a busy-loop */
* C implementation of PThreads cancel cleanup while (1)
*/ {
/* Try to grab lock */
if (!pthread_rwlock_trywrlock(l)) return 0;
#define pthread_cleanup_push( _rout, _arg ) \ /* Get current time */
{ \ ct = _pthread_time_in_ms();
ptw32_cleanup_t _cleanup; \
\
ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \
#define pthread_cleanup_pop( _execute ) \ /* Have we waited long enough? */
(void) ptw32_pop_cleanup( _execute ); \ if (ct > t) return ETIMEDOUT;
} }
}
#else /* __CLEANUP_C */ static int pthread_get_concurrency(int *val)
{
*val = _pthread_concur;
return 0;
}
#ifdef __CLEANUP_CXX static int pthread_set_concurrency(int val)
{
_pthread_concur = val;
return 0;
}
/* #define pthread_getschedparam(T, P, S) ENOTSUP
* C++ version of cancel cleanup. #define pthread_setschedparam(T, P, S) ENOTSUP
* - John E. Bossom. #define pthread_getcpuclockid(T, C) ENOTSUP
*/
class PThreadCleanup { static int pthread_exit(void *res)
/* {
* PThreadCleanup pthread_t t = pthread_self();
*
* 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( t->ret_arg = res;
ptw32_cleanup_callback_t routine,
void * arg ) : _pthread_cleanup_dest(t);
cleanUpRout( routine ),
obj( arg ), longjmp(t->jb, 1);
executeIt( 1 ) }
/*
* Registers a cleanup routine for 'arg'
*/ static void _pthread_invoke_cancel(void)
{
_pthread_cleanup *pcup;
_InterlockedDecrement(&_pthread_cancelling);
/* Call cancel queue */
for (pcup = pthread_self()->clean; pcup; pcup = pcup->next)
{ {
pcup->func(pcup->arg);
} }
~PThreadCleanup() pthread_exit(PTHREAD_CANCELED);
}
static void pthread_testcancel(void)
{
if (_pthread_cancelling)
{ {
if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) pthread_t t = pthread_self();
if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
{ {
(void) (*cleanUpRout)( obj ); _pthread_invoke_cancel();
} }
} }
}
void execute( int exec )
static int pthread_cancel(pthread_t t)
{
if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS)
{ {
executeIt = exec; /* Dangerous asynchronous cancelling */
} CONTEXT ctxt;
};
/* /* Already done? */
* C++ implementation of PThreads cancel cleanup; if (t->cancelled) return ESRCH;
* 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 ) \ ctxt.ContextFlags = CONTEXT_CONTROL;
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)
{
*a &= (PTHREAD_PRIO_MULT - 1);
*a += prio * PTHREAD_PRIO_MULT;
PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); return 0;
}
/* static int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts)
* Read-Write Lock Functions {
*/ unsigned long long t, ct;
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); struct _pthread_crit_t
{
void *debug;
LONG count;
LONG r_count;
HANDLE owner;
HANDLE sem;
ULONG_PTR spin;
};
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); /* Try to lock it without waiting */
if (!pthread_mutex_trylock(m)) return 0;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); ct = _pthread_time_in_ms();
t = _pthread_time_in_ms_from_timespec(ts);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); while (1)
{
/* Have we waited long enough? */
if (ct > t) return ETIMEDOUT;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, /* Wait on semaphore within critical section */
const struct timespec *abstime); WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, t - ct);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); /* Try to grab lock */
if (!pthread_mutex_trylock(m)) return 0;
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, /* Get current time */
const struct timespec *abstime); ct = _pthread_time_in_ms();
}
}
PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); #define _PTHREAD_BARRIER_FLAG (1<<30)
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); static int pthread_barrier_destroy(pthread_barrier_t *b)
{
EnterCriticalSection(&b->m);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); while (b->total > _PTHREAD_BARRIER_FLAG)
{
/* Wait until everyone exits the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, LeaveCriticalSection(&b->m);
int *pshared);
PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, DeleteCriticalSection(&b->m);
int pshared);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 return 0;
}
/* static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count)
* Signal Functions. Should be defined in <signal.h> but MSVC and MinGW32 {
* already have signal.h that don't define these. /* Ignore attr */
*/ (void) attr;
PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig);
/* b->count = count;
* Non-portable functions b->total = 0;
*/
/* InitializeCriticalSection(&b->m);
* Compatibility with Linux. InitializeConditionVariable(&b->cv);
*/
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);
/* return 0;
* Possibly supported by other POSIX threads implementations }
*/
PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval);
PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void);
/* static int pthread_barrier_wait(pthread_barrier_t *b)
* Useful if an application wants to statically link {
* the lib rather than load the DLL at run-time. EnterCriticalSection(&b->m);
*/
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);
/* while (b->total > _PTHREAD_BARRIER_FLAG)
* Features that are auto-detected at load/run time. {
*/ /* Wait until everyone exits the barrier */
PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
enum ptw32_features { }
PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */
PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */
};
/* /* Are we the first to enter? */
* Register a system time change with the library. if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0;
* Causes the library to perform various functions
* in response to the change. Should be called whenever
* the application's top level window receives a
* WM_TIMECHANGE message. It can be passed directly to
* pthread_create() as a new thread if desired.
*/
PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *);
#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ b->total++;
#if PTW32_LEVEL >= PTW32_LEVEL_MAX if (b->total == b->count)
{
b->total += _PTHREAD_BARRIER_FLAG - 1;
WakeAllConditionVariable(&b->cv);
/* LeaveCriticalSection(&b->m);
* Returns the Win32 HANDLE for the POSIX thread.
*/
PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread);
return 1;
}
else
{
while (b->total < _PTHREAD_BARRIER_FLAG)
{
/* Wait until enough threads enter the barrier */
SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
}
/* b->total--;
* Protected Methods
*
* This function blocks until the given WIN32 handle
* is signaled or pthread_cancel had been called.
* This function allows the caller to hook into the
* PThreads cancel mechanism. It is implemented using
*
* WaitForMultipleObjects
*
* on 'waitHandle' and a manually reset WIN32 Event
* used to implement pthread_cancel. The 'timeout'
* argument to TimedWait is simply passed to
* WaitForMultipleObjects.
*/
PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle);
PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle,
DWORD timeout);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ /* Get entering threads to wake up */
if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
/* LeaveCriticalSection(&b->m);
* Thread-Safe C Runtime Library Mappings.
*/
#ifndef _UWIN
# if defined(NEED_ERRNO)
PTW32_DLLPORT int * PTW32_CDECL _errno( void );
# else
# ifndef errno
# if (defined(_MT) || defined(_DLL))
__declspec(dllimport) extern int * __cdecl _errno(void);
# define errno (*_errno())
# endif
# endif
# endif
#endif
/* return 0;
* 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__) static int pthread_barrierattr_init(void **attr)
#define strtok_r( _s, _sep, _lasts ) \ {
( *(_lasts) = strtok( (_s), (_sep) ) ) *attr = NULL;
#endif /* !__MINGW32__ */ return 0;
}
#define asctime_r( _tm, _buf ) \ static int pthread_barrierattr_destroy(void **attr)
( strcpy( (_buf), asctime( (_tm) ) ), \ {
(_buf) ) /* Ignore attr */
(void) attr;
#define ctime_r( _clock, _buf ) \ return 0;
( strcpy( (_buf), ctime( (_clock) ) ), \ }
(_buf) )
#define gmtime_r( _clock, _result ) \ static int pthread_barrierattr_setpshared(void **attr, int s)
( *(_result) = *gmtime( (_clock) ), \ {
(_result) ) *attr = (void *) s;
return 0;
}
#define localtime_r( _clock, _result ) \ static int pthread_barrierattr_getpshared(void **attr, int *s)
( *(_result) = *localtime( (_clock) ), \ {
(_result) ) *s = (int) (size_t) *attr;
#define rand_r( _seed ) \ return 0;
( _seed == _seed? rand() : rand() ) }
static int pthread_key_create(pthread_key_t *key, void (* dest)(void *))
{
int i;
long nmax;
void (**d)(void *);
/* if (!key) return EINVAL;
* Some compiler environments don't define some things.
*/
#if defined(__BORLANDC__)
# define _ftime ftime
# define _timeb timeb
#endif
#ifdef __cplusplus pthread_rwlock_wrlock(&_pthread_key_lock);
/* for (i = _pthread_key_sch; i < _pthread_key_max; i++)
* Internal exceptions {
*/ if (!_pthread_key_dest[i])
class ptw32_exception {}; {
class ptw32_exception_cancel : public ptw32_exception {}; *key = i;
class ptw32_exception_exit : public ptw32_exception {}; 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);
#if PTW32_LEVEL >= PTW32_LEVEL_MAX return ENOMEM;
}
/* FIXME: This is only required if the library was built using SEH */ /* Clear new region */
/* memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
* Get internal SEH tag
*/
PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void);
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ /* Use new region */
_pthread_key_dest = d;
_pthread_key_sch = _pthread_key_max + 1;
*key = _pthread_key_max;
_pthread_key_max = nmax;
#ifndef PTW32_BUILD if (dest)
{
_pthread_key_dest[*key] = dest;
}
else
{
_pthread_key_dest[*key] = (void(*)(void *))1;
}
#ifdef __CLEANUP_SEH pthread_rwlock_unlock(&_pthread_key_lock);
/* return 0;
* Redefine the SEH __except keyword to ensure that applications }
* propagate our internal exceptions up to the library's internal handlers.
*/
#define __except( E ) \
__except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \
? EXCEPTION_CONTINUE_SEARCH : ( E ) )
#endif /* __CLEANUP_SEH */ static int pthread_key_delete(pthread_key_t key)
{
if (key > _pthread_key_max) return EINVAL;
if (!_pthread_key_dest) return EINVAL;
#ifdef __CLEANUP_CXX pthread_rwlock_wrlock(&_pthread_key_lock);
_pthread_key_dest[key] = NULL;
/* /* Start next search from our location */
* Redefine the C++ catch 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.
*/
#ifdef _MSC_VER
/*
* WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll'
* if you want Pthread-Win32 cancelation and pthread_exit to work.
*/
#ifndef PtW32NoCatchWarn pthread_rwlock_unlock(&_pthread_key_lock);
#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 return 0;
}
#define PtW32CatchAll \ static void *pthread_getspecific(pthread_key_t key)
catch( ptw32_exception & ) { throw; } \ {
catch( ... ) pthread_t t = pthread_self();
#else /* _MSC_VER */ if (key >= t->keymax) return NULL;
#define catch( E ) \ return t->keyval[key];
catch( ptw32_exception & ) { throw; } \
catch( E )
#endif /* _MSC_VER */ }
#endif /* __CLEANUP_CXX */ static int pthread_setspecific(pthread_key_t key, const void *value)
{
pthread_t t = pthread_self();
#endif /* ! PTW32_BUILD */ if (key > t->keymax)
{
int keymax = (key + 1) * 2;
void **kv = (void**) realloc(t->keyval, keymax * sizeof(void *));
#ifdef __cplusplus if (!kv) return ENOMEM;
} /* End of extern "C" */
#endif /* __cplusplus */
#ifdef PTW32__HANDLE_DEF /* Clear new region */
# undef HANDLE memset(&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void*));
#endif
#ifdef PTW32__DWORD_DEF t->keyval = kv;
# undef DWORD t->keymax = keymax;
#endif }
t->keyval[key] = (void *) value;
return 0;
}
static int pthread_spin_init(pthread_spinlock_t *l, int pshared)
{
(void) pshared;
*l = 0;
return 0;
}
static int pthread_spin_destroy(pthread_spinlock_t *l)
{
(void) l;
return 0;
}
/* No-fair spinlock due to lack of knowledge of thread number */
static int pthread_spin_lock(pthread_spinlock_t *l)
{
while (_InterlockedExchange(l, EBUSY))
{
/* Don't lock the bus whilst waiting */
while (*l)
{
YieldProcessor();
/* Compiler barrier. Prevent caching of *l */
_ReadWriteBarrier();
}
}
return 0;
}
static int pthread_spin_trylock(pthread_spinlock_t *l)
{
return _InterlockedExchange(l, EBUSY);
}
static int pthread_spin_unlock(pthread_spinlock_t *l)
{
/* Compiler barrier. The store below acts with release symmantics */
_ReadWriteBarrier();
*l = 0;
return 0;
}
static int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a)
{
(void) a;
InitializeConditionVariable(c);
return 0;
}
static int pthread_cond_signal(pthread_cond_t *c)
{
WakeConditionVariable(c);
return 0;
}
static int pthread_cond_broadcast(pthread_cond_t *c)
{
WakeAllConditionVariable(c);
return 0;
}
static int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
{
pthread_testcancel();
SleepConditionVariableCS(c, m, INFINITE);
return 0;
}
static int pthread_cond_destroy(pthread_cond_t *c)
{
(void) c;
return 0;
}
static int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t)
{
unsigned long long tm = _pthread_rel_time_in_ms(t);
pthread_testcancel();
#undef PTW32_LEVEL if (!SleepConditionVariableCS(c, m, tm)) return ETIMEDOUT;
#undef PTW32_LEVEL_MAX
#endif /* ! RC_INVOKED */ /* We can have a spurious wakeup after the timeout */
if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT;
return 0;
}
static int pthread_condattr_destroy(pthread_condattr_t *a)
{
(void) a;
return 0;
}
#define pthread_condattr_getclock(A, C) ENOTSUP
#define pthread_condattr_setclock(A, C) ENOTSUP
static int pthread_condattr_init(pthread_condattr_t *a)
{
*a = 0;
return 0;
}
static int pthread_condattr_getpshared(pthread_condattr_t *a, int *s)
{
*s = *a;
return 0;
}
#endif /* PTHREAD_H */ static int pthread_condattr_setpshared(pthread_condattr_t *a, int s)
{
*a = s;
return 0;
}
static int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
{
(void) a;
return 0;
}
static int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
{
*a = 0;
}
static int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s)
{
*s = *a;
return 0;
}
static int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s)
{
*a = s;
return 0;
}
/* No fork() in windows - so ignore this */
#define pthread_atfork(F1,F2,F3) 0
/* Windows has rudimentary signals support */
#define pthread_kill(T, S) 0
#define pthread_sigmask(H, S1, S2) 0
/* Wrap cancellation points */
/*
#define accept(...) (pthread_testcancel(), accept(__VA_ARGS__))
#define aio_suspend(...) (pthread_testcancel(), aio_suspend(__VA_ARGS__))
#define clock_nanosleep(...) (pthread_testcancel(), clock_nanosleep(__VA_ARGS__))
#define close(...) (pthread_testcancel(), close(__VA_ARGS__))
#define connect(...) (pthread_testcancel(), connect(__VA_ARGS__))
#define creat(...) (pthread_testcancel(), creat(__VA_ARGS__))
#define fcntl(...) (pthread_testcancel(), fcntl(__VA_ARGS__))
#define fdatasync(...) (pthread_testcancel(), fdatasync(__VA_ARGS__))
#define fsync(...) (pthread_testcancel(), fsync(__VA_ARGS__))
#define getmsg(...) (pthread_testcancel(), getmsg(__VA_ARGS__))
#define getpmsg(...) (pthread_testcancel(), getpmsg(__VA_ARGS__))
#define lockf(...) (pthread_testcancel(), lockf(__VA_ARGS__))
#define mg_receive(...) (pthread_testcancel(), mg_receive(__VA_ARGS__))
#define mg_send(...) (pthread_testcancel(), mg_send(__VA_ARGS__))
#define mg_timedreceive(...) (pthread_testcancel(), mg_timedreceive(__VA_ARGS__))
#define mg_timessend(...) (pthread_testcancel(), mg_timedsend(__VA_ARGS__))
#define msgrcv(...) (pthread_testcancel(), msgrecv(__VA_ARGS__))
#define msgsnd(...) (pthread_testcancel(), msgsnd(__VA_ARGS__))
#define msync(...) (pthread_testcancel(), msync(__VA_ARGS__))
#define nanosleep(...) (pthread_testcancel(), nanosleep(__VA_ARGS__))
#define open(...) (pthread_testcancel(), open(__VA_ARGS__))
#define pause(...) (pthread_testcancel(), pause(__VA_ARGS__))
#define poll(...) (pthread_testcancel(), poll(__VA_ARGS__))
#define pread(...) (pthread_testcancel(), pread(__VA_ARGS__))
#define pselect(...) (pthread_testcancel(), pselect(__VA_ARGS__))
#define putmsg(...) (pthread_testcancel(), putmsg(__VA_ARGS__))
#define putpmsg(...) (pthread_testcancel(), putpmsg(__VA_ARGS__))
#define pwrite(...) (pthread_testcancel(), pwrite(__VA_ARGS__))
#define read(...) (pthread_testcancel(), read(__VA_ARGS__))
#define readv(...) (pthread_testcancel(), readv(__VA_ARGS__))
#define recv(...) (pthread_testcancel(), recv(__VA_ARGS__))
#define recvfrom(...) (pthread_testcancel(), recvfrom(__VA_ARGS__))
#define recvmsg(...) (pthread_testcancel(), recvmsg(__VA_ARGS__))
#define select(...) (pthread_testcancel(), select(__VA_ARGS__))
#define sem_timedwait(...) (pthread_testcancel(), sem_timedwait(__VA_ARGS__))
#define sem_wait(...) (pthread_testcancel(), sem_wait(__VA_ARGS__))
#define send(...) (pthread_testcancel(), send(__VA_ARGS__))
#define sendmsg(...) (pthread_testcancel(), sendmsg(__VA_ARGS__))
#define sendto(...) (pthread_testcancel(), sendto(__VA_ARGS__))
#define sigpause(...) (pthread_testcancel(), sigpause(__VA_ARGS__))
#define sigsuspend(...) (pthread_testcancel(), sigsuspend(__VA_ARGS__))
#define sigwait(...) (pthread_testcancel(), sigwait(__VA_ARGS__))
#define sigwaitinfo(...) (pthread_testcancel(), sigwaitinfo(__VA_ARGS__))
#define sleep(...) (pthread_testcancel(), sleep(__VA_ARGS__))
//#define Sleep(...) (pthread_testcancel(), Sleep(__VA_ARGS__))
#define system(...) (pthread_testcancel(), system(__VA_ARGS__))
#define access(...) (pthread_testcancel(), access(__VA_ARGS__))
#define asctime(...) (pthread_testcancel(), asctime(__VA_ARGS__))
#define asctime_r(...) (pthread_testcancel(), asctime_r(__VA_ARGS__))
#define catclose(...) (pthread_testcancel(), catclose(__VA_ARGS__))
#define catgets(...) (pthread_testcancel(), catgets(__VA_ARGS__))
#define catopen(...) (pthread_testcancel(), catopen(__VA_ARGS__))
#define closedir(...) (pthread_testcancel(), closedir(__VA_ARGS__))
#define closelog(...) (pthread_testcancel(), closelog(__VA_ARGS__))
#define ctermid(...) (pthread_testcancel(), ctermid(__VA_ARGS__))
#define ctime(...) (pthread_testcancel(), ctime(__VA_ARGS__))
#define ctime_r(...) (pthread_testcancel(), ctime_r(__VA_ARGS__))
#define dbm_close(...) (pthread_testcancel(), dbm_close(__VA_ARGS__))
#define dbm_delete(...) (pthread_testcancel(), dbm_delete(__VA_ARGS__))
#define dbm_fetch(...) (pthread_testcancel(), dbm_fetch(__VA_ARGS__))
#define dbm_nextkey(...) (pthread_testcancel(), dbm_nextkey(__VA_ARGS__))
#define dbm_open(...) (pthread_testcancel(), dbm_open(__VA_ARGS__))
#define dbm_store(...) (pthread_testcancel(), dbm_store(__VA_ARGS__))
#define dlclose(...) (pthread_testcancel(), dlclose(__VA_ARGS__))
#define dlopen(...) (pthread_testcancel(), dlopen(__VA_ARGS__))
#define endgrent(...) (pthread_testcancel(), endgrent(__VA_ARGS__))
#define endhostent(...) (pthread_testcancel(), endhostent(__VA_ARGS__))
#define endnetent(...) (pthread_testcancel(), endnetent(__VA_ARGS__))
#define endprotoent(...) (pthread_testcancel(), endprotoend(__VA_ARGS__))
#define endpwent(...) (pthread_testcancel(), endpwent(__VA_ARGS__))
#define endservent(...) (pthread_testcancel(), endservent(__VA_ARGS__))
#define endutxent(...) (pthread_testcancel(), endutxent(__VA_ARGS__))
#define fclose(...) (pthread_testcancel(), fclose(__VA_ARGS__))
#define fflush(...) (pthread_testcancel(), fflush(__VA_ARGS__))
#define fgetc(...) (pthread_testcancel(), fgetc(__VA_ARGS__))
#define fgetpos(...) (pthread_testcancel(), fgetpos(__VA_ARGS__))
#define fgets(...) (pthread_testcancel(), fgets(__VA_ARGS__))
#define fgetwc(...) (pthread_testcancel(), fgetwc(__VA_ARGS__))
#define fgetws(...) (pthread_testcancel(), fgetws(__VA_ARGS__))
#define fmtmsg(...) (pthread_testcancel(), fmtmsg(__VA_ARGS__))
#define fopen(...) (pthread_testcancel(), fopen(__VA_ARGS__))
#define fpathconf(...) (pthread_testcancel(), fpathconf(__VA_ARGS__))
#define fprintf(...) (pthread_testcancel(), fprintf(__VA_ARGS__))
#define fputc(...) (pthread_testcancel(), fputc(__VA_ARGS__))
#define fputs(...) (pthread_testcancel(), fputs(__VA_ARGS__))
#define fputwc(...) (pthread_testcancel(), fputwc(__VA_ARGS__))
#define fputws(...) (pthread_testcancel(), fputws(__VA_ARGS__))
#define fread(...) (pthread_testcancel(), fread(__VA_ARGS__))
#define freopen(...) (pthread_testcancel(), freopen(__VA_ARGS__))
#define fscanf(...) (pthread_testcancel(), fscanf(__VA_ARGS__))
#define fseek(...) (pthread_testcancel(), fseek(__VA_ARGS__))
#define fseeko(...) (pthread_testcancel(), fseeko(__VA_ARGS__))
#define fsetpos(...) (pthread_testcancel(), fsetpos(__VA_ARGS__))
#define fstat(...) (pthread_testcancel(), fstat(__VA_ARGS__))
#define ftell(...) (pthread_testcancel(), ftell(__VA_ARGS__))
#define ftello(...) (pthread_testcancel(), ftello(__VA_ARGS__))
#define ftw(...) (pthread_testcancel(), ftw(__VA_ARGS__))
#define fwprintf(...) (pthread_testcancel(), fwprintf(__VA_ARGS__))
#define fwrite(...) (pthread_testcancel(), fwrite(__VA_ARGS__))
#define fwscanf(...) (pthread_testcancel(), fwscanf(__VA_ARGS__))
#define getaddrinfo(...) (pthread_testcancel(), getaddrinfo(__VA_ARGS__))
#define getc(...) (pthread_testcancel(), getc(__VA_ARGS__))
#define getc_unlocked(...) (pthread_testcancel(), getc_unlocked(__VA_ARGS__))
#define getchar(...) (pthread_testcancel(), getchar(__VA_ARGS__))
#define getchar_unlocked(...) (pthread_testcancel(), getchar_unlocked(__VA_ARGS__))
#define getcwd(...) (pthread_testcancel(), getcwd(__VA_ARGS__))
#define getdate(...) (pthread_testcancel(), getdate(__VA_ARGS__))
#define getgrent(...) (pthread_testcancel(), getgrent(__VA_ARGS__))
#define getgrgid(...) (pthread_testcancel(), getgrgid(__VA_ARGS__))
#define getgrgid_r(...) (pthread_testcancel(), getgrgid_r(__VA_ARGS__))
#define gergrnam(...) (pthread_testcancel(), getgrnam(__VA_ARGS__))
#define getgrnam_r(...) (pthread_testcancel(), getgrnam_r(__VA_ARGS__))
#define gethostbyaddr(...) (pthread_testcancel(), gethostbyaddr(__VA_ARGS__))
#define gethostbyname(...) (pthread_testcancel(), gethostbyname(__VA_ARGS__))
#define gethostent(...) (pthread_testcancel(), gethostent(__VA_ARGS__))
#define gethostid(...) (pthread_testcancel(), gethostid(__VA_ARGS__))
#define gethostname(...) (pthread_testcancel(), gethostname(__VA_ARGS__))
#define getlogin(...) (pthread_testcancel(), getlogin(__VA_ARGS__))
#define getlogin_r(...) (pthread_testcancel(), getlogin_r(__VA_ARGS__))
#define getnameinfo(...) (pthread_testcancel(), getnameinfo(__VA_ARGS__))
#define getnetbyaddr(...) (pthread_testcancel(), getnetbyaddr(__VA_ARGS__))
#define getnetbyname(...) (pthread_testcancel(), getnetbyname(__VA_ARGS__))
#define getnetent(...) (pthread_testcancel(), getnetent(__VA_ARGS__))
#define getopt(...) (pthread_testcancel(), getopt(__VA_ARGS__))
#define getprotobyname(...) (pthread_testcancel(), getprotobyname(__VA_ARGS__))
#define getprotobynumber(...) (pthread_testcancel(), getprotobynumber(__VA_ARGS__))
#define getprotoent(...) (pthread_testcancel(), getprotoent(__VA_ARGS__))
#define getpwent(...) (pthread_testcancel(), getpwent(__VA_ARGS__))
#define getpwnam(...) (pthread_testcancel(), getpwnam(__VA_ARGS__))
#define getpwnam_r(...) (pthread_testcancel(), getpwnam_r(__VA_ARGS__))
#define getpwuid(...) (pthread_testcancel(), getpwuid(__VA_ARGS__))
#define getpwuid_r(...) (pthread_testcancel(), getpwuid_r(__VA_ARGS__))
#define gets(...) (pthread_testcancel(), gets(__VA_ARGS__))
#define getservbyname(...) (pthread_testcancel(), getservbyname(__VA_ARGS__))
#define getservbyport(...) (pthread_testcancel(), getservbyport(__VA_ARGS__))
#define getservent(...) (pthread_testcancel(), getservent(__VA_ARGS__))
#define getutxent(...) (pthread_testcancel(), getutxent(__VA_ARGS__))
#define getutxid(...) (pthread_testcancel(), getutxid(__VA_ARGS__))
#define getutxline(...) (pthread_testcancel(), getutxline(__VA_ARGS__))
#undef getwc
#define getwc(...) (pthread_testcancel(), getwc(__VA_ARGS__))
#undef getwchar
#define getwchar(...) (pthread_testcancel(), getwchar(__VA_ARGS__))
#define getwd(...) (pthread_testcancel(), getwd(__VA_ARGS__))
#define glob(...) (pthread_testcancel(), glob(__VA_ARGS__))
#define iconv_close(...) (pthread_testcancel(), iconv_close(__VA_ARGS__))
#define iconv_open(...) (pthread_testcancel(), iconv_open(__VA_ARGS__))
#define ioctl(...) (pthread_testcancel(), ioctl(__VA_ARGS__))
#define link(...) (pthread_testcancel(), link(__VA_ARGS__))
#define localtime(...) (pthread_testcancel(), localtime(__VA_ARGS__))
#define localtime_r(...) (pthread_testcancel(), localtime_r(__VA_ARGS__))
#define lseek(...) (pthread_testcancel(), lseek(__VA_ARGS__))
#define lstat(...) (pthread_testcancel(), lstat(__VA_ARGS__))
#define mkstemp(...) (pthread_testcancel(), mkstemp(__VA_ARGS__))
#define nftw(...) (pthread_testcancel(), nftw(__VA_ARGS__))
#define opendir(...) (pthread_testcancel(), opendir(__VA_ARGS__))
#define openlog(...) (pthread_testcancel(), openlog(__VA_ARGS__))
#define pathconf(...) (pthread_testcancel(), pathconf(__VA_ARGS__))
#define pclose(...) (pthread_testcancel(), pclose(__VA_ARGS__))
#define perror(...) (pthread_testcancel(), perror(__VA_ARGS__))
#define popen(...) (pthread_testcancel(), popen(__VA_ARGS__))
#define posix_fadvise(...) (pthread_testcancel(), posix_fadvise(__VA_ARGS__))
#define posix_fallocate(...) (pthread_testcancel(), posix_fallocate(__VA_ARGS__))
#define posix_madvise(...) (pthread_testcancel(), posix_madvise(__VA_ARGS__))
#define posix_openpt(...) (pthread_testcancel(), posix_openpt(__VA_ARGS__))
#define posix_spawn(...) (pthread_testcancel(), posix_spawn(__VA_ARGS__))
#define posix_spawnp(...) (pthread_testcancel(), posix_spawnp(__VA_ARGS__))
#define posix_trace_clear(...) (pthread_testcancel(), posix_trace_clear(__VA_ARGS__))
#define posix_trace_close(...) (pthread_testcancel(), posix_trace_close(__VA_ARGS__))
#define posix_trace_create(...) (pthread_testcancel(), posix_trace_create(__VA_ARGS__))
#define posix_trace_create_withlog(...) (pthread_testcancel(), posix_trace_create_withlog(__VA_ARGS__))
#define posix_trace_eventtypelist_getne(...) (pthread_testcancel(), posix_trace_eventtypelist_getne(__VA_ARGS__))
#define posix_trace_eventtypelist_rewin(...) (pthread_testcancel(), posix_trace_eventtypelist_rewin(__VA_ARGS__))
#define posix_trace_flush(...) (pthread_testcancel(), posix_trace_flush(__VA_ARGS__))
#define posix_trace_get_attr(...) (pthread_testcancel(), posix_trace_get_attr(__VA_ARGS__))
#define posix_trace_get_filter(...) (pthread_testcancel(), posix_trace_get_filter(__VA_ARGS__))
#define posix_trace_get_status(...) (pthread_testcancel(), posix_trace_get_status(__VA_ARGS__))
#define posix_trace_getnext_event(...) (pthread_testcancel(), posix_trace_getnext_event(__VA_ARGS__))
#define posix_trace_open(...) (pthread_testcancel(), posix_trace_open(__VA_ARGS__))
#define posix_trace_rewind(...) (pthread_testcancel(), posix_trace_rewind(__VA_ARGS__))
#define posix_trace_setfilter(...) (pthread_testcancel(), posix_trace_setfilter(__VA_ARGS__))
#define posix_trace_shutdown(...) (pthread_testcancel(), posix_trace_shutdown(__VA_ARGS__))
#define posix_trace_timedgetnext_event(...) (pthread_testcancel(), posix_trace_timedgetnext_event(__VA_ARGS__))
#define posix_typed_mem_open(...) (pthread_testcancel(), posix_typed_mem_open(__VA_ARGS__))
#define printf(...) (pthread_testcancel(), printf(__VA_ARGS__))
#define putc(...) (pthread_testcancel(), putc(__VA_ARGS__))
#define putc_unlocked(...) (pthread_testcancel(), putc_unlocked(__VA_ARGS__))
#define putchar(...) (pthread_testcancel(), putchar(__VA_ARGS__))
#define putchar_unlocked(...) (pthread_testcancel(), putchar_unlocked(__VA_ARGS__))
#define puts(...) (pthread_testcancel(), puts(__VA_ARGS__))
#define pututxline(...) (pthread_testcancel(), pututxline(__VA_ARGS__))
#undef putwc
#define putwc(...) (pthread_testcancel(), putwc(__VA_ARGS__))
#undef putwchar
#define putwchar(...) (pthread_testcancel(), putwchar(__VA_ARGS__))
#define readdir(...) (pthread_testcancel(), readdir(__VA_ARSG__))
#define readdir_r(...) (pthread_testcancel(), readdir_r(__VA_ARGS__))
#define remove(...) (pthread_testcancel(), remove(__VA_ARGS__))
#define rename(...) (pthread_testcancel(), rename(__VA_ARGS__))
#define rewind(...) (pthread_testcancel(), rewind(__VA_ARGS__))
#define rewinddir(...) (pthread_testcancel(), rewinddir(__VA_ARGS__))
#define scanf(...) (pthread_testcancel(), scanf(__VA_ARGS__))
#define seekdir(...) (pthread_testcancel(), seekdir(__VA_ARGS__))
#define semop(...) (pthread_testcancel(), semop(__VA_ARGS__))
#define setgrent(...) (pthread_testcancel(), setgrent(__VA_ARGS__))
#define sethostent(...) (pthread_testcancel(), sethostemt(__VA_ARGS__))
#define setnetent(...) (pthread_testcancel(), setnetent(__VA_ARGS__))
#define setprotoent(...) (pthread_testcancel(), setprotoent(__VA_ARGS__))
#define setpwent(...) (pthread_testcancel(), setpwent(__VA_ARGS__))
#define setservent(...) (pthread_testcancel(), setservent(__VA_ARGS__))
#define setutxent(...) (pthread_testcancel(), setutxent(__VA_ARGS__))
#define stat(...) (pthread_testcancel(), stat(__VA_ARGS__))
#define strerror(...) (pthread_testcancel(), strerror(__VA_ARGS__))
#define strerror_r(...) (pthread_testcancel(), strerror_r(__VA_ARGS__))
#define strftime(...) (pthread_testcancel(), strftime(__VA_ARGS__))
#define symlink(...) (pthread_testcancel(), symlink(__VA_ARGS__))
#define sync(...) (pthread_testcancel(), sync(__VA_ARGS__))
#define syslog(...) (pthread_testcancel(), syslog(__VA_ARGS__))
#define tmpfile(...) (pthread_testcancel(), tmpfile(__VA_ARGS__))
#define tmpnam(...) (pthread_testcancel(), tmpnam(__VA_ARGS__))
#define ttyname(...) (pthread_testcancel(), ttyname(__VA_ARGS__))
#define ttyname_r(...) (pthread_testcancel(), ttyname_r(__VA_ARGS__))
#define tzset(...) (pthread_testcancel(), tzset(__VA_ARGS__))
#define ungetc(...) (pthread_testcancel(), ungetc(__VA_ARGS__))
#define ungetwc(...) (pthread_testcancel(), ungetwc(__VA_ARGS__))
#define unlink(...) (pthread_testcancel(), unlink(__VA_ARGS__))
#define vfprintf(...) (pthread_testcancel(), vfprintf(__VA_ARGS__))
#define vfwprintf(...) (pthread_testcancel(), vfwprintf(__VA_ARGS__))
#define vprintf(...) (pthread_testcancel(), vprintf(__VA_ARGS__))
#define vwprintf(...) (pthread_testcancel(), vwprintf(__VA_ARGS__))
#define wcsftime(...) (pthread_testcancel(), wcsftime(__VA_ARGS__))
#define wordexp(...) (pthread_testcancel(), wordexp(__VA_ARGS__))
#define wprintf(...) (pthread_testcancel(), wprintf(__VA_ARGS__))
#define wscanf(...) (pthread_testcancel(), wscanf(__VA_ARGS__))
*/
#endif /* WIN_PTHREADS */
/*
* Module: sched.h
*
* Purpose:
* Provides an implementation of POSIX realtime extensions
* as defined in
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifndef _SCHED_H
#define _SCHED_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#if defined(__MINGW32__) || defined(_UWIN)
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
/* For pid_t */
# include <sys/types.h>
/* Required by Unix 98 */
# include <time.h>
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#else
typedef int pid_t;
#endif
/* Thread scheduling policies */
enum {
SCHED_OTHER = 0,
SCHED_FIFO,
SCHED_RR,
SCHED_MIN = SCHED_OTHER,
SCHED_MAX = SCHED_RR
};
struct sched_param {
int sched_priority;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
PTW32_DLLPORT int __cdecl sched_yield (void);
PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy);
PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy);
PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy);
PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid);
/*
* Note that this macro returns ENOTSUP rather than
* ENOSYS as might be expected. However, returning ENOSYS
* should mean that sched_get_priority_{min,max} are
* not implemented as well as sched_rr_get_interval.
* This is not the case, since we just don't support
* round-robin scheduling. Therefore I have chosen to
* return the same value as sched_setscheduler when
* SCHED_RR is passed to it.
*/
#define sched_rr_get_interval(_pid, _interval) \
( errno = ENOTSUP, (int) -1 )
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !_SCHED_H */
/*
* Module: semaphore.h
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
* They are defined by the POSIX Standard:
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* --------------------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2005 Pthreads-win32 contributors
*
* Contact Email: rpj@callisto.canberra.edu.au
*
* The current list of contributors is contained
* in the file CONTRIBUTORS included with the source
* code distribution. The list can also be seen at the
* following World Wide Web location:
* http://sources.redhat.com/pthreads-win32/contributors.html
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined( SEMAPHORE_H )
#define SEMAPHORE_H
#undef PTW32_LEVEL
#if defined(_POSIX_SOURCE)
#define PTW32_LEVEL 0
/* Early POSIX */
#endif
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309
#undef PTW32_LEVEL
#define PTW32_LEVEL 1
/* Include 1b, 1c and 1d */
#endif
#if defined(INCLUDE_NP)
#undef PTW32_LEVEL
#define PTW32_LEVEL 2
/* Include Non-Portable extensions */
#endif
#define PTW32_LEVEL_MAX 3
#if !defined(PTW32_LEVEL)
#define PTW32_LEVEL PTW32_LEVEL_MAX
/* Include everything */
#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
#endif
/*
* When building the DLL code, you should define PTW32_BUILD so that
* the variables/functions are exported correctly. When using the DLL,
* do NOT define PTW32_BUILD, and then the variables/functions will
* be imported correctly.
*/
#ifndef PTW32_STATIC_LIB
# ifdef PTW32_BUILD
# define PTW32_DLLPORT __declspec (dllexport)
# else
# define PTW32_DLLPORT __declspec (dllimport)
# endif
#else
# define PTW32_DLLPORT
#endif
/*
* This is a duplicate of what is in the autoconf config.h,
* which is only used when building the pthread-win32 libraries.
*/
#ifndef PTW32_CONFIG_H
# if defined(WINCE)
# define NEED_ERRNO
# define NEED_SEM
# endif
# if defined(_UWIN) || defined(__MINGW32__)
# define HAVE_MODE_T
# endif
#endif
/*
*
*/
#if PTW32_LEVEL >= PTW32_LEVEL_MAX
#ifdef NEED_ERRNO
#include "need_errno.h"
#else
#include <errno.h>
#endif
#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */
#define _POSIX_SEMAPHORES
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
#ifndef HAVE_MODE_T
typedef unsigned int mode_t;
#endif
typedef struct sem_t_ * sem_t;
PTW32_DLLPORT int __cdecl sem_init (sem_t * sem,
int pshared,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem,
const struct timespec * abstime);
PTW32_DLLPORT int __cdecl sem_post (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem,
int count);
PTW32_DLLPORT int __cdecl sem_open (const char * name,
int oflag,
mode_t mode,
unsigned int value);
PTW32_DLLPORT int __cdecl sem_close (sem_t * sem);
PTW32_DLLPORT int __cdecl sem_unlink (const char * name);
PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem,
int * sval);
#ifdef __cplusplus
} /* End of extern "C" */
#endif /* __cplusplus */
#undef PTW32_LEVEL
#undef PTW32_LEVEL_MAX
#endif /* !SEMAPHORE_H */
#include "pthread.h"
PTHREAD_EXPORT volatile long _pthread_cancelling;
PTHREAD_EXPORT int _pthread_concur;
/* Will default to zero as needed */
PTHREAD_EXPORT pthread_once_t _pthread_tls_once;
PTHREAD_EXPORT DWORD _pthread_tls;
/* Note initializer is zero, so this works */
PTHREAD_EXPORT pthread_rwlock_t _pthread_key_lock;
PTHREAD_EXPORT long _pthread_key_max;
PTHREAD_EXPORT long _pthread_key_sch;
PTHREAD_EXPORT void (**_pthread_key_dest)(void *);
/* 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