diff options
author | Kevin B Kenny <kennykb@acm.org> | 2001-05-31 23:45:44 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2001-05-31 23:45:44 (GMT) |
commit | f16a9d29ec4b0f401338397dee7f5d24f9acffb5 (patch) | |
tree | fdd7e6cc3e4c627755440c7f60e6ebe4311248fc /unix/tclUnixThrd.c | |
parent | 97464e6cba8eb0008cf2727c15718671992b913f (diff) | |
download | tcl-f16a9d29ec4b0f401338397dee7f5d24f9acffb5.zip tcl-f16a9d29ec4b0f401338397dee7f5d24f9acffb5.tar.gz tcl-f16a9d29ec4b0f401338397dee7f5d24f9acffb5.tar.bz2 |
Development branch for TIPs 22 and 33
kennykb_tip_22_33_botched
Diffstat (limited to 'unix/tclUnixThrd.c')
-rw-r--r-- | unix/tclUnixThrd.c | 682 |
1 files changed, 0 insertions, 682 deletions
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c deleted file mode 100644 index b00bf42..0000000 --- a/unix/tclUnixThrd.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * tclUnixThrd.c -- - * - * This file implements the UNIX-specific thread support. - * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * SCCS: @(#) tclUnixThrd.c 1.18 98/02/19 14:24:12 - */ - -#include "tclInt.h" - -#ifdef TCL_THREADS - -#include "tclPort.h" -#include "pthread.h" - -/* - * masterLock is used to serialize creation of mutexes, condition - * variables, and thread local storage. - * This is the only place that can count on the ability to statically - * initialize the mutex. - */ - -static pthread_mutex_t masterLock = PTHREAD_MUTEX_INITIALIZER; - -/* - * initLock is used to serialize initialization and finalization - * of Tcl. It cannot use any dyamically allocated storage. - */ - -static pthread_mutex_t initLock = PTHREAD_MUTEX_INITIALIZER; - -/* - * These are for the critical sections inside this file. - */ - -#define MASTER_LOCK pthread_mutex_lock(&masterLock) -#define MASTER_UNLOCK pthread_mutex_unlock(&masterLock) - -#endif /* TCL_THREADS */ - - - -#ifdef TCL_THREADS - -/* - *---------------------------------------------------------------------- - * - * TclpThreadCreate -- - * - * This procedure creates a new thread. - * - * Results: - * TCL_OK if the thread could be created. The thread ID is - * returned in a parameter. - * - * Side effects: - * A new thread is created. - * - *---------------------------------------------------------------------- - */ - -int -TclpThreadCreate(idPtr, proc, clientData) - Tcl_ThreadId *idPtr; /* Return, the ID of the thread */ - Tcl_ThreadCreateProc proc; /* Main() function of the thread */ - ClientData clientData; /* The one argument to Main() */ -{ - pthread_attr_t attr; - - pthread_attr_init(&attr); - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - if (pthread_create((pthread_t *)idPtr, &attr, (void * (*)())proc, (void *)clientData) < 0) { - return TCL_ERROR; - } else { - return TCL_OK; - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpThreadExit -- - * - * This procedure terminates the current thread. - * - * Results: - * None. - * - * Side effects: - * This procedure terminates the current thread. - * - *---------------------------------------------------------------------- - */ - -void -TclpThreadExit(status) - int status; -{ - pthread_exit((VOID *)status); -} -#endif /* TCL_THREADS */ - -/* - *---------------------------------------------------------------------- - * - * Tcl_GetCurrentThread -- - * - * This procedure returns the ID of the currently running thread. - * - * Results: - * A thread ID. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -Tcl_ThreadId -Tcl_GetCurrentThread() -{ -#ifdef TCL_THREADS - return (Tcl_ThreadId) pthread_self(); -#else - return (Tcl_ThreadId) 0; -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpInitLock - * - * This procedure is used to grab a lock that serializes initialization - * and finalization of Tcl. On some platforms this may also initialize - * the mutex used to serialize creation of more mutexes and thread - * local storage keys. - * - * Results: - * None. - * - * Side effects: - * Acquire the initialization mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpInitLock() -{ -#ifdef TCL_THREADS - pthread_mutex_lock(&initLock); -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpInitUnlock - * - * This procedure is used to release a lock that serializes initialization - * and finalization of Tcl. - * - * Results: - * None. - * - * Side effects: - * Release the initialization mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpInitUnlock() -{ -#ifdef TCL_THREADS - pthread_mutex_unlock(&initLock); -#endif -} - -/* - *---------------------------------------------------------------------- - * - * TclpMasterLock - * - * This procedure is used to grab a lock that serializes creation - * and finalization of serialization objects. This interface is - * only needed in finalization; it is hidden during - * creation of the objects. - * - * This lock must be different than the initLock because the - * initLock is held during creation of syncronization objects. - * - * Results: - * None. - * - * Side effects: - * Acquire the master mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpMasterLock() -{ -#ifdef TCL_THREADS - pthread_mutex_lock(&masterLock); -#endif -} - - -/* - *---------------------------------------------------------------------- - * - * TclpMasterUnlock - * - * This procedure is used to release a lock that serializes creation - * and finalization of synchronization objects. - * - * Results: - * None. - * - * Side effects: - * Release the master mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpMasterUnlock() -{ -#ifdef TCL_THREADS - pthread_mutex_unlock(&masterLock); -#endif -} - -#ifdef TCL_THREADS - -/* - *---------------------------------------------------------------------- - * - * TclpMutexInit -- - * TclpMutexLock -- - * TclpMutexUnlock -- - * - * These procedures use an explicitly initialized mutex. - * These are used by memory allocators for their own mutex. - * - * Results: - * None. - * - * Side effects: - * Initialize, Lock, and Unlock the mutex. - * - *---------------------------------------------------------------------- - */ - -void -TclpMutexInit(mPtr) - TclpMutex *mPtr; -{ - pthread_mutex_init((pthread_mutex_t *)mPtr, NULL); -} -void -TclpMutexLock(mPtr) - TclpMutex *mPtr; -{ - pthread_mutex_lock((pthread_mutex_t *)mPtr); -} -void -TclpMutexUnlock(mPtr) - TclpMutex *mPtr; -{ - pthread_mutex_unlock((pthread_mutex_t *)mPtr); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_MutexLock -- - * - * This procedure is invoked to lock a mutex. This procedure - * handles initializing the mutex, if necessary. The caller - * can rely on the fact that Tcl_Mutex is an opaque pointer. - * This routine will change that pointer from NULL after first use. - * - * Results: - * None. - * - * Side effects: - * May block the current thread. The mutex is aquired when - * this returns. Will allocate memory for a pthread_mutex_t - * and initialize this the first time this Tcl_Mutex is used. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_MutexLock(mutexPtr) - Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ -{ - pthread_mutex_t *pmutexPtr; - if (*mutexPtr == NULL) { - MASTER_LOCK; - if (*mutexPtr == NULL) { - /* - * Double inside master lock check to avoid a race. - */ - - pmutexPtr = (pthread_mutex_t *)ckalloc(sizeof(pthread_mutex_t)); - pthread_mutex_init(pmutexPtr, NULL); - *mutexPtr = (Tcl_Mutex)pmutexPtr; - TclRememberMutex(mutexPtr); - } - MASTER_UNLOCK; - } - pmutexPtr = *((pthread_mutex_t **)mutexPtr); - pthread_mutex_lock(pmutexPtr); -} - - -/* - *---------------------------------------------------------------------- - * - * TclpMutexUnlock -- - * - * This procedure is invoked to unlock a mutex. The mutex must - * have been locked by Tcl_MutexLock. - * - * Results: - * None. - * - * Side effects: - * The mutex is released when this returns. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_MutexUnlock(mutexPtr) - Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ -{ - pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr; - pthread_mutex_unlock(pmutexPtr); -} - - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeMutex -- - * - * This procedure is invoked to clean up one mutex. This is only - * safe to call at the end of time. - * - * This assumes the Master Lock is held. - * - * Results: - * None. - * - * Side effects: - * The mutex list is deallocated. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeMutex(mutexPtr) - Tcl_Mutex *mutexPtr; -{ - pthread_mutex_t *pmutexPtr = *(pthread_mutex_t **)mutexPtr; - if (pmutexPtr != NULL) { - ckfree((char *)pmutexPtr); - *mutexPtr = NULL; - } -} - - -/* - *---------------------------------------------------------------------- - * - * TclpThreadDataKeyInit -- - * - * This procedure initializes a thread specific data block key. - * Each thread has table of pointers to thread specific data. - * all threads agree on which table entry is used by each module. - * this is remembered in a "data key", that is just an index into - * this table. To allow self initialization, the interface - * passes a pointer to this key and the first thread to use - * the key fills in the pointer to the key. The key should be - * a process-wide static. - * - * Results: - * None. - * - * Side effects: - * Will allocate memory the first time this process calls for - * this key. In this case it modifies its argument - * to hold the pointer to information about the key. - * - *---------------------------------------------------------------------- - */ - -void -TclpThreadDataKeyInit(keyPtr) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ -{ - pthread_key_t *pkeyPtr; - - MASTER_LOCK; - if (*keyPtr == NULL) { - pkeyPtr = (pthread_key_t *)ckalloc(sizeof(pthread_key_t)); - pthread_key_create(pkeyPtr, NULL); - *keyPtr = (Tcl_ThreadDataKey)pkeyPtr; - TclRememberDataKey(keyPtr); - } - MASTER_UNLOCK; -} - -/* - *---------------------------------------------------------------------- - * - * TclpThreadDataKeyGet -- - * - * This procedure returns a pointer to a block of thread local storage. - * - * Results: - * A thread-specific pointer to the data structure, or NULL - * if the memory has not been assigned to this key for this thread. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -VOID * -TclpThreadDataKeyGet(keyPtr) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ -{ - pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr; - if (pkeyPtr == NULL) { - return NULL; - } else { - return (VOID *)pthread_getspecific(*pkeyPtr); - } -} - - -/* - *---------------------------------------------------------------------- - * - * TclpThreadDataKeySet -- - * - * This procedure sets the pointer to a block of thread local storage. - * - * Results: - * None. - * - * Side effects: - * Sets up the thread so future calls to TclpThreadDataKeyGet with - * this key will return the data pointer. - * - *---------------------------------------------------------------------- - */ - -void -TclpThreadDataKeySet(keyPtr, data) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ - VOID *data; /* Thread local storage */ -{ - pthread_key_t *pkeyPtr = *(pthread_key_t **)keyPtr; - pthread_setspecific(*pkeyPtr, data); -} - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeThreadData -- - * - * This procedure cleans up the thread-local storage. This is - * called once for each thread. - * - * Results: - * None. - * - * Side effects: - * Frees up all thread local storage. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeThreadData(keyPtr) - Tcl_ThreadDataKey *keyPtr; -{ - VOID *result; - pthread_key_t *pkeyPtr; - - if (*keyPtr != NULL) { - pkeyPtr = *(pthread_key_t **)keyPtr; - result = (VOID *)pthread_getspecific(*pkeyPtr); - if (result != NULL) { - ckfree((char *)result); - pthread_setspecific(*pkeyPtr, (void *)NULL); - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeThreadDataKey -- - * - * This procedure is invoked to clean up one key. This is a - * process-wide storage identifier. The thread finalization code - * cleans up the thread local storage itself. - * - * This assumes the master lock is held. - * - * Results: - * None. - * - * Side effects: - * The key is deallocated. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeThreadDataKey(keyPtr) - Tcl_ThreadDataKey *keyPtr; -{ - pthread_key_t *pkeyPtr; - if (*keyPtr != NULL) { - pkeyPtr = *(pthread_key_t **)keyPtr; - pthread_key_delete(*pkeyPtr); - ckfree((char *)pkeyPtr); - *keyPtr = NULL; - } -} - - -/* - *---------------------------------------------------------------------- - * - * Tcl_ConditionWait -- - * - * This procedure is invoked to wait on a condition variable. - * The mutex is automically released as part of the wait, and - * automatically grabbed when the condition is signaled. - * - * The mutex must be held when this procedure is called. - * - * Results: - * None. - * - * Side effects: - * May block the current thread. The mutex is aquired when - * this returns. Will allocate memory for a pthread_mutex_t - * and initialize this the first time this Tcl_Mutex is used. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_ConditionWait(condPtr, mutexPtr, timePtr) - Tcl_Condition *condPtr; /* Really (pthread_cond_t **) */ - Tcl_Mutex *mutexPtr; /* Really (pthread_mutex_t **) */ - Tcl_Time *timePtr; /* Timeout on waiting period */ -{ - pthread_cond_t *pcondPtr; - pthread_mutex_t *pmutexPtr; - struct timespec ptime; - - if (*condPtr == NULL) { - MASTER_LOCK; - - /* - * Double check inside mutex to avoid race, - * then initialize condition variable if necessary. - */ - - if (*condPtr == NULL) { - pcondPtr = (pthread_cond_t *)ckalloc(sizeof(pthread_cond_t)); - pthread_cond_init(pcondPtr, NULL); - *condPtr = (Tcl_Condition)pcondPtr; - TclRememberCondition(condPtr); - } - MASTER_UNLOCK; - } - pmutexPtr = *((pthread_mutex_t **)mutexPtr); - pcondPtr = *((pthread_cond_t **)condPtr); - if (timePtr == NULL) { - pthread_cond_wait(pcondPtr, pmutexPtr); - } else { - ptime.tv_sec = timePtr->sec + TclpGetSeconds(); - ptime.tv_nsec = 1000 * timePtr->usec; - pthread_cond_timedwait(pcondPtr, pmutexPtr, &ptime); - } -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_ConditionNotify -- - * - * This procedure is invoked to signal a condition variable. - * - * The mutex must be held during this call to avoid races, - * but this interface does not enforce that. - * - * Results: - * None. - * - * Side effects: - * May unblock another thread. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_ConditionNotify(condPtr) - Tcl_Condition *condPtr; -{ - pthread_cond_t *pcondPtr = *((pthread_cond_t **)condPtr); - if (pcondPtr != NULL) { - pthread_cond_broadcast(pcondPtr); - } else { - /* - * Noone has used the condition variable, so there are no waiters. - */ - } -} - - -/* - *---------------------------------------------------------------------- - * - * TclpFinalizeCondition -- - * - * This procedure is invoked to clean up a condition variable. - * This is only safe to call at the end of time. - * - * This assumes the Master Lock is held. - * - * Results: - * None. - * - * Side effects: - * The condition variable is deallocated. - * - *---------------------------------------------------------------------- - */ - -void -TclpFinalizeCondition(condPtr) - Tcl_Condition *condPtr; -{ - pthread_cond_t *pcondPtr = *(pthread_cond_t **)condPtr; - if (pcondPtr != NULL) { - pthread_cond_destroy(pcondPtr); - ckfree((char *)pcondPtr); - *condPtr = NULL; - } -} - - - -#endif /* TCL_THREADS */ - |