summaryrefslogtreecommitdiff
path: root/private.c
diff options
context:
space:
mode:
authorrpj <rpj>2001-05-31 02:01:47 +0000
committerrpj <rpj>2001-05-31 02:01:47 +0000
commite121b938c9f012958196a3141f04a3fd4f58bdb9 (patch)
treed1cb950413e3a350606f2a4d9bea687b6680570d /private.c
parent6bf07e836550f9ffe11e0f38ff1323be731eb250 (diff)
2001-05-30 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
* pthread.h (rand_r): Fake using _seed argument to quell compiler warning (compiler should optimise this away later). * GNUmakefile (OPT): Leave symbolic information out of the library and increase optimisation level - for smaller faster prebuilt dlls. 2001-05-29 Ross Johnson <rpj@setup1.ise.canberra.edu.au> Contributed by - Milan Gardian <Milan.Gardian@LEIBINGER.com> * Makefile: fix typo. * pthreads.h: Fix problems with stdcall/cdecl conventions, in particular remove the need for PT_STDCALL everywhere; remove warning supression. * (errno): Fix the longstanding "inconsistent dll linkage" problem with errno; now also works with /MD debugging libs - warnings emerged when compiling pthreads library with /MD (or /MDd) compiler switch, instead of /MT (or /MTd) (i.e. when compiling pthreads using Multithreaded DLL CRT instead of Multithreaded statically linked CRT). * create.c (pthread_create): Likewise; fix typo. * private.c (ptw32_threadStart): Eliminate use of terminate() which doesn't throw exceptions. * Remove unnecessary #includes from a number of modules - [I had to #include malloc.h in implement.h for gcc - rpj]. 2001-05-29 Ross Johnson <rpj@setup1.ise.canberra.edu.au> Contributed by - Thomas Pfaff <tpfaff@gmx.net> * pthread.h (PTHREAD_MUTEX_DEFAULT): New; equivalent to PTHREAD_MUTEX_DEFAULT_NP. * (PTHREAD_MUTEX_NORMAL): Similarly. * (PTHREAD_MUTEX_ERRORCHECK): Similarly. * (PTHREAD_MUTEX_RECURSIVE): Similarly. * (pthread_mutex_setdefaultkind_np): New; Linux compatibility stub for pthread_mutexattr_settype. * (pthread_mutexattr_getkind_np): New; Linux compatibility stub for pthread_mutexattr_gettype. * mutex.c (pthread_mutexattr_settype): New; allow the following types of mutex: PTHREAD_MUTEX_DEFAULT_NP PTHREAD_MUTEX_NORMAL_NP PTHREAD_MUTEX_ERRORCHECK_NP PTHREAD_MUTEX_RECURSIVE_NP * Note that PTHREAD_MUTEX_DEFAULT is equivalent to PTHREAD_MUTEX_NORMAL - ie. mutexes should no longer be recursive by default, and a thread will deadlock if it tries to relock a mutex it already owns. This is inline with other pthreads implementations. * (pthread_mutex_lock): Process the lock request according to the mutex type. * (pthread_mutex_init): Eliminate use of Win32 mutexes as the basis of POSIX mutexes - instead, a combination of one critical section and one semaphore are used in conjunction with Win32 Interlocked* routines. * (pthread_mutex_destroy): Likewise. * (pthread_mutex_lock): Likewise. * (pthread_mutex_trylock): Likewise. * (pthread_mutex_unlock): Likewise. * Use longjmp/setjmp to implement cancelation when building the library using a C compiler which doesn't support exceptions, e.g. gcc -x c (note that gcc -x c++ uses exceptions). * Also fixed some of the same typos and eliminated PT_STDCALL as Milan Gardian's patches above. 2001-02-07 Ross Johnson <rpj@special.ise.canberra.edu.au> Contributed by - Alexander Terekhov <TEREKHOV@de.ibm.com> * rwlock.c: Revamped. * implement.h (pthread_rwlock_t_): Redefined. This implementation does not have reader/writer starvation problem. Rwlock attempts to behave more like a normal mutex with races and scheduling policy determining who is more important; It also supports recursive locking, has less synchronization overhead (no broadcasts at all, readers are not blocked on any condition variable) and seem to be faster than the current implementation [W98 appears to be approximately 15 percent faster at least - on top of speed increase from Thomas Pfaff's changes to mutex.c - rpj].
Diffstat (limited to 'private.c')
-rw-r--r--private.c151
1 files changed, 106 insertions, 45 deletions
diff --git a/private.c b/private.c
index ee3ab52..5274da9 100644
--- a/private.c
+++ b/private.c
@@ -24,12 +24,7 @@
* MA 02111-1307, USA
*/
-#if !defined(_MSC_VER) && !defined(__cplusplus) && defined(__GNUC__)
-
-#warning Compile __FILE__ as C++ or thread cancellation will not work properly.
-
-#endif /* !_MSC_VER && !__cplusplus && __GNUC__ */
-
+#include <process.h>
#ifndef NEED_FTIME
#include <sys/timeb.h>
#endif
@@ -154,7 +149,7 @@ ptw32_processTerminate (void)
} /* processTerminate */
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
static DWORD
ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
@@ -194,7 +189,7 @@ ExceptionFilter (EXCEPTION_POINTERS * ep, DWORD * ei)
}
}
-#elif defined(__cplusplus)
+#elif defined(__CLEANUP_CXX)
#if defined(_MSC_VER)
#include <eh.h>
@@ -230,20 +225,25 @@ ptw32_terminate ()
#endif /* _MSC_VER */
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
-unsigned PT_STDCALL
+unsigned __stdcall
#else
void
#endif
-ptw32_threadStart (ThreadParms * threadParms)
+ptw32_threadStart (void * vthreadParms)
{
+ ThreadParms *threadParms = (ThreadParms *) vthreadParms;
pthread_t self;
void *(*start) (void *);
void *arg;
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
DWORD ei[] = {0,0,0};
#endif
+#ifdef __CLEANUP_C
+ int setjmp_rc;
+#endif
+
void * status = (void *) 0;
self = threadParms->tid;
@@ -270,7 +270,7 @@ ptw32_threadStart (ThreadParms * threadParms)
pthread_setspecific (ptw32_selfThreadKey, self);
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
__try
{
@@ -295,9 +295,39 @@ ptw32_threadStart (ThreadParms * threadParms)
}
}
-#else /* _MSC_VER && !__cplusplus */
+#else /* __CLEANUP_SEH */
-#ifdef __cplusplus
+#ifdef __CLEANUP_C
+
+ setjmp_rc = setjmp( self->start_mark );
+
+ if( 0 == setjmp_rc ) {
+
+ /*
+ * Run the caller's routine;
+ */
+ status = self->exitStatus = (*start) (arg);
+ }
+
+ else {
+
+ switch (setjmp_rc)
+ {
+ case PTW32_EPS_CANCEL:
+ status = PTHREAD_CANCELED;
+ break;
+ case PTW32_EPS_EXIT:
+ status = self->exitStatus;
+ break;
+ default:
+ status = PTHREAD_CANCELED;
+ break;
+ }
+ }
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
ptw32_oldTerminate = set_terminate(&ptw32_terminate);
@@ -328,7 +358,30 @@ ptw32_threadStart (ThreadParms * threadParms)
*
* ptw32_terminate() will be called if there is no user supplied function.
*/
- (void) terminate();
+
+ //Original invocation:
+ //(void) terminate();
+
+
+ //New invocation:
+ // a) get pointer to the termination function
+#if defined(_MSC_VER)
+ terminate_function term_func = set_terminate(0);
+#else
+ terminate_handler term_func = set_terminate(0);
+#endif
+
+ set_terminate(term_func);
+
+ // b) call the termination function (if any)
+ if (term_func != 0) {
+ term_func();
+ }
+
+ // c) if there was no termination function or the termination function did
+ // not exit thread/process, (we got this far), propagate the exception on!
+ // (should be caught by the second level try/catch block below)
+ throw;
}
}
catch (ptw32_exception_cancel &)
@@ -365,17 +418,14 @@ ptw32_threadStart (ThreadParms * threadParms)
(void) set_terminate(ptw32_oldTerminate);
-#else /* __cplusplus */
+#else
- /*
- * Run the caller's routine; no cancelation or other exceptions will
- * be honoured.
- */
- status = self->exitStatus = (*start) (arg);
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
-#endif /* __cplusplus */
+#endif /* __CLEANUP_CXX */
+#endif /* __CLEANUP_C */
+#endif /* __CLEANUP_SEH */
-#endif /* _MSC_VER */
(void) pthread_mutex_destroy(&self->cancelLock);
@@ -637,19 +687,6 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
if (value != NULL && k->destructor != NULL)
{
-#if defined(_MSC_VER) && !defined(__cplusplus)
-
- /*
- * Run the caller's cleanup routine.
- *
- * If an exception occurs we let the system handle it
- * as an unhandled exception. Since we are leaving the
- * thread we should not get any internal pthreads
- * exceptions.
- */
- (*(k->destructor)) (value);
-
-#else /* _MSC_VER && !__cplusplus */
#ifdef __cplusplus
try
@@ -681,7 +718,6 @@ ptw32_callUserDestroyRoutines (pthread_t thread)
(*(k->destructor)) (value);
#endif /* __cplusplus */
-#endif /* _MSC_VER */
}
}
@@ -895,7 +931,7 @@ ptw32_sem_timedwait (sem_t * sem, const struct timespec * abstime)
DWORD
ptw32_get_exception_services_code(void)
{
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
return EXCEPTION_PTW32_SERVICES;
@@ -910,10 +946,13 @@ ptw32_get_exception_services_code(void)
void
ptw32_throw(DWORD exception)
{
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_C
+ pthread_t self = pthread_self();
+#endif
- DWORD exceptionInformation[3];
+#ifdef __CLEANUP_SEH
+ DWORD exceptionInformation[3];
#endif
if (exception != PTW32_EPS_CANCEL &&
@@ -923,7 +962,8 @@ ptw32_throw(DWORD exception)
exit(1);
}
-#if defined(_MSC_VER) && !defined(__cplusplus)
+#ifdef __CLEANUP_SEH
+
exceptionInformation[0] = (DWORD) (exception);
exceptionInformation[1] = (DWORD) (0);
@@ -935,9 +975,17 @@ ptw32_throw(DWORD exception)
3,
exceptionInformation);
-#else /* _MSC_VER && ! __cplusplus */
+#else /* __CLEANUP_SEH */
+
+#ifdef __CLEANUP_C
-# ifdef __cplusplus
+ ptw32_pop_cleanup_all( 1 );
+
+ longjmp( self->start_mark, exception );
+
+#else /* __CLEANUP_C */
+
+#ifdef __CLEANUP_CXX
switch (exception)
{
@@ -949,9 +997,22 @@ ptw32_throw(DWORD exception)
break;
}
-# endif /* __cplusplus */
+#else
-#endif /* _MSC_VER && ! __cplusplus */
+#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined.
+
+#endif /* __CLEANUP_CXX */
+
+#endif /* __CLEANUP_C */
+
+#endif /* __CLEANUP_SEH */
/* Never reached */
}
+
+void
+ptw32_pop_cleanup_all(int execute)
+{
+ while( NULL != ptw32_pop_cleanup(execute) ) {
+ }
+}