summaryrefslogtreecommitdiff
path: root/private.c
diff options
context:
space:
mode:
authorrpj <rpj>1998-12-22 15:59:24 +0000
committerrpj <rpj>1998-12-22 15:59:24 +0000
commit95aa0a376d93ee021a6c085c71418e9f16513e0a (patch)
treef05f436e30d759df3af5cfe9e2cde62e3efa6f1b /private.c
parent4650bcf1f1efd88a0c8f502c28945bfabd7ef6db (diff)
Sun Dec 20 14:51:58 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au>
* misc.c (pthreadCancelableWait): New function by John Bossom. Non-stand ard but provides a hook that can be used to implement cancellation points in applications that use this library. * pthread.h (pthread_cleanup_pop): C++ (non-WIN32) version uses try/catch to emulate John Bossom's WIN32 __try/__finally behaviour. In the WIN32 version __finally block, add a test for AbnormalTermination otherwise cleanup is only run if the cleanup_pop execute arg is non-zero. Cancella tion should cause the cleanup to run irrespective of the execute arg. * condvar.c (pthread_condattr_init): Replaced by John Bossom's version. (pthread_condattr_destroy): Replaced by John Bossom's version. (pthread_condattr_getpshared): Replaced by John Bossom's version. (pthread_condattr_setpshared): Replaced by John Bossom's version. (pthread_cond_init): Replaced by John Bossom's version. Fix comment (refered to mutex rather than condition variable). (pthread_cond_destroy): Replaced by John Bossom's version. (pthread_cond_wait): Replaced by John Bossom's version. (pthread_cond_timedwait): Replaced by John Bossom's version. (pthread_cond_signal): Replaced by John Bossom's version. (pthread_cond_broadcast): Replaced by John Bossom's version. Thu Dec 17 19:10:46 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * tsd.c (pthread_key_create): Replaced by John Bossom's version. (pthread_key_delete): Replaced by John Bossom's version. (pthread_setspecific): Replaced by John Bossom's version. (pthread_getspecific): Replaced by John Bossom's version. Mon Dec 7 09:44:40 1998 Ross Johnson <rpj@ixobrychus.canberra.edu.au> * cancel.c (pthread_setcancelstate): Replaced by John Bossom's version. (pthread_setcanceltype): Replaced by John Bossom's version. (pthread_testcancel): Replaced by John Bossom's version. (pthread_cancel): Replaced by John Bossom's version. * exit.c (pthread_exit): Replaced by John Bossom's version. * misc.c (pthread_self): Replaced by John Bossom's version. (pthread_equal): Replaced by John Bossom's version. * sync.c (pthread_detach): Replaced by John Bossom's version. (pthread_join): Replaced by John Bossom's version. * create.c (pthread_create): Replaced by John Bossom's version. * private.c (_pthread_processInitialize): New by John Bossom. (_pthread_processTerminate): Non-public function by John Bossom. (_pthread_threadStart): Non-public function by John Bossom. (_pthread_threadDestroy): Non-public function by John Bossom. (_pthread_cleanupStack): Non-public function by John Bossom. (_pthread_tkAssocCreate): Non-public function by John Bossom. (_pthread_tkAssocDestroy): Non-public function by John Bossom. (_pthread_callUserDestroyRoutines): Non-public function by John Bossom. * implement.h: Added John Bossom's non-API structures and declarations. * dll.c (PthreadsEntryPoint): Cast return value of GetProcAddress to resolve compile warning from MSVC. * dll.c (DLLmain): Replaced by John Bossom's version. * dll.c (PthreadsEntryPoint): Re-applied Anders Norlander's patch:- Initialize _pthread_try_enter_critical_section at startup and release kernel32 handle when DLL is being unloaded.
Diffstat (limited to 'private.c')
-rw-r--r--private.c411
1 files changed, 411 insertions, 0 deletions
diff --git a/private.c b/private.c
index 32116ef..9891660 100644
--- a/private.c
+++ b/private.c
@@ -11,6 +11,415 @@
#include "pthread.h"
#include "implement.h"
+/*
+ * Code contributed by John E. Bossom <JEB>.
+ */
+
+int
+_pthread_processInitialize (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPRIVATE
+ * This function performs process wide initialization for
+ * the pthread library.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ * DESCRIPTION
+ * This function performs process wide initialization for
+ * the pthread library.
+ * If successful, this routine sets the global variable
+ * _pthread_processInitialized to TRUE.
+ *
+ * RESULTS
+ * TRUE if successful,
+ * FALSE otherwise
+ *
+ * ------------------------------------------------------
+ */
+{
+ _pthread_processInitialized = TRUE;
+
+ /*
+ * Initialize Keys
+ */
+ if ((pthread_key_create (&_pthread_selfThreadKey, NULL) != 0) ||
+ (pthread_key_create (&_pthread_cleanupKey, NULL) != 0))
+ {
+
+ _pthread_processTerminate ();
+ }
+
+ return (_pthread_processInitialized);
+
+} /* processInitialize */
+
+void
+_pthread_processTerminate (void)
+ /*
+ * ------------------------------------------------------
+ * DOCPRIVATE
+ * This function performs process wide termination for
+ * the pthread library.
+ *
+ * PARAMETERS
+ * N/A
+ *
+ * DESCRIPTION
+ * This function performs process wide termination for
+ * the pthread library.
+ * This routine sets the global variable
+ * _pthread_processInitialized to FALSE
+ *
+ * RESULTS
+ * N/A
+ *
+ * ------------------------------------------------------
+ */
+{
+ if (_pthread_processInitialized)
+ {
+
+ if (_pthread_selfThreadKey != NULL)
+ {
+ /*
+ * Release _pthread_selfThreadKey
+ */
+ pthread_key_delete (_pthread_selfThreadKey);
+
+ _pthread_selfThreadKey = NULL;
+ }
+
+ if (_pthread_cleanupKey != NULL)
+ {
+ /*
+ * Release _pthread_cleanupKey
+ */
+ pthread_key_delete (_pthread_cleanupKey);
+
+ _pthread_cleanupKey = NULL;
+ }
+
+ _pthread_processInitialized = FALSE;
+ }
+
+} /* processTerminate */
+
+
+
+void *
+_pthread_threadStart (ThreadParms * threadParms)
+{
+ pthread_t tid;
+ void *(*start) (void *);
+ void *arg;
+
+ int status;
+
+ tid = threadParms->tid;
+ start = threadParms->start;
+ arg = threadParms->arg;
+
+ free (threadParms);
+
+ pthread_setspecific (_pthread_selfThreadKey, tid);
+
+ __try
+ {
+ /*
+ * Run the caller's routine;
+ */
+ (*start) (arg);
+ status = 0;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ /*
+ * A system unexpected exception had occurred running the user's
+ * routine. We get control back within this block.
+ */
+ status = -1;
+ }
+
+ pthread_exit ((void *) status);
+
+ return ((void *) status);
+
+} /* threadStart */
+
+
+void
+_pthread_threadDestroy (pthread_t thread)
+{
+ if (thread != NULL)
+ {
+
+ callUserDestroyRoutines (thread);
+
+ if (thread->cancelEvent != NULL)
+ {
+ CloseHandle (thread->cancelEvent);
+ }
+
+ free (thread);
+ }
+
+} /* threadDestroy */
+
+#if defined( KLUDGE )
+
+void
+_pthread_cleanupStack (void)
+{
+ while (pthread_pop_cleanup (1))
+ {
+ }
+
+} /* cleanupStack */
+
+#endif /* KLUDGE */
+
+int
+_pthread_tkAssocCreate (ThreadKeyAssoc ** assocP,
+ pthread_t thread,
+ pthread_key_t key)
+ /*
+ * -------------------------------------------------------------------
+ * This routine creates an association that
+ * is unique for the given (thread,key) combination.The association
+ * is referenced by both the thread and the key.
+ * This association allows us to determine what keys the
+ * current thread references and what threads a given key
+ * references.
+ * See the detailed description
+ * at the beginning of this file for further details.
+ *
+ * Notes:
+ * 1) New associations are pushed to the beginning of the
+ * chain so that the internal _pthread_selfThreadKey association
+ * is always last, thus allowing selfThreadExit to
+ * be implicitly called by pthread_exit last.
+ *
+ * Parameters:
+ * assocP
+ * address into which the association is returned.
+ * thread
+ * current running thread. If NULL, then association
+ * is only added to the key. A NULL thread indicates
+ * that the user called pthread_setspecific prior
+ * to starting a thread. That's ok.
+ * key
+ * key on which to create an association.
+ * Returns:
+ * 0 - if successful,
+ * -1 - general error
+ * -------------------------------------------------------------------
+ */
+{
+ int result;
+ ThreadKeyAssoc *assoc;
+
+ /*
+ * Have to create an association and add it
+ * to both the key and the thread.
+ */
+ assoc = (ThreadKeyAssoc *)
+ calloc (1, sizeof (*assoc));
+
+ if (assoc == NULL)
+ {
+ result = -1;
+ goto FAIL0;
+ }
+
+ if ((result = pthread_mutex_init (&(assoc->lock), NULL)) !=
+ 0)
+ {
+ goto FAIL1;
+ }
+
+ assoc->thread = thread;
+ assoc->key = key;
+
+ /*
+ * Register assoc with key
+ */
+ if ((result = pthread_mutex_lock (&(key->threadsLock))) !=
+ 0)
+ {
+ goto FAIL2;
+ }
+
+ assoc->nextThread = (ThreadKeyAssoc *) key->threads;
+ key->threads = (void *) assoc;
+
+ pthread_mutex_unlock (&(key->threadsLock));
+
+ if (thread != NULL)
+ {
+ /*
+ * Register assoc with thread
+ */
+ assoc->nextKey = (ThreadKeyAssoc *) thread->keys;
+ thread->keys = (void *) assoc;
+ }
+
+ *assocP = assoc;
+
+ return (result);
+
+ /*
+ * -------------
+ * Failure Code
+ * -------------
+ */
+FAIL2:
+ pthread_mutex_destroy (&(assoc->lock));
+
+FAIL1:
+ free (assoc);
+
+FAIL0:
+
+ return (result);
+
+} /* tkAssocCreate */
+
+
+void
+_pthread_tkAssocDestroy (ThreadKeyAssoc * assoc)
+ /*
+ * -------------------------------------------------------------------
+ * This routine releases all resources for the given ThreadKeyAssoc
+ * once it is no longer being referenced
+ * ie) both the key and thread have stopped referencing it.
+ *
+ * Parameters:
+ * assoc
+ * an instance of ThreadKeyAssoc.
+ * Returns:
+ * N/A
+ * -------------------------------------------------------------------
+ */
+{
+
+ if ((assoc != NULL) &&
+ (assoc->key == NULL && assoc->thread == NULL))
+ {
+
+ pthread_mutex_destroy (&(assoc->lock));
+
+ free (assoc);
+ }
+
+} /* tkAssocDestroy */
+
+
+void
+_pthread_callUserDestroyRoutines (pthread_t thread)
+ /*
+ * -------------------------------------------------------------------
+ * DOCPRIVATE
+ *
+ * This the routine runs through all thread keys and calls
+ * the destroy routines on the user's data for the current thread.
+ * It simulates the behaviour of POSIX Threads.
+ *
+ * PARAMETERS
+ * thread
+ * an instance of pthread_t
+ *
+ * RETURNS
+ * N/A
+ * -------------------------------------------------------------------
+ */
+{
+ ThreadKeyAssoc **nextP;
+ ThreadKeyAssoc *assoc;
+
+ if (thread != NULL)
+ {
+ /*
+ * Run through all Thread<-->Key associations
+ * for the current thread.
+ * If the pthread_key_t still exits (ie the assoc->key
+ * is not NULL) then call the user's TSD destroy routine.
+ * Notes:
+ * If assoc->key is NULL, then the user previously called
+ * PThreadKeyDestroy. The association is now only referenced
+ * by the current thread and must be released; otherwise
+ * the assoc will be destroyed when the key is destroyed.
+ */
+ nextP = (ThreadKeyAssoc **) & (thread->keys);
+ assoc = *nextP;
+
+ while (assoc != NULL)
+ {
+
+ if (pthread_mutex_lock (&(assoc->lock)) == 0)
+ {
+ pthread_key_t k;
+ if ((k = assoc->key) != NULL)
+ {
+ /*
+ * Key still active; pthread_key_delete
+ * will block on this same mutex before
+ * it can release actual key; therefore,
+ * key is valid and we can call the destroy
+ * routine;
+ */
+ void *value = NULL;
+
+ value = pthread_getspecific (k);
+ if (value != NULL && k->destructor != NULL)
+ {
+
+ __try
+ {
+ /*
+ * Run the caller's cleanup routine.
+ */
+ (*(k->destructor)) (value);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ /*
+ * A system unexpected exception had occurred
+ * running the user's destructor.
+ * We get control back within this block.
+ */
+ }
+ }
+ }
+
+ /*
+ * mark assoc->thread as NULL to indicate the
+ * thread no longer references this association
+ */
+ assoc->thread = NULL;
+
+ /*
+ * Remove association from the pthread_t chain
+ */
+ *nextP = assoc->nextKey;
+
+ pthread_mutex_unlock (&(assoc->lock));
+
+ _pthread_tkAssocDestroy (assoc);
+
+ assoc = *nextP;
+ }
+ }
+ }
+
+} /* callUserDestroyRoutines */
+
+/* </JEB> */
+
+
+#if 0 /* Pre Bossom */
+
/* Thread ID management.
---------------------
@@ -141,3 +550,5 @@ _pthread_delete_thread(_pthread_t * thread)
return EINVAL;
}
+
+#endif /* Pre Bossom */