summaryrefslogtreecommitdiffstats
path: root/tcl8.6/generic/tclThreadStorage.c
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-12-21 22:47:21 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-12-21 22:47:21 (GMT)
commit5514e37335c012cc70f5b9aee3cedfe3d57f583f (patch)
tree4ba7d8aad13735e52f59bdce7ca5ba3151ebd7e3 /tcl8.6/generic/tclThreadStorage.c
parent768f87f613cc9789fcf8073018fa02178c8c91df (diff)
downloadblt-5514e37335c012cc70f5b9aee3cedfe3d57f583f.zip
blt-5514e37335c012cc70f5b9aee3cedfe3d57f583f.tar.gz
blt-5514e37335c012cc70f5b9aee3cedfe3d57f583f.tar.bz2
undo subtree
Diffstat (limited to 'tcl8.6/generic/tclThreadStorage.c')
-rw-r--r--tcl8.6/generic/tclThreadStorage.c373
1 files changed, 0 insertions, 373 deletions
diff --git a/tcl8.6/generic/tclThreadStorage.c b/tcl8.6/generic/tclThreadStorage.c
deleted file mode 100644
index 755a461..0000000
--- a/tcl8.6/generic/tclThreadStorage.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * tclThreadStorage.c --
- *
- * This file implements platform independent thread storage operations to
- * work around system limits on the number of thread-specific variables.
- *
- * Copyright (c) 2003-2004 by Joe Mistachkin
- * 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.
- */
-
-#include "tclInt.h"
-
-#ifdef TCL_THREADS
-#include <signal.h>
-
-/*
- * IMPLEMENTATION NOTES:
- *
- * The primary idea is that we create one platform-specific TSD slot, and use
- * it for storing a table pointer. Each Tcl_ThreadDataKey has an offset into
- * the table of TSD values. We don't use more than 1 platform-specific TSD
- * slot, because there is a hard limit on the number of TSD slots. Valid key
- * offsets are greater than 0; 0 is for the initialized Tcl_ThreadDataKey.
- */
-
-/*
- * The master collection of information about TSDs. This is shared across the
- * whole process, and includes the mutex used to protect it.
- */
-
-static struct TSDMaster {
- void *key; /* Key into the system TSD structure. The
- * collection of Tcl TSD values for a
- * particular thread will hang off the
- * back-end of this. */
- sig_atomic_t counter; /* The number of different Tcl TSDs used
- * across *all* threads. This is a strictly
- * increasing value. */
- Tcl_Mutex mutex; /* Protection for the rest of this structure,
- * which holds per-process data. */
-} tsdMaster = { NULL, 0, NULL };
-
-/*
- * The type of the data held per thread in a system TSD.
- */
-
-typedef struct TSDTable {
- ClientData *tablePtr; /* The table of Tcl TSDs. */
- sig_atomic_t allocated; /* The size of the table in the current
- * thread. */
-} TSDTable;
-
-/*
- * The actual type of Tcl_ThreadDataKey.
- */
-
-typedef union TSDUnion {
- volatile sig_atomic_t offset;
- /* The type is really an offset into the
- * thread-local table of TSDs, which is this
- * field. */
- void *ptr; /* For alignment purposes only. Not actually
- * accessed through this. */
-} TSDUnion;
-
-/*
- * Forward declarations of functions in this file.
- */
-
-static TSDTable * TSDTableCreate(void);
-static void TSDTableDelete(TSDTable *tsdTablePtr);
-static void TSDTableGrow(TSDTable *tsdTablePtr,
- sig_atomic_t atLeast);
-
-/*
- * Allocator and deallocator for a TSDTable structure.
- */
-
-static TSDTable *
-TSDTableCreate(void)
-{
- TSDTable *tsdTablePtr;
- sig_atomic_t i;
-
- tsdTablePtr = TclpSysAlloc(sizeof(TSDTable), 0);
- if (tsdTablePtr == NULL) {
- Tcl_Panic("unable to allocate TSDTable");
- }
-
- tsdTablePtr->allocated = 8;
- tsdTablePtr->tablePtr =
- TclpSysAlloc(sizeof(void *) * tsdTablePtr->allocated, 0);
- if (tsdTablePtr->tablePtr == NULL) {
- Tcl_Panic("unable to allocate TSDTable");
- }
-
- for (i = 0; i < tsdTablePtr->allocated; ++i) {
- tsdTablePtr->tablePtr[i] = NULL;
- }
-
- return tsdTablePtr;
-}
-
-static void
-TSDTableDelete(
- TSDTable *tsdTablePtr)
-{
- sig_atomic_t i;
-
- for (i=0 ; i<tsdTablePtr->allocated ; i++) {
- if (tsdTablePtr->tablePtr[i] != NULL) {
- /*
- * These values were allocated in Tcl_GetThreadData in tclThread.c
- * and must now be deallocated or they will leak.
- */
-
- ckfree(tsdTablePtr->tablePtr[i]);
- }
- }
-
- TclpSysFree(tsdTablePtr->tablePtr);
- TclpSysFree(tsdTablePtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TSDTableGrow --
- *
- * This procedure makes the passed TSDTable grow to fit the atLeast
- * value.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The table is enlarged.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-TSDTableGrow(
- TSDTable *tsdTablePtr,
- sig_atomic_t atLeast)
-{
- sig_atomic_t newAllocated = tsdTablePtr->allocated * 2;
- ClientData *newTablePtr;
- sig_atomic_t i;
-
- if (newAllocated <= atLeast) {
- newAllocated = atLeast + 10;
- }
-
- newTablePtr = TclpSysRealloc(tsdTablePtr->tablePtr,
- sizeof(ClientData) * newAllocated);
- if (newTablePtr == NULL) {
- Tcl_Panic("unable to reallocate TSDTable");
- }
-
- for (i = tsdTablePtr->allocated; i < newAllocated; ++i) {
- newTablePtr[i] = NULL;
- }
-
- tsdTablePtr->allocated = newAllocated;
- tsdTablePtr->tablePtr = newTablePtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclThreadStorageKeyGet --
- *
- * This procedure gets the value associated with the passed key.
- *
- * Results:
- * A pointer value associated with the Tcl_ThreadDataKey or NULL.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-void *
-TclThreadStorageKeyGet(
- Tcl_ThreadDataKey *dataKeyPtr)
-{
- TSDTable *tsdTablePtr = TclpThreadGetMasterTSD(tsdMaster.key);
- ClientData resultPtr = NULL;
- TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr;
- sig_atomic_t offset = keyPtr->offset;
-
- if ((tsdTablePtr != NULL) && (offset > 0)
- && (offset < tsdTablePtr->allocated)) {
- resultPtr = tsdTablePtr->tablePtr[offset];
- }
- return resultPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclThreadStorageKeySet --
- *
- * This procedure set an association of value with the key passed. The
- * associated value may be retrieved with TclThreadDataKeyGet().
- *
- * Results:
- * None.
- *
- * Side effects:
- * The thread-specific table may be created or reallocated.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclThreadStorageKeySet(
- Tcl_ThreadDataKey *dataKeyPtr,
- void *value)
-{
- TSDTable *tsdTablePtr = TclpThreadGetMasterTSD(tsdMaster.key);
- TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr;
-
- if (tsdTablePtr == NULL) {
- tsdTablePtr = TSDTableCreate();
- TclpThreadSetMasterTSD(tsdMaster.key, tsdTablePtr);
- }
-
- /*
- * Get the lock while we check if this TSD is new or not. Note that this
- * is the only place where Tcl_ThreadDataKey values are set. We use a
- * double-checked lock to try to avoid having to grab this lock a lot,
- * since it is on quite a few critical paths and will only get set once in
- * each location.
- */
-
- if (keyPtr->offset == 0) {
- Tcl_MutexLock(&tsdMaster.mutex);
- if (keyPtr->offset == 0) {
- /*
- * The Tcl_ThreadDataKey hasn't been used yet. Make a new one.
- */
-
- keyPtr->offset = ++tsdMaster.counter;
- }
- Tcl_MutexUnlock(&tsdMaster.mutex);
- }
-
- /*
- * Check if this is the first time this Tcl_ThreadDataKey has been used
- * with the current thread. Note that we don't need to hold a lock when
- * doing this, as we are *definitely* the only point accessing this
- * tsdTablePtr right now; it's thread-local.
- */
-
- if (keyPtr->offset >= tsdTablePtr->allocated) {
- TSDTableGrow(tsdTablePtr, keyPtr->offset);
- }
-
- /*
- * Set the value in the Tcl thread-local variable.
- */
-
- tsdTablePtr->tablePtr[keyPtr->offset] = value;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclFinalizeThreadDataThread --
- *
- * This procedure finalizes the data for a single thread.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The TSDTable is deleted/freed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclFinalizeThreadDataThread(void)
-{
- TSDTable *tsdTablePtr = TclpThreadGetMasterTSD(tsdMaster.key);
-
- if (tsdTablePtr != NULL) {
- TSDTableDelete(tsdTablePtr);
- TclpThreadSetMasterTSD(tsdMaster.key, NULL);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclInitializeThreadStorage --
- *
- * This procedure initializes the TSD subsystem with per-platform code.
- * This should be called before any Tcl threads are created.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Allocates a system TSD.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInitThreadStorage(void)
-{
- tsdMaster.key = TclpThreadCreateKey();
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclFinalizeThreadStorage --
- *
- * This procedure cleans up the thread storage data key for all threads.
- * IMPORTANT: All Tcl threads must be finalized before calling this!
- *
- * Results:
- * None.
- *
- * Side effects:
- * Releases the thread data key.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclFinalizeThreadStorage(void)
-{
- TclpThreadDeleteKey(tsdMaster.key);
- tsdMaster.key = NULL;
-}
-
-#else /* !TCL_THREADS */
-/*
- * Stub functions for non-threaded builds
- */
-
-void
-TclInitThreadStorage(void)
-{
-}
-
-void
-TclFinalizeThreadDataThread(void)
-{
-}
-
-void
-TclFinalizeThreadStorage(void)
-{
-}
-#endif /* TCL_THREADS */
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */