diff options
Diffstat (limited to 'generic/tclThread.c')
-rw-r--r-- | generic/tclThread.c | 354 |
1 files changed, 143 insertions, 211 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c index c2f769d..8384107 100644 --- a/generic/tclThread.c +++ b/generic/tclThread.c @@ -1,22 +1,21 @@ -/* +/* * tclThread.c -- * - * This file implements Platform independent thread operations. - * Most of the real work is done in the platform dependent files. + * 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. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* - * There are three classes of synchronization objects: - * mutexes, thread data keys, and condition variables. - * The following are used to record the memory used for these - * objects so they can be finalized. + * There are three classes of synchronization objects: mutexes, thread data + * keys, and condition variables. The following are used to record the memory + * used for these objects so they can be finalized. * * These statics are guarded by the mutex in the caller of * TclRememberThreadData, e.g., TclpThreadDataKeyInit @@ -33,19 +32,19 @@ static SyncObjRecord mutexRecord = {0, 0, NULL}; static SyncObjRecord condRecord = {0, 0, NULL}; /* - * Prototypes of functions used only in this file + * 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(char *objPtr, SyncObjRecord *recPtr); +static void RememberSyncObject(char *objPtr, + SyncObjRecord *recPtr); + +/* * Several functions are #defined to nothing in tcl.h if TCL_THREADS is not - * specified. Here we undo that so the procedures are defined in the - * stubs table. + * specified. Here we undo that so the functions are defined in the stubs + * table. */ + #ifndef TCL_THREADS #undef Tcl_MutexLock #undef Tcl_MutexUnlock @@ -54,61 +53,51 @@ static void ForgetSyncObject _ANSI_ARGS_((char *objPtr, #undef Tcl_ConditionWait #undef Tcl_ConditionFinalize #endif - /* *---------------------------------------------------------------------- * * Tcl_GetThreadData -- * - * This procedure allocates and initializes a chunk of thread - * local storage. + * This function allocates and initializes a chunk of thread local + * storage. * * Results: * A thread-specific pointer to the data structure. * * Side effects: - * Will allocate memory the first time this thread calls for - * this chunk of storage. + * Will allocate memory the first time this thread calls for this chunk + * of storage. * *---------------------------------------------------------------------- */ -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 - - /* - * See if this is the first thread to init this key. - */ - - if (*keyPtr == NULL) { - TclpThreadDataKeyInit(keyPtr); - } - /* * Initialize the key for this thread. */ - result = TclpThreadDataKeyGet(keyPtr); + if (result == NULL) { - result = (VOID *)ckalloc((size_t)size); - memset(result, 0, (size_t)size); + result = ckalloc((size_t) size); + memset(result, 0, (size_t) size); TclpThreadDataKeySet(keyPtr, result); } -#else +#else /* TCL_THREADS */ if (*keyPtr == NULL) { - result = (VOID *)ckalloc((size_t)size); - memset((char *)result, 0, (size_t)size); + result = ckalloc((size_t) size); + memset(result, 0, (size_t) size); *keyPtr = (Tcl_ThreadDataKey)result; - TclRememberDataKey(keyPtr); + RememberSyncObject((char *) keyPtr, &keyRecord); } - result = *(VOID **)keyPtr; -#endif + result = * (void **) keyPtr; +#endif /* TCL_THREADS */ return result; } @@ -117,11 +106,11 @@ Tcl_GetThreadData(keyPtr, size) * * TclThreadDataKeyGet -- * - * This procedure returns a pointer to a block of thread local storage. + * This function 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. + * 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. @@ -129,61 +118,27 @@ Tcl_GetThreadData(keyPtr, size) *---------------------------------------------------------------------- */ -VOID * -TclThreadDataKeyGet(keyPtr) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ -{ -#ifdef TCL_THREADS - return (VOID *)TclpThreadDataKeyGet(keyPtr); -#else - char *result = *(char **)keyPtr; - return (VOID *)result; -#endif /* TCL_THREADS */ -} - - -/* - *---------------------------------------------------------------------- - * - * TclThreadDataKeySet -- - * - * This procedure sets a thread local storage pointer. - * - * Results: - * None. - * - * Side effects: - * The assigned value will be returned by TclpThreadDataKeyGet. - * - *---------------------------------------------------------------------- - */ - -void -TclThreadDataKeySet(keyPtr, data) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, - * really (pthread_key_t **) */ - VOID *data; /* Thread local storage */ +void * +TclThreadDataKeyGet( + Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really + * (pthread_key_t **) */ { #ifdef TCL_THREADS - if (*keyPtr == NULL) { - TclpThreadDataKeyInit(keyPtr); - } - TclpThreadDataKeySet(keyPtr, data); -#else - *keyPtr = (Tcl_ThreadDataKey)data; + return TclpThreadDataKeyGet(keyPtr); +#else /* TCL_THREADS */ + char *result = *(char **) keyPtr; + return result; #endif /* TCL_THREADS */ } - /* *---------------------------------------------------------------------- * * RememberSyncObject * - * Keep a list of (mutexes/condition variable/data key) - * used during finalization. + * Keep a list of (mutexes/condition variable/data key) used during + * finalization. * * Assume master lock is held. * @@ -197,22 +152,23 @@ TclThreadDataKeySet(keyPtr, data) */ static void -RememberSyncObject(objPtr, recPtr) - char *objPtr; /* Pointer to sync object */ - SyncObjRecord *recPtr; /* Record of sync objects */ +RememberSyncObject( + char *objPtr, /* Pointer to sync object */ + SyncObjRecord *recPtr) /* Record of sync objects */ { char **newList; int i, j; + /* - * Reuse any free slot in the 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; - } + } } /* @@ -222,14 +178,14 @@ RememberSyncObject(objPtr, recPtr) if (recPtr->num >= recPtr->max) { recPtr->max += 8; - newList = (char **)ckalloc(recPtr->max * sizeof(char *)); - for (i=0, j=0 ; i < recPtr->num ; i++) { - if (recPtr->list[i] != NULL) { + newList = (char **) ckalloc(recPtr->max * sizeof(char *)); + 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((char *) recPtr->list); } recPtr->list = newList; recPtr->num = j; @@ -244,7 +200,7 @@ RememberSyncObject(objPtr, recPtr) * * ForgetSyncObject * - * Remove a single object from the list. + * Remove a single object from the list. * Assume master lock is held. * * Results: @@ -257,9 +213,9 @@ RememberSyncObject(objPtr, recPtr) */ static void -ForgetSyncObject(objPtr, recPtr) - char *objPtr; /* Pointer to sync object */ - SyncObjRecord *recPtr; /* Record of sync objects */ +ForgetSyncObject( + char *objPtr, /* Pointer to sync object */ + SyncObjRecord *recPtr) /* Record of sync objects */ { int i; @@ -276,7 +232,7 @@ ForgetSyncObject(objPtr, recPtr) * * TclRememberMutex * - * Keep a list of mutexes used during finalization. + * Keep a list of mutexes used during finalization. * Assume master lock is held. * * Results: @@ -289,8 +245,8 @@ ForgetSyncObject(objPtr, recPtr) */ void -TclRememberMutex(mutexPtr) - Tcl_Mutex *mutexPtr; +TclRememberMutex( + Tcl_Mutex *mutexPtr) { RememberSyncObject((char *)mutexPtr, &mutexRecord); } @@ -298,10 +254,10 @@ TclRememberMutex(mutexPtr) /* *---------------------------------------------------------------------- * - * Tcl_MutexFinalize + * Tcl_MutexFinalize -- * - * Finalize a single mutex and remove it from the - * list of remembered objects. + * Finalize a single mutex and remove it from the list of remembered + * objects. * * Results: * None. @@ -313,47 +269,23 @@ TclRememberMutex(mutexPtr) */ void -Tcl_MutexFinalize(mutexPtr) - Tcl_Mutex *mutexPtr; +Tcl_MutexFinalize( + Tcl_Mutex *mutexPtr) { #ifdef TCL_THREADS TclpFinalizeMutex(mutexPtr); #endif TclpMasterLock(); - ForgetSyncObject((char *)mutexPtr, &mutexRecord); + ForgetSyncObject((char *) mutexPtr, &mutexRecord); TclpMasterUnlock(); } /* *---------------------------------------------------------------------- * - * TclRememberDataKey - * - * Keep a list of thread data keys used during finalization. - * Assume master lock is held. - * - * Results: - * None. - * - * Side effects: - * Add to the key list. - * - *---------------------------------------------------------------------- - */ - -void -TclRememberDataKey(keyPtr) - Tcl_ThreadDataKey *keyPtr; -{ - RememberSyncObject((char *)keyPtr, &keyRecord); -} - -/* - *---------------------------------------------------------------------- - * * TclRememberCondition * - * Keep a list of condition variables used during finalization. + * Keep a list of condition variables used during finalization. * Assume master lock is held. * * Results: @@ -366,19 +298,19 @@ TclRememberDataKey(keyPtr) */ void -TclRememberCondition(condPtr) - Tcl_Condition *condPtr; +TclRememberCondition( + Tcl_Condition *condPtr) { - RememberSyncObject((char *)condPtr, &condRecord); + RememberSyncObject((char *) condPtr, &condRecord); } /* *---------------------------------------------------------------------- * - * Tcl_ConditionFinalize + * Tcl_ConditionFinalize -- * - * Finalize a single condition variable and remove it from the - * list of remembered objects. + * Finalize a single condition variable and remove it from the list of + * remembered objects. * * Results: * None. @@ -390,14 +322,14 @@ TclRememberCondition(condPtr) */ void -Tcl_ConditionFinalize(condPtr) - Tcl_Condition *condPtr; +Tcl_ConditionFinalize( + Tcl_Condition *condPtr) { #ifdef TCL_THREADS TclpFinalizeCondition(condPtr); #endif TclpMasterLock(); - ForgetSyncObject((char *)condPtr, &condRecord); + ForgetSyncObject((char *) condPtr, &condRecord); TclpMasterUnlock(); } @@ -406,8 +338,8 @@ Tcl_ConditionFinalize(condPtr) * * TclFinalizeThreadData -- * - * This procedure cleans up the thread-local storage. This is - * called once for each thread. + * This function cleans up the thread-local storage. This is called once + * for each thread. * * Results: * None. @@ -419,24 +351,9 @@ Tcl_ConditionFinalize(condPtr) */ void -TclFinalizeThreadData() +TclFinalizeThreadData(void) { - int i; - Tcl_ThreadDataKey *keyPtr; - - TclpMasterLock(); - for (i=0 ; i<keyRecord.num ; i++) { - keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; -#ifdef TCL_THREADS - TclpFinalizeThreadData(keyPtr); -#else - if (*keyPtr != NULL) { - ckfree((char *)*keyPtr); - *keyPtr = NULL; - } -#endif - } - TclpMasterUnlock(); + TclpFinalizeThreadDataThread(); } /* @@ -444,8 +361,8 @@ TclFinalizeThreadData() * * TclFinalizeSynchronization -- * - * This procedure cleans up all synchronization objects: - * mutexes, condition variables, and thread-local storage. + * This function cleans up all synchronization objects: mutexes, + * condition variables, and thread-local storage. * * Results: * None. @@ -457,25 +374,41 @@ TclFinalizeThreadData() */ void -TclFinalizeSynchronization() +TclFinalizeSynchronization(void) { -#ifdef TCL_THREADS + int i; + void *blockPtr; Tcl_ThreadDataKey *keyPtr; +#ifdef TCL_THREADS Tcl_Mutex *mutexPtr; Tcl_Condition *condPtr; - int i; TclpMasterLock(); - for (i=0 ; i<keyRecord.num ; i++) { - keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i]; - TclpFinalizeThreadDataKey(keyPtr); - } +#endif + + /* + * If we're running unthreaded, the TSD blocks are simply stored inside + * their thread data keys. Free them here. + */ + if (keyRecord.list != NULL) { - ckfree((char *)keyRecord.list); + for (i=0 ; i<keyRecord.num ; i++) { + keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; + blockPtr = (void *) *keyPtr; + ckfree(blockPtr); + } + ckfree((char *) keyRecord.list); keyRecord.list = NULL; } keyRecord.max = 0; keyRecord.num = 0; + +#ifdef TCL_THREADS + /* + * Call thread storage master cleanup. + */ + + TclFinalizeThreadStorage(); for (i=0 ; i<mutexRecord.num ; i++) { mutexPtr = (Tcl_Mutex *)mutexRecord.list[i]; @@ -484,45 +417,37 @@ TclFinalizeSynchronization() } } if (mutexRecord.list != NULL) { - ckfree((char *)mutexRecord.list); + ckfree((char *) 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((char *) condRecord.list); condRecord.list = NULL; } condRecord.max = 0; condRecord.num = 0; TclpMasterUnlock(); -#else - if (keyRecord.list != NULL) { - ckfree((char *)keyRecord.list); - keyRecord.list = NULL; - } - keyRecord.max = 0; - keyRecord.num = 0; -#endif +#endif /* TCL_THREADS */ } - /* *---------------------------------------------------------------------- * * Tcl_ExitThread -- * - * This procedure is called to terminate the current thread. - * This should be used by extensions that create threads with - * additional interpreters in them. + * This function is called to terminate the current thread. This should + * be used by extensions that create threads with additional interpreters + * in them. * * Results: * None. @@ -534,8 +459,8 @@ TclFinalizeSynchronization() */ void -Tcl_ExitThread(status) - int status; +Tcl_ExitThread( + int status) { Tcl_FinalizeThread(); #ifdef TCL_THREADS @@ -550,10 +475,9 @@ Tcl_ExitThread(status) * * Tcl_ConditionWait, et al. -- * - * These noop procedures are provided so the stub table does - * not have to be conditionalized for threads. The real - * implementations of these functions live in the platform - * specific files. + * These noop functions are provided so the stub table does not have to + * be conditionalized for threads. The real implementations of these + * functions live in the platform specific files. * * Results: * None. @@ -566,31 +490,39 @@ 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 **) */ + 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 +#endif /* !TCL_THREADS */ + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |