diff options
Diffstat (limited to 'generic/tclThread.c')
| -rw-r--r-- | generic/tclThread.c | 354 |
1 files changed, 211 insertions, 143 deletions
diff --git a/generic/tclThread.c b/generic/tclThread.c index 8384107..c2f769d 100644 --- a/generic/tclThread.c +++ b/generic/tclThread.c @@ -1,21 +1,22 @@ -/* +/* * 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 @@ -32,19 +33,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 functions are defined in the stubs - * table. + * specified. Here we undo that so the procedures are defined in the + * stubs table. */ - #ifndef TCL_THREADS #undef Tcl_MutexLock #undef Tcl_MutexUnlock @@ -53,51 +54,61 @@ static void RememberSyncObject(char *objPtr, #undef Tcl_ConditionWait #undef Tcl_ConditionFinalize #endif + /* *---------------------------------------------------------------------- * * Tcl_GetThreadData -- * - * This function allocates and initializes a chunk of thread local - * storage. + * This procedure 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( - Tcl_ThreadDataKey *keyPtr, /* Identifier for the data chunk */ - int size) /* Size of storage block */ +VOID * +Tcl_GetThreadData(keyPtr, size) + 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); + result = TclpThreadDataKeyGet(keyPtr); if (result == NULL) { - result = ckalloc((size_t) size); - memset(result, 0, (size_t) size); + result = (VOID *)ckalloc((size_t)size); + memset(result, 0, (size_t)size); TclpThreadDataKeySet(keyPtr, result); } -#else /* TCL_THREADS */ +#else if (*keyPtr == NULL) { - result = ckalloc((size_t) size); - memset(result, 0, (size_t) size); + result = (VOID *)ckalloc((size_t)size); + memset((char *)result, 0, (size_t)size); *keyPtr = (Tcl_ThreadDataKey)result; - RememberSyncObject((char *) keyPtr, &keyRecord); + TclRememberDataKey(keyPtr); } - result = * (void **) keyPtr; -#endif /* TCL_THREADS */ + result = *(VOID **)keyPtr; +#endif return result; } @@ -106,11 +117,11 @@ Tcl_GetThreadData( * * TclThreadDataKeyGet -- * - * This function returns a pointer to a block of thread local storage. + * 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. + * 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. @@ -118,27 +129,61 @@ Tcl_GetThreadData( *---------------------------------------------------------------------- */ -void * -TclThreadDataKeyGet( - Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk, really - * (pthread_key_t **) */ +VOID * +TclThreadDataKeyGet(keyPtr) + Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk, + * really (pthread_key_t **) */ { #ifdef TCL_THREADS - return TclpThreadDataKeyGet(keyPtr); -#else /* TCL_THREADS */ - char *result = *(char **) keyPtr; - return result; + 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 */ +{ +#ifdef TCL_THREADS + if (*keyPtr == NULL) { + TclpThreadDataKeyInit(keyPtr); + } + TclpThreadDataKeySet(keyPtr, data); +#else + *keyPtr = (Tcl_ThreadDataKey)data; #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. * @@ -152,23 +197,22 @@ TclThreadDataKeyGet( */ static void -RememberSyncObject( - char *objPtr, /* Pointer to sync object */ - SyncObjRecord *recPtr) /* Record of sync objects */ +RememberSyncObject(objPtr, recPtr) + 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; - } + } } /* @@ -178,14 +222,14 @@ RememberSyncObject( 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; @@ -200,7 +244,7 @@ RememberSyncObject( * * ForgetSyncObject * - * Remove a single object from the list. + * Remove a single object from the list. * Assume master lock is held. * * Results: @@ -213,9 +257,9 @@ RememberSyncObject( */ static void -ForgetSyncObject( - char *objPtr, /* Pointer to sync object */ - SyncObjRecord *recPtr) /* Record of sync objects */ +ForgetSyncObject(objPtr, recPtr) + char *objPtr; /* Pointer to sync object */ + SyncObjRecord *recPtr; /* Record of sync objects */ { int i; @@ -232,7 +276,7 @@ ForgetSyncObject( * * TclRememberMutex * - * Keep a list of mutexes used during finalization. + * Keep a list of mutexes used during finalization. * Assume master lock is held. * * Results: @@ -245,8 +289,8 @@ ForgetSyncObject( */ void -TclRememberMutex( - Tcl_Mutex *mutexPtr) +TclRememberMutex(mutexPtr) + Tcl_Mutex *mutexPtr; { RememberSyncObject((char *)mutexPtr, &mutexRecord); } @@ -254,10 +298,10 @@ TclRememberMutex( /* *---------------------------------------------------------------------- * - * 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. @@ -269,23 +313,47 @@ TclRememberMutex( */ void -Tcl_MutexFinalize( - Tcl_Mutex *mutexPtr) +Tcl_MutexFinalize(mutexPtr) + 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: @@ -298,19 +366,19 @@ Tcl_MutexFinalize( */ void -TclRememberCondition( - Tcl_Condition *condPtr) +TclRememberCondition(condPtr) + 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. @@ -322,14 +390,14 @@ TclRememberCondition( */ void -Tcl_ConditionFinalize( - Tcl_Condition *condPtr) +Tcl_ConditionFinalize(condPtr) + Tcl_Condition *condPtr; { #ifdef TCL_THREADS TclpFinalizeCondition(condPtr); #endif TclpMasterLock(); - ForgetSyncObject((char *) condPtr, &condRecord); + ForgetSyncObject((char *)condPtr, &condRecord); TclpMasterUnlock(); } @@ -338,8 +406,8 @@ Tcl_ConditionFinalize( * * TclFinalizeThreadData -- * - * This function cleans up the thread-local storage. This is called once - * for each thread. + * This procedure cleans up the thread-local storage. This is + * called once for each thread. * * Results: * None. @@ -351,9 +419,24 @@ Tcl_ConditionFinalize( */ void -TclFinalizeThreadData(void) +TclFinalizeThreadData() { - TclpFinalizeThreadDataThread(); + 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(); } /* @@ -361,8 +444,8 @@ TclFinalizeThreadData(void) * * TclFinalizeSynchronization -- * - * This function cleans up all synchronization objects: mutexes, - * condition variables, and thread-local storage. + * This procedure cleans up all synchronization objects: + * mutexes, condition variables, and thread-local storage. * * Results: * None. @@ -374,41 +457,25 @@ TclFinalizeThreadData(void) */ void -TclFinalizeSynchronization(void) +TclFinalizeSynchronization() { - int i; - void *blockPtr; - Tcl_ThreadDataKey *keyPtr; #ifdef TCL_THREADS + Tcl_ThreadDataKey *keyPtr; 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. - */ - + for (i=0 ; i<keyRecord.num ; i++) { + keyPtr = (Tcl_ThreadDataKey *)keyRecord.list[i]; + TclpFinalizeThreadDataKey(keyPtr); + } if (keyRecord.list != NULL) { - for (i=0 ; i<keyRecord.num ; i++) { - keyPtr = (Tcl_ThreadDataKey *) keyRecord.list[i]; - blockPtr = (void *) *keyPtr; - ckfree(blockPtr); - } - ckfree((char *) keyRecord.list); + 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]; @@ -417,37 +484,45 @@ TclFinalizeSynchronization(void) } } 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(); -#endif /* TCL_THREADS */ +#else + if (keyRecord.list != NULL) { + ckfree((char *)keyRecord.list); + keyRecord.list = NULL; + } + keyRecord.max = 0; + keyRecord.num = 0; +#endif } + /* *---------------------------------------------------------------------- * * Tcl_ExitThread -- * - * This function is called to terminate the current thread. This should - * be used by extensions that create threads with additional interpreters - * in them. + * This procedure is called to terminate the current thread. + * This should be used by extensions that create threads with + * additional interpreters in them. * * Results: * None. @@ -459,8 +534,8 @@ TclFinalizeSynchronization(void) */ void -Tcl_ExitThread( - int status) +Tcl_ExitThread(status) + int status; { Tcl_FinalizeThread(); #ifdef TCL_THREADS @@ -475,9 +550,10 @@ Tcl_ExitThread( * * Tcl_ConditionWait, et al. -- * - * 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. + * 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. * * Results: * None. @@ -490,39 +566,31 @@ Tcl_ExitThread( #undef Tcl_ConditionWait void -Tcl_ConditionWait( - Tcl_Condition *condPtr, /* Really (pthread_cond_t **) */ - Tcl_Mutex *mutexPtr, /* Really (pthread_mutex_t **) */ - Tcl_Time *timePtr) /* Timeout on waiting period */ +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 */ { } #undef Tcl_ConditionNotify void -Tcl_ConditionNotify( - Tcl_Condition *condPtr) +Tcl_ConditionNotify(condPtr) + Tcl_Condition *condPtr; { } #undef Tcl_MutexLock void -Tcl_MutexLock( - Tcl_Mutex *mutexPtr) +Tcl_MutexLock(mutexPtr) + Tcl_Mutex *mutexPtr; { } #undef Tcl_MutexUnlock void -Tcl_MutexUnlock( - Tcl_Mutex *mutexPtr) +Tcl_MutexUnlock(mutexPtr) + Tcl_Mutex *mutexPtr; { } -#endif /* !TCL_THREADS */ - -/* - * Local Variables: - * mode: c - * c-basic-offset: 4 - * fill-column: 78 - * End: - */ +#endif |
