From 75f8ad67d45d48b9cdde5a298083881790c76c73 Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 31 Jan 2002 06:56:03 +0000 Subject: 2002-01-27 Ross Johnson * mutex.c (pthread_mutex_timedlock): New function suggested by Alexander Terekhov. The logic required to implement this properly came from Alexander, with some collaboration with Thomas Pfaff. (pthread_mutex_unlock): Wrap the waiters check and sema post in a critical section to prevent a race with pthread_mutex_timedlock. (ptw32_timed_semwait): New function; returns a special result if the absolute timeout parameter represents a time already passed when called; used by pthread_mutex_timedwait(). Have deliberately not reused the name "ptw32_sem_timedwait" because they are not the same routine. * condvar.c (ptw32_cond_timedwait): Use the new sem_timedwait() instead of ptw32_sem_timedwait(), which now has a different function. See previous. * implement.h: Remove prototype for ptw32_sem_timedwait. See next. (pthread_mutex_t_): Add critical section element for access to lock_idx during mutex post-timeout processing. * semaphore.h (sem_timedwait): See next. * semaphore.c (sem_timedwait): See next. * private.c (ptw32_sem_timedwait): Move to semaphore.c and rename as sem_timedwait(). 2002-01-18 Ross Johnson * sync.c (pthread_join): Was getting the exit code from the calling thread rather than the joined thread if defined(__MINGW32__) && !defined(__MSVCRT__). 2002-01-15 Ross Johnson * pthread.h: Unless the build explicitly defines __CLEANUP_SEH, __CLEANUP_CXX, or __CLEANUP_C, then the build defaults to __CLEANUP_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. * spin.c (pthread_spin_init): Edit renamed function call. * nonportable.c (pthread_num_processors_np): New. (pthread_getprocessors_np): Renamed to ptw32_getprocessors and moved to private.c. * private.c (pthread_getprocessors): Moved here from nonportable.c. * pthread.def (pthread_getprocessors_np): Removed from export list. * rwlock.c (pthread_rwlockattr_init): New. (pthread_rwlockattr_destroy): New. (pthread_rwlockattr_getpshared): New. (pthread_rwlockattr_setpshared): New. --- pthread.h | 369 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 209 insertions(+), 160 deletions(-) (limited to 'pthread.h') diff --git a/pthread.h b/pthread.h index de97dc9..8ecb7d7 100644 --- a/pthread.h +++ b/pthread.h @@ -27,7 +27,7 @@ #ifdef _UWIN # define HAVE_STRUCT_TIMESPEC 1 -# define HAVE_SIGNAL_H 1 +# define HAVE_SIGNAL_H 1 # undef HAVE_CONFIG_H # pragma comment(lib, "pthread") #endif @@ -39,16 +39,20 @@ * Module: pthread.h * * Purpose: - * Provides an implementation of PThreads based upon the - * standard: + * Provides an implementation of PThreads based upon the + * standard: * - * POSIX 1003.1c-1995 (POSIX.1c) + * POSIX 1003.1c-1995 (POSIX.1c) * * Parts of the implementation also comply with the * Open Group Unix 98 specification 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 @@ -63,7 +67,7 @@ * in the ChangeLog file in the source code distribution * where their changes are noted in detail. * - * Contributors are listed in the MAINTAINERS file. + * Contributors are listed in the CONTRIBUTORS file. * * As usual, all bouquets go to the contributors, and all * brickbats go to the project maintainer. @@ -99,6 +103,24 @@ * ------------------------------------------------------------- */ +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +/* + * FIXME: The pthreadGCE.dll build gets linker unresolved errors + * on pthread_key_create() unless windows.h is included here. + * It appears to have something to do with an argument type mismatch. + * Looking at tsd.o with 'nm' shows this line: + * 00000000 T _pthread_key_create__FPP14pthread_key_t_PFPv_v + * instead of + * 00000000 T _pthread_key_create + */ +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + /* * ----------------- * autoconf switches @@ -109,8 +131,6 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ -#include - #ifndef NEED_FTIME #include #else /* NEED_FTIME */ @@ -142,11 +162,6 @@ struct timespec { #define SIG_SETMASK 2 #endif /* SIG_SETMASK */ -/* - * note: ETIMEDOUT is correctly defined in winsock.h - */ -#include - #ifdef NEED_ERRNO # include "need_errno.h" #else @@ -156,18 +171,31 @@ struct timespec { #include /* - * In case ETIMEDOUT hasn't been defined above somehow. + * Several systems don't define ENOTSUP. If not, we use + * the same value as Solaris. */ +#ifndef ENOTSUP +# define ENOTSUP 48 +#endif + #ifndef ETIMEDOUT # define ETIMEDOUT 10060 /* This is the value in winsock.h. */ #endif /* - * Several systems don't define ENOTSUP. If not, we use - * the same value as Solaris. + * To avoid including windows.h we define only those things that we + * actually need from it. I don't like the potential incompatibility that + * this creates with future versions of windows. */ -#ifndef ENOTSUP -# define ENOTSUP 48 +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define __HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define __DWORD_DEF +# define DWORD unsigned long +#endif #endif #ifdef __cplusplus @@ -182,104 +210,104 @@ extern "C" * =========================== * * _POSIX_THREADS (set) - * If set, you can use threads + * If set, you can use threads * * _POSIX_THREAD_ATTR_STACKSIZE (set) - * If set, you can control the size of a thread's - * stack - * pthread_attr_getstacksize - * pthread_attr_setstacksize + * If set, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize * * _POSIX_THREAD_ATTR_STACKADDR (not set) - * If set, 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 + * If set, 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 (set) - * If set, you can use realtime scheduling. - * Indicates the availability of: - * pthread_attr_getinheritsched - * pthread_attr_getschedparam - * pthread_attr_getschedpolicy - * pthread_attr_getscope - * pthread_attr_setinheritsched - * pthread_attr_setschedparam - * pthread_attr_setschedpolicy - * pthread_attr_setscope - * pthread_getschedparam - * pthread_setschedparam - * sched_get_priority_max - * sched_get_priority_min - * sched_rr_set_interval + * If set, you can use realtime scheduling. + * Indicates the availability of: + * pthread_attr_getinheritsched + * pthread_attr_getschedparam + * pthread_attr_getschedpolicy + * pthread_attr_getscope + * pthread_attr_setinheritsched + * pthread_attr_setschedparam + * pthread_attr_setschedpolicy + * pthread_attr_setscope + * pthread_getschedparam + * pthread_setschedparam + * sched_get_priority_max + * sched_get_priority_min + * sched_rr_set_interval * * _POSIX_THREAD_PRIO_INHERIT (not set) - * If set, you can create priority inheritance - * mutexes. - * pthread_mutexattr_getprotocol + - * pthread_mutexattr_setprotocol + + * If set, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + * * _POSIX_THREAD_PRIO_PROTECT (not set) - * If set, 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 + + * If set, 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 (not set) - * 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 + * 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 (set) - * If set you can use the special *_r library - * functions that provide thread-safe behaviour + * If set you can use the special *_r library + * functions that provide thread-safe behaviour * - * + These functions provide both 'inherit' and/or - * 'protect' protocol, based upon these macro - * settings. + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. * * POSIX 1003.1c-1995 Limits * =========================== * * PTHREAD_DESTRUCTOR_ITERATIONS - * Maximum number of attempts to destroy - * a thread's thread-specific data on - * termination (must be at least 4) + * 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) + * 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 + * Minimum supported stack size for a thread * * PTHREAD_THREADS_MAX - * Maximum number of threads supported per - * process (must be at least 64). + * Maximum number of threads supported per + * process (must be at least 64). * * * POSIX 1003.1j/D10-1999 Options * ============================== * * _POSIX_READER_WRITER_LOCKS (set) - * If set, you can use read/write locks + * If set, you can use read/write locks * * _POSIX_SPIN_LOCKS (set) - * If set, you can use spin locks + * If set, you can use spin locks * * _POSIX_BARRIERS (set) - * If set, you can use barriers + * If set, you can use barriers * * ------------------------------------------------------------- */ @@ -321,30 +349,33 @@ extern "C" /* * POSIX Limits * - * PTHREAD_DESTRUCTOR_ITERATIONS - * Standard states this must be at least - * 4. + * PTHREAD_DESTRUCTOR_ITERATIONS + * Standard states this must be at least + * 4. * - * PTHREAD_KEYS_MAX - * WIN32 permits only 64 TLS keys per process. - * This limitation could be worked around by - * simply simulating keys. + * PTHREAD_KEYS_MAX + * WIN32 permits only 64 TLS keys per process. + * This limitation could be worked around by + * simply simulating keys. * - * PTHREADS_STACK_MIN - * POSIX specifies 0 which is also the value WIN32 - * interprets as allowing the system to - * set the size to that of the main thread. The - * maximum stack size in Win32 is 1Meg. WIN32 - * allocates more stack as required up to the 1Meg - * limit. + * PTHREADS_STACK_MIN + * POSIX specifies 0 which is also the value WIN32 + * interprets as allowing the system to + * set the size to that of the main thread. The + * maximum stack size in Win32 is 1Meg. WIN32 + * allocates more stack as required up to the 1Meg + * limit. * - * PTHREAD_THREADS_MAX - * Not documented by WIN32. Wrote a test program - * that kept creating threads until it failed - * revealed this approximate number. + * PTHREAD_THREADS_MAX + * Not documented by WIN32. Wrote a test program + * that kept creating threads until it failed + * revealed this approximate number (Windows NT). + * This number is somewhat less for Windows 9x + * and is effectively less than 64. Perhaps this + * constant should be set at DLL load time. * */ -#define PTHREAD_DESTRUCTOR_ITERATIONS 4 +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 #define PTHREAD_KEYS_MAX 64 #define PTHREAD_STACK_MIN 0 #define PTHREAD_THREADS_MAX 2019 @@ -386,19 +417,19 @@ enum { /* * pthread_attr_{get,set}inheritsched */ - PTHREAD_INHERIT_SCHED = 0, + PTHREAD_INHERIT_SCHED = 0, PTHREAD_EXPLICIT_SCHED = 1, /* Default */ /* * pthread_{get,set}scope */ - PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_PROCESS = 0, PTHREAD_SCOPE_SYSTEM = 1, /* Default */ /* * pthread_setcancelstate paramters */ - PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ PTHREAD_CANCEL_DISABLE = 1, /* @@ -437,13 +468,13 @@ enum { * ==================== * ==================== */ -#define PTHREAD_ONCE_INIT { FALSE, -1 } +#define PTHREAD_ONCE_INIT { FALSE, -1 } struct pthread_once_t_ { - int done; /* indicates if user function executed */ - long started; /* First thread to increment this value */ - /* to zero executes the user function */ + int done; /* indicates if user function executed */ + long started; /* First thread to increment this value */ + /* to zero executes the user function */ }; @@ -495,19 +526,17 @@ enum * C++ and C built versions will not. */ -/* - * define defaults for cleanup code +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. */ #if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) - -#if defined(_MSC_VER) -#define __CLEANUP_SEH -#elif defined(__cplusplus) -#define __CLEANUP_CXX -#else -#define __CLEANUP_C -#endif - +# define __CLEANUP_C #endif #if defined( __CLEANUP_SEH ) && defined(__GNUC__) @@ -533,7 +562,7 @@ struct ptw32_cleanup_t { \ ptw32_cleanup_t _cleanup; \ \ - _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ _cleanup.arg = (_arg); \ __try \ { \ @@ -560,7 +589,7 @@ struct ptw32_cleanup_t #define pthread_cleanup_push( _rout, _arg ) \ { \ ptw32_cleanup_t _cleanup; \ - \ + \ ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ #define pthread_cleanup_pop( _execute ) \ @@ -581,22 +610,22 @@ struct ptw32_cleanup_t * PThreadCleanup * * Purpose - * This class is a C++ helper class that is - * used to implement pthread_cleanup_push/ - * pthread_cleanup_pop. - * The destructor of this class automatically - * pops the pushed cleanup routine regardless - * of how the code exits the scope - * (i.e. such as by an exception) + * 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; + void * obj; + int executeIt; public: PThreadCleanup() : - cleanUpRout( NULL ), - obj( NULL ), + cleanUpRout( 0 ), + obj( 0 ), executeIt( 0 ) /* * No cleanup performed @@ -605,22 +634,22 @@ struct ptw32_cleanup_t } PThreadCleanup( - ptw32_cleanup_callback_t routine, - void * arg ) : + ptw32_cleanup_callback_t routine, + void * arg ) : cleanUpRout( routine ), obj( arg ), executeIt( 1 ) /* - * Registers a cleanup routine for 'arg' - */ + * Registers a cleanup routine for 'arg' + */ { } ~PThreadCleanup() { - if ( executeIt && ((void *) cleanUpRout != NULL) ) + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) { - (void) (*cleanUpRout)( obj ); + (void) (*cleanUpRout)( obj ); } } @@ -637,7 +666,7 @@ struct ptw32_cleanup_t * cleanup routine if we exit our scope weirdly */ #define pthread_cleanup_push( _rout, _arg ) \ - { \ + { \ PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ (void *) (_arg) ); @@ -689,28 +718,28 @@ int pthread_attr_setstacksize (pthread_attr_t * attr, size_t stacksize); int pthread_attr_getschedparam (const pthread_attr_t *attr, - struct sched_param *param); + struct sched_param *param); int pthread_attr_setschedparam (pthread_attr_t *attr, - const struct sched_param *param); + const struct sched_param *param); int pthread_attr_setschedpolicy (pthread_attr_t *, - int); + int); int pthread_attr_getschedpolicy (pthread_attr_t *, - int *); + int *); int pthread_attr_setinheritsched(pthread_attr_t * attr, - int inheritsched); + int inheritsched); int pthread_attr_getinheritsched(pthread_attr_t * attr, - int * inheritsched); + int * inheritsched); int pthread_attr_setscope (pthread_attr_t *, - int); + int); int pthread_attr_getscope (const pthread_attr_t *, - int *); + int *); /* * PThread Functions @@ -806,6 +835,9 @@ int pthread_mutex_destroy (pthread_mutex_t * mutex); int pthread_mutex_lock (pthread_mutex_t * mutex); +int pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + int pthread_mutex_trylock (pthread_mutex_t * mutex); int pthread_mutex_unlock (pthread_mutex_t * mutex); @@ -828,7 +860,7 @@ int pthread_spin_unlock (pthread_spinlock_t * lock); */ int pthread_barrier_init (pthread_barrier_t * barrier, const pthread_barrierattr_t * attr, - unsigned int count); + unsigned int count); int pthread_barrier_destroy (pthread_barrier_t * barrier); @@ -885,7 +917,7 @@ int pthread_getconcurrency (void); * Read-Write Lock Functions */ int pthread_rwlock_init(pthread_rwlock_t *lock, - const pthread_rwlockattr_t *attr); + const pthread_rwlockattr_t *attr); int pthread_rwlock_destroy(pthread_rwlock_t *lock); @@ -899,6 +931,15 @@ int pthread_rwlock_wrlock(pthread_rwlock_t *lock); int pthread_rwlock_unlock(pthread_rwlock_t *lock); +int pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +int pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +int pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); /* * Non-portable functions @@ -924,6 +965,7 @@ HANDLE pthread_getw32threadhandle_np(pthread_t thread); * Returns the number of CPUs available to the process. */ int pthread_getprocessors_np(int * count); +int pthread_num_processors_np(void); /* * Useful if an application wants to statically link @@ -943,7 +985,7 @@ int pthread_win32_thread_detach_np(void); * This function allows the caller to hook into the * PThreads cancel mechanism. It is implemented using * - * WaitForMultipleObjects + * WaitForMultipleObjects * * on 'waitHandle' and a manually reset WIN32 Event * used to implement pthread_cancel. The 'timeout' @@ -991,8 +1033,8 @@ int * _errno( void ); (_buf) ) #define ctime_r( _clock, _buf ) \ - ( strcpy( (_buf), ctime( (_clock) ) ), \ - (_buf) ) + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) #define gmtime_r( _clock, _result ) \ ( *(_result) = *gmtime( (_clock) ), \ @@ -1032,22 +1074,22 @@ DWORD ptw32_get_exception_services_code(void); * propagate our internal exceptions up to the library's internal handlers. */ #define __except( E ) \ - __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) #endif /* __CLEANUP_SEH */ -#ifdef __cplusplus +#ifdef __CLEANUP_CXX /* * Redefine the C++ catch keyword to ensure that applications * propagate our internal exceptions up to the library's internal handlers. */ #ifdef _MSC_VER - /* - * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' - * if you want Pthread-Win32 cancelation and pthread_exit to work. - */ + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ #ifndef PtW32NoCatchWarn @@ -1058,18 +1100,18 @@ DWORD ptw32_get_exception_services_code(void); #endif #define PtW32CatchAll \ - catch( ptw32_exception & ) { throw; } \ - catch( ... ) + catch( ptw32_exception & ) { throw; } \ + catch( ... ) #else /* _MSC_VER */ #define catch( E ) \ - catch( ptw32_exception & ) { throw; } \ - catch( E ) + catch( ptw32_exception & ) { throw; } \ + catch( E ) #endif /* _MSC_VER */ -#endif /* __cplusplus */ +#endif /* __CLEANUP_CXX */ #endif /* ! PTW32_BUILD */ @@ -1077,4 +1119,11 @@ DWORD ptw32_get_exception_services_code(void); } /* End of extern "C" */ #endif /* __cplusplus */ +#ifdef __HANDLE_DEF +# undef HANDLE +#endif +#ifdef __DWORD_DEF +# undef DWORD +#endif + #endif /* PTHREAD_H */ -- cgit v1.2.3