--- projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclthread.c 2016/10/14 02:09:58 44 +++ projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclthread.c 2016/11/05 11:07:06 71 @@ -1,592 +1,582 @@ -/* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tcl_base/tclthread.c,v 1.1.1.1 2001/06/13 04:46:27 dtashley Exp $ */ - -/* - * 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. - * - * 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.1.1.1 2001/06/13 04:46:27 dtashley Exp $ - */ - -#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. - * - * These statics are guarded by the mutex in the caller of - * TclRememberThreadData, e.g., TclpThreadDataKeyInit - */ - -typedef struct { - int num; /* Number of objects remembered */ - int max; /* Max size of the array */ - char **list; /* List of pointers */ -} SyncObjRecord; - -static SyncObjRecord keyRecord; -static SyncObjRecord mutexRecord; -static SyncObjRecord condRecord; - -/* - * 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)); - -/* - * 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. - */ -#ifndef TCL_THREADS -#undef Tcl_MutexLock -#undef Tcl_MutexUnlock -#undef Tcl_MutexFinalize -#undef Tcl_ConditionNotify -#undef Tcl_ConditionWait -#undef Tcl_ConditionFinalize -#endif - - -/* - *---------------------------------------------------------------------- - * - * Tcl_GetThreadData -- - * - * 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. - * - *---------------------------------------------------------------------- - */ - -VOID * -Tcl_GetThreadData(keyPtr, size) - Tcl_ThreadDataKey *keyPtr; /* Identifier for the data chunk */ - int size; /* Size of storage block */ -{ - 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); - TclpThreadDataKeySet(keyPtr, result); - } -#else - if (*keyPtr == NULL) { - result = (VOID *)ckalloc((size_t)size); - memset((char *)result, 0, (size_t)size); - *keyPtr = (Tcl_ThreadDataKey)result; - TclRememberDataKey(keyPtr); - } - result = *(VOID **)keyPtr; -#endif - return result; -} - -/* - *---------------------------------------------------------------------- - * - * TclThreadDataKeyGet -- - * - * 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 * -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 */ -{ -#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. - * - * Results: - * None. - * - * Side effects: - * Add to the appropriate list. - * - *---------------------------------------------------------------------- - */ - -static void -RememberSyncObject(objPtr, recPtr) - char *objPtr; /* Pointer to sync object */ - SyncObjRecord *recPtr; /* Record of sync objects */ -{ - char **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. - */ - - if (recPtr->num >= recPtr->max) { - recPtr->max += 8; - newList = (char **)ckalloc(recPtr->max * sizeof(char *)); - for (i=0,j=0 ; inum ; i++) { - if (recPtr->list[i] != NULL) { - newList[j++] = recPtr->list[i]; - } - } - if (recPtr->list != NULL) { - ckfree((char *)recPtr->list); - } - recPtr->list = newList; - recPtr->num = j; - } - recPtr->list[recPtr->num] = objPtr; - recPtr->num++; -} - -/* - *---------------------------------------------------------------------- - * - * ForgetSyncObject - * - * Remove a single object from the list. - * - * Results: - * None. - * - * Side effects: - * Remove from the appropriate list. - * - *---------------------------------------------------------------------- - */ - -static void -ForgetSyncObject(objPtr, recPtr) - char *objPtr; /* Pointer to sync object */ - SyncObjRecord *recPtr; /* Record of sync objects */ -{ - int i; - - for (i=0 ; inum ; i++) { - if (objPtr == recPtr->list[i]) { - recPtr->list[i] = NULL; - return; - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TclRememberMutex - * - * Keep a list of mutexes used during finalization. - * - * Results: - * None. - * - * Side effects: - * Add to the mutex list. - * - *---------------------------------------------------------------------- - */ - -void -TclRememberMutex(mutexPtr) - Tcl_Mutex *mutexPtr; -{ - RememberSyncObject((char *)mutexPtr, &mutexRecord); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_MutexFinalize - * - * Finalize a single mutex and remove it from the - * list of remembered objects. - * - * Results: - * None. - * - * Side effects: - * Remove the mutex from the list. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_MutexFinalize(mutexPtr) - Tcl_Mutex *mutexPtr; -{ -#ifdef TCL_THREADS - TclpFinalizeMutex(mutexPtr); -#endif - ForgetSyncObject((char *)mutexPtr, &mutexRecord); -} - -/* - *---------------------------------------------------------------------- - * - * TclRememberDataKey - * - * Keep a list of thread data keys used during finalization. - * - * 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. - * - * Results: - * None. - * - * Side effects: - * Add to the condition variable list. - * - *---------------------------------------------------------------------- - */ - -void -TclRememberCondition(condPtr) - Tcl_Condition *condPtr; -{ - RememberSyncObject((char *)condPtr, &condRecord); -} - -/* - *---------------------------------------------------------------------- - * - * Tcl_ConditionFinalize - * - * Finalize a single condition variable and remove it from the - * list of remembered objects. - * - * Results: - * None. - * - * Side effects: - * Remove the condition variable from the list. - * - *---------------------------------------------------------------------- - */ - -void -Tcl_ConditionFinalize(condPtr) - Tcl_Condition *condPtr; -{ -#ifdef TCL_THREADS - TclpFinalizeCondition(condPtr); -#endif - ForgetSyncObject((char *)condPtr, &condRecord); -} - -/* - *---------------------------------------------------------------------- - * - * TclFinalizeThreadData -- - * - * 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 -TclFinalizeThreadData() -{ - int i; - Tcl_ThreadDataKey *keyPtr; - - TclpMasterLock(); - for (i=0 ; inum >= recPtr->max) { + recPtr->max += 8; + newList = (char **)ckalloc(recPtr->max * sizeof(char *)); + for (i=0,j=0 ; inum ; i++) { + if (recPtr->list[i] != NULL) { + newList[j++] = recPtr->list[i]; + } + } + if (recPtr->list != NULL) { + ckfree((char *)recPtr->list); + } + recPtr->list = newList; + recPtr->num = j; + } + recPtr->list[recPtr->num] = objPtr; + recPtr->num++; +} + +/* + *---------------------------------------------------------------------- + * + * ForgetSyncObject + * + * Remove a single object from the list. + * + * Results: + * None. + * + * Side effects: + * Remove from the appropriate list. + * + *---------------------------------------------------------------------- + */ + +static void +ForgetSyncObject(objPtr, recPtr) + char *objPtr; /* Pointer to sync object */ + SyncObjRecord *recPtr; /* Record of sync objects */ +{ + int i; + + for (i=0 ; inum ; i++) { + if (objPtr == recPtr->list[i]) { + recPtr->list[i] = NULL; + return; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TclRememberMutex + * + * Keep a list of mutexes used during finalization. + * + * Results: + * None. + * + * Side effects: + * Add to the mutex list. + * + *---------------------------------------------------------------------- + */ + +void +TclRememberMutex(mutexPtr) + Tcl_Mutex *mutexPtr; +{ + RememberSyncObject((char *)mutexPtr, &mutexRecord); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_MutexFinalize + * + * Finalize a single mutex and remove it from the + * list of remembered objects. + * + * Results: + * None. + * + * Side effects: + * Remove the mutex from the list. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_MutexFinalize(mutexPtr) + Tcl_Mutex *mutexPtr; +{ +#ifdef TCL_THREADS + TclpFinalizeMutex(mutexPtr); +#endif + ForgetSyncObject((char *)mutexPtr, &mutexRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclRememberDataKey + * + * Keep a list of thread data keys used during finalization. + * + * 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. + * + * Results: + * None. + * + * Side effects: + * Add to the condition variable list. + * + *---------------------------------------------------------------------- + */ + +void +TclRememberCondition(condPtr) + Tcl_Condition *condPtr; +{ + RememberSyncObject((char *)condPtr, &condRecord); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ConditionFinalize + * + * Finalize a single condition variable and remove it from the + * list of remembered objects. + * + * Results: + * None. + * + * Side effects: + * Remove the condition variable from the list. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_ConditionFinalize(condPtr) + Tcl_Condition *condPtr; +{ +#ifdef TCL_THREADS + TclpFinalizeCondition(condPtr); +#endif + ForgetSyncObject((char *)condPtr, &condRecord); +} + +/* + *---------------------------------------------------------------------- + * + * TclFinalizeThreadData -- + * + * 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 +TclFinalizeThreadData() +{ + int i; + Tcl_ThreadDataKey *keyPtr; + + TclpMasterLock(); + for (i=0 ; i