diff options
Diffstat (limited to 'generic/tclThread.c')
-rw-r--r-- | generic/tclThread.c | 210 |
1 files changed, 113 insertions, 97 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c index 17dd0ad..8c972a8 100644 --- a/generic/tclThread.c +++ b/generic/tclThread.c @@ -1,15 +1,14 @@ -/* +/* * tclThread.c -- * * This file implements Platform independent thread operations. Most of * the real work is done in the platform dependent files. * * Copyright (c) 1998 by Sun Microsystems, Inc. + * Copyright (c) 2008 by George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclThread.c,v 1.13 2005/08/11 22:06:47 kennykb Exp $ */ #include "tclInt.h" @@ -26,7 +25,7 @@ typedef struct { int num; /* Number of objects remembered */ int max; /* Max size of the array */ - char **list; /* List of pointers */ + void **list; /* List of pointers */ } SyncObjRecord; static SyncObjRecord keyRecord = {0, 0, NULL}; @@ -36,13 +35,12 @@ static SyncObjRecord condRecord = {0, 0, NULL}; /* * Prototypes of functions used only in this file. */ - -static void RememberSyncObject _ANSI_ARGS_((char *objPtr, - SyncObjRecord *recPtr)); -static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, - SyncObjRecord *recPtr)); -/* +static void ForgetSyncObject(void *objPtr, SyncObjRecord *recPtr); +static void RememberSyncObject(void *objPtr, + SyncObjRecord *recPtr); + +/* * Several functions are #defined to nothing in tcl.h if TCL_THREADS is not * specified. Here we undo that so the functions are defined in the stubs * table. @@ -56,7 +54,6 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, #undef Tcl_ConditionWait #undef Tcl_ConditionFinalize #endif - /* *---------------------------------------------------------------------- @@ -76,31 +73,33 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, *---------------------------------------------------------------------- */ -VOID * -Tcl_GetThreadData(keyPtr, size) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */ - int size; /* Size of storage block */ +void * +Tcl_GetThreadData( + Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */ + int size) /* Size of storage block */ { - VOID *result; + void *result; #ifdef TCL_THREADS /* * Initialize the key for this thread. */ - result = TclpThreadDataKeyGet(keyPtr); + + result = TclThreadStorageKeyGet(keyPtr); if (result == NULL) { - result = (VOID *)ckalloc((size_t)size); - memset(result, 0, (size_t)size); - TclpThreadDataKeySet(keyPtr, result); + result = ckalloc(size); + memset(result, 0, (size_t) size); + TclThreadStorageKeySet(keyPtr, result); } #else /* TCL_THREADS */ if (*keyPtr == NULL) { - result = (VOID *)ckalloc((size_t)size); - memset((char *)result, 0, (size_t)size); - *keyPtr = (Tcl_ThreadDataKey)result; - RememberSyncObject((char *)keyPtr, &keyRecord); + result = ckalloc(size); + memset(result, 0, (size_t)size); + *keyPtr = result; + RememberSyncObject(keyPtr, &keyRecord); + } else { + result = *keyPtr; } - result = *(VOID **)keyPtr; #endif /* TCL_THREADS */ return result; } @@ -122,19 +121,17 @@ Tcl_GetThreadData(keyPtr, size) *---------------------------------------------------------------------- */ -VOID * -TclThreadDataKeyGet(keyPtr) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, really - * (pthread_key_t **) */ +void * +TclThreadDataKeyGet( + Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk. */ + { #ifdef TCL_THREADS - return (VOID *)TclpThreadDataKeyGet(keyPtr); + return TclThreadStorageKeyGet(keyPtr); #else /* TCL_THREADS */ - char *result = *(char **)keyPtr; - return (VOID *)result; + return *keyPtr; #endif /* TCL_THREADS */ } - /* *---------------------------------------------------------------------- @@ -144,6 +141,8 @@ TclThreadDataKeyGet(keyPtr) * Keep a list of (mutexes/condition variable/data key) used during * finalization. * + * Assume master lock is held. + * * Results: * None. * @@ -154,33 +153,45 @@ TclThreadDataKeyGet(keyPtr) */ static void -RememberSyncObject(objPtr, recPtr) - char *objPtr; /* Pointer to sync object */ - SyncObjRecord *recPtr; /* Record of sync objects */ +RememberSyncObject( + void *objPtr, /* Pointer to sync object */ + SyncObjRecord *recPtr) /* Record of sync objects */ { - char **newList; + void **newList; int i, j; + /* - * Save the pointer to the allocated object so it can be finalized. Grow - * the list of pointers if necessary, copying only non-NULL pointers to - * the new list. + * Reuse any free slot in the list. + */ + + for (i=0 ; i < recPtr->num ; ++i) { + if (recPtr->list[i] == NULL) { + recPtr->list[i] = objPtr; + return; + } + } + + /* + * Grow the list of pointers if necessary, copying only non-NULL + * pointers to the new list. */ if (recPtr->num >= recPtr->max) { recPtr->max += 8; - newList = (char **)ckalloc(recPtr->max * sizeof(char *)); + newList = ckalloc(recPtr->max * sizeof(void *)); for (i=0,j=0 ; i<recPtr->num ; i++) { if (recPtr->list[i] != NULL) { newList[j++] = recPtr->list[i]; } } if (recPtr->list != NULL) { - ckfree((char *)recPtr->list); + ckfree(recPtr->list); } recPtr->list = newList; recPtr->num = j; } + recPtr->list[recPtr->num] = objPtr; recPtr->num++; } @@ -191,6 +202,7 @@ RememberSyncObject(objPtr, recPtr) * ForgetSyncObject * * Remove a single object from the list. + * Assume master lock is held. * * Results: * None. @@ -202,9 +214,9 @@ RememberSyncObject(objPtr, recPtr) */ static void -ForgetSyncObject(objPtr, recPtr) - char *objPtr; /* Pointer to sync object */ - SyncObjRecord *recPtr; /* Record of sync objects */ +ForgetSyncObject( + void *objPtr, /* Pointer to sync object */ + SyncObjRecord *recPtr) /* Record of sync objects */ { int i; @@ -222,6 +234,7 @@ ForgetSyncObject(objPtr, recPtr) * TclRememberMutex * * Keep a list of mutexes used during finalization. + * Assume master lock is held. * * Results: * None. @@ -233,10 +246,10 @@ ForgetSyncObject(objPtr, recPtr) */ void -TclRememberMutex(mutexPtr) - Tcl_Mutex *mutexPtr; +TclRememberMutex( + Tcl_Mutex *mutexPtr) { - RememberSyncObject((char *)mutexPtr, &mutexRecord); + RememberSyncObject(mutexPtr, &mutexRecord); } /* @@ -257,13 +270,15 @@ TclRememberMutex(mutexPtr) */ void -Tcl_MutexFinalize(mutexPtr) - Tcl_Mutex *mutexPtr; +Tcl_MutexFinalize( + Tcl_Mutex *mutexPtr) { #ifdef TCL_THREADS TclpFinalizeMutex(mutexPtr); #endif - ForgetSyncObject((char *)mutexPtr, &mutexRecord); + TclpMasterLock(); + ForgetSyncObject(mutexPtr, &mutexRecord); + TclpMasterUnlock(); } /* @@ -272,6 +287,7 @@ Tcl_MutexFinalize(mutexPtr) * TclRememberCondition * * Keep a list of condition variables used during finalization. + * Assume master lock is held. * * Results: * None. @@ -283,10 +299,10 @@ Tcl_MutexFinalize(mutexPtr) */ void -TclRememberCondition(condPtr) - Tcl_Condition *condPtr; +TclRememberCondition( + Tcl_Condition *condPtr) { - RememberSyncObject((char *)condPtr, &condRecord); + RememberSyncObject(condPtr, &condRecord); } /* @@ -307,13 +323,15 @@ TclRememberCondition(condPtr) */ void -Tcl_ConditionFinalize(condPtr) - Tcl_Condition *condPtr; +Tcl_ConditionFinalize( + Tcl_Condition *condPtr) { #ifdef TCL_THREADS TclpFinalizeCondition(condPtr); #endif - ForgetSyncObject((char *)condPtr, &condRecord); + TclpMasterLock(); + ForgetSyncObject(condPtr, &condRecord); + TclpMasterUnlock(); } /* @@ -321,8 +339,9 @@ Tcl_ConditionFinalize(condPtr) * * TclFinalizeThreadData -- * - * This function cleans up the thread-local storage. This is called once - * for each thread. + * This function cleans up the thread-local storage. Secondary, it cleans + * thread alloc cache. + * This is called once for each thread before thread exits. * * Results: * None. @@ -334,9 +353,12 @@ Tcl_ConditionFinalize(condPtr) */ void -TclFinalizeThreadData() +TclFinalizeThreadData(void) { - TclpFinalizeThreadDataThread(); + TclFinalizeThreadDataThread(); +#if defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) + TclFinalizeThreadAllocThread(); +#endif } /* @@ -357,34 +379,36 @@ TclFinalizeThreadData() */ void -TclFinalizeSynchronization() +TclFinalizeSynchronization(void) { -#ifdef TCL_THREADS - void* blockPtr; + int i; + void *blockPtr; Tcl_ThreadDataKey *keyPtr; +#ifdef TCL_THREADS Tcl_Mutex *mutexPtr; Tcl_Condition *condPtr; - int i; TclpMasterLock(); +#endif - /* - * If we're running unthreaded, the TSD blocks are simply stored - * inside their thread data keys. Free them here. + /* + * If we're running unthreaded, the TSD blocks are simply stored inside + * their thread data keys. Free them here. */ - for (i=0 ; i<keyRecord.num ; i++) { - keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i]; - blockPtr = (void*) *keyPtr; - ckfree(blockPtr); - } if (keyRecord.list != NULL) { - ckfree((char *)keyRecord.list); + for (i=0 ; i<keyRecord.num ; i++) { + keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; + blockPtr = *keyPtr; + ckfree(blockPtr); + } + ckfree(keyRecord.list); keyRecord.list = NULL; } keyRecord.max = 0; keyRecord.num = 0; +#ifdef TCL_THREADS /* * Call thread storage master cleanup. */ @@ -398,36 +422,28 @@ TclFinalizeSynchronization() } } if (mutexRecord.list != NULL) { - ckfree((char *)mutexRecord.list); + ckfree(mutexRecord.list); mutexRecord.list = NULL; } mutexRecord.max = 0; mutexRecord.num = 0; for (i=0 ; i<condRecord.num ; i++) { - condPtr = (Tcl_Condition *)condRecord.list[i]; + condPtr = (Tcl_Condition *) condRecord.list[i]; if (condPtr != NULL) { TclpFinalizeCondition(condPtr); } } if (condRecord.list != NULL) { - ckfree((char *)condRecord.list); + ckfree(condRecord.list); condRecord.list = NULL; } condRecord.max = 0; condRecord.num = 0; TclpMasterUnlock(); -#else /* TCL_THREADS */ - if (keyRecord.list != NULL) { - ckfree((char *)keyRecord.list); - keyRecord.list = NULL; - } - keyRecord.max = 0; - keyRecord.num = 0; #endif /* TCL_THREADS */ } - /* *---------------------------------------------------------------------- @@ -448,8 +464,8 @@ TclFinalizeSynchronization() */ void -Tcl_ExitThread(status) - int status; +Tcl_ExitThread( + int status) { Tcl_FinalizeThread(); #ifdef TCL_THREADS @@ -479,31 +495,31 @@ Tcl_ExitThread(status) #undef Tcl_ConditionWait 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 */ +Tcl_ConditionWait( + Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */ + Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */ + const Tcl_Time *timePtr) /* Timeout on waiting period */ { } #undef Tcl_ConditionNotify void -Tcl_ConditionNotify(condPtr) - Tcl_Condition *condPtr; +Tcl_ConditionNotify( + Tcl_Condition *condPtr) { } #undef Tcl_MutexLock void -Tcl_MutexLock(mutexPtr) - Tcl_Mutex *mutexPtr; +Tcl_MutexLock( + Tcl_Mutex *mutexPtr) { } #undef Tcl_MutexUnlock void -Tcl_MutexUnlock(mutexPtr) - Tcl_Mutex *mutexPtr; +Tcl_MutexUnlock( + Tcl_Mutex *mutexPtr) { } #endif /* !TCL_THREADS */ |