summaryrefslogtreecommitdiffstats
path: root/generic/tclThreadAlloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclThreadAlloc.c')
-rw-r--r--generic/tclThreadAlloc.c148
1 files changed, 82 insertions, 66 deletions
diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c
index f754bde..106e908 100644
--- a/generic/tclThreadAlloc.c
+++ b/generic/tclThreadAlloc.c
@@ -35,9 +35,7 @@
*/
#define NOBJALLOC 800
-
-/* Actual definition moved to tclInt.h */
-#define NOBJHIGH ALLOC_NOBJHIGH
+#define NOBJHIGH 1200
/*
* The following union stores accounting information for each block including
@@ -97,16 +95,14 @@ typedef struct Bucket {
/*
* The following structure defines a cache of buckets and objs, of which there
- * will be (at most) one per thread. Any changes need to be reflected in the
- * struct AllocCache defined in tclInt.h, possibly also in the initialisation
- * code in Tcl_CreateInterp().
+ * will be (at most) one per thread.
*/
typedef struct Cache {
struct Cache *nextPtr; /* Linked list of cache entries */
Tcl_ThreadId owner; /* Which thread's cache is this? */
Tcl_Obj *firstObjPtr; /* List of free objects for thread */
- size_t numObjects; /* Number of objects for thread */
+ int numObjects; /* Number of objects for thread */
int totalAssigned; /* Total space assigned to thread */
Bucket buckets[NBUCKETS]; /* The buckets for this thread */
} Cache;
@@ -133,7 +129,7 @@ static void UnlockBucket(Cache *cachePtr, int bucket);
static void PutBlocks(Cache *cachePtr, int bucket, int numMove);
static int GetBlocks(Cache *cachePtr, int bucket);
static Block * Ptr2Block(char *ptr);
-static char * Block2Ptr(Block *blockPtr, int bucket, size_t reqSize);
+static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize);
static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove);
/*
@@ -145,26 +141,6 @@ static Tcl_Mutex *objLockPtr;
static Cache sharedCache;
static Cache *sharedPtr = &sharedCache;
static Cache *firstCachePtr = &sharedCache;
-
-#if defined(HAVE_FAST_TSD)
-static __thread Cache *tcachePtr;
-
-# define GETCACHE(cachePtr) \
- do { \
- if (!tcachePtr) { \
- tcachePtr = GetCache(); \
- } \
- (cachePtr) = tcachePtr; \
- } while (0)
-#else
-# define GETCACHE(cachePtr) \
- do { \
- (cachePtr) = TclpGetAllocCache(); \
- if ((cachePtr) == NULL) { \
- (cachePtr) = GetCache(); \
- } \
- } while (0)
-#endif
/*
*----------------------------------------------------------------------
@@ -308,7 +284,7 @@ TclFreeAllocCache(
char *
TclpAlloc(
- size_t reqSize)
+ unsigned int reqSize)
{
Cache *cachePtr;
Block *blockPtr;
@@ -328,7 +304,10 @@ TclpAlloc(
}
#endif
- GETCACHE(cachePtr);
+ cachePtr = TclpGetAllocCache();
+ if (cachePtr == NULL) {
+ cachePtr = GetCache();
+ }
/*
* Increment the requested size to include room for the Block structure.
@@ -340,7 +319,7 @@ TclpAlloc(
blockPtr = NULL;
size = reqSize + sizeof(Block);
#if RCHECK
- size++;
+ ++size;
#endif
if (size > MAXALLOC) {
bucket = NBUCKETS;
@@ -351,13 +330,13 @@ TclpAlloc(
} else {
bucket = 0;
while (bucketInfo[bucket].blockSize < size) {
- bucket++;
+ ++bucket;
}
if (cachePtr->buckets[bucket].numFree || GetBlocks(cachePtr, bucket)) {
blockPtr = cachePtr->buckets[bucket].firstPtr;
cachePtr->buckets[bucket].firstPtr = blockPtr->nextBlock;
- cachePtr->buckets[bucket].numFree--;
- cachePtr->buckets[bucket].numRemoves++;
+ --cachePtr->buckets[bucket].numFree;
+ ++cachePtr->buckets[bucket].numRemoves;
cachePtr->buckets[bucket].totalAssigned += reqSize;
}
}
@@ -395,7 +374,10 @@ TclpFree(
return;
}
- GETCACHE(cachePtr);
+ cachePtr = TclpGetAllocCache();
+ if (cachePtr == NULL) {
+ cachePtr = GetCache();
+ }
/*
* Get the block back from the user pointer and call system free directly
@@ -414,8 +396,8 @@ TclpFree(
cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize;
blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr;
cachePtr->buckets[bucket].firstPtr = blockPtr;
- cachePtr->buckets[bucket].numFree++;
- cachePtr->buckets[bucket].numInserts++;
+ ++cachePtr->buckets[bucket].numFree;
+ ++cachePtr->buckets[bucket].numInserts;
if (cachePtr != sharedPtr &&
cachePtr->buckets[bucket].numFree > bucketInfo[bucket].maxBlocks) {
@@ -442,7 +424,7 @@ TclpFree(
char *
TclpRealloc(
char *ptr,
- size_t reqSize)
+ unsigned int reqSize)
{
Cache *cachePtr;
Block *blockPtr;
@@ -467,7 +449,10 @@ TclpRealloc(
}
#endif
- GETCACHE(cachePtr);
+ cachePtr = TclpGetAllocCache();
+ if (cachePtr == NULL) {
+ cachePtr = GetCache();
+ }
/*
* If the block is not a system block and fits in place, simply return the
@@ -478,7 +463,7 @@ TclpRealloc(
blockPtr = Ptr2Block(ptr);
size = reqSize + sizeof(Block);
#if RCHECK
- size++;
+ ++size;
#endif
bucket = blockPtr->sourceBucket;
if (bucket != NBUCKETS) {
@@ -531,20 +516,18 @@ TclpRealloc(
* May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's if
* list is empty.
*
- * Note:
- * If this code is updated, the changes need to be reflected in the macro
- * TclAllocObjStorageEx() defined in tclInt.h
- *
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclThreadAllocObj(void)
{
- register Cache *cachePtr;
+ register Cache *cachePtr = TclpGetAllocCache();
register Tcl_Obj *objPtr;
- GETCACHE(cachePtr);
+ if (cachePtr == NULL) {
+ cachePtr = GetCache();
+ }
/*
* Get this thread's obj list structure and move or allocate new objs if
@@ -573,7 +556,7 @@ TclThreadAllocObj(void)
}
while (--numMove >= 0) {
objPtr = &newObjsPtr[numMove];
- objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr;
}
}
@@ -584,8 +567,8 @@ TclThreadAllocObj(void)
*/
objPtr = cachePtr->firstObjPtr;
- cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
- cachePtr->numObjects--;
+ cachePtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ --cachePtr->numObjects;
return objPtr;
}
@@ -602,10 +585,6 @@ TclThreadAllocObj(void)
* Side effects:
* May move free Tcl_Obj's to shared list upon hitting high water mark.
*
- * Note:
- * If this code is updated, the changes need to be reflected in the macro
- * TclAllocObjStorageEx() defined in tclInt.h
- *
*----------------------------------------------------------------------
*/
@@ -613,17 +592,19 @@ void
TclThreadFreeObj(
Tcl_Obj *objPtr)
{
- Cache *cachePtr;
+ Cache *cachePtr = TclpGetAllocCache();
- GETCACHE(cachePtr);
+ if (cachePtr == NULL) {
+ cachePtr = GetCache();
+ }
/*
* Get this thread's list and push on the free Tcl_Obj.
*/
- objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = cachePtr->firstObjPtr;
cachePtr->firstObjPtr = objPtr;
- cachePtr->numObjects++;
+ ++cachePtr->numObjects;
/*
* If the number of free objects has exceeded the high water mark, move
@@ -722,16 +703,16 @@ MoveObjs(
*/
while (--numMove) {
- objPtr = objPtr->internalRep.otherValuePtr;
+ objPtr = objPtr->internalRep.twoPtrValue.ptr1;
}
- fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr;
+ fromPtr->firstObjPtr = objPtr->internalRep.twoPtrValue.ptr1;
/*
* Move all objects as a block - they are already linked to each other, we
* just have to update the first and last.
*/
- objPtr->internalRep.otherValuePtr = toPtr->firstObjPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = toPtr->firstObjPtr;
toPtr->firstObjPtr = fromFirstObjPtr;
}
@@ -755,7 +736,7 @@ static char *
Block2Ptr(
Block *blockPtr,
int bucket,
- size_t reqSize)
+ unsigned int reqSize)
{
register void *ptr;
@@ -812,9 +793,17 @@ LockBucket(
Cache *cachePtr,
int bucket)
{
+#if 0
+ if (Tcl_MutexTryLock(bucketInfo[bucket].lockPtr) != TCL_OK) {
+ Tcl_MutexLock(bucketInfo[bucket].lockPtr);
+ ++cachePtr->buckets[bucket].numWaits;
+ ++sharedPtr->buckets[bucket].numWaits;
+ }
+#else
Tcl_MutexLock(bucketInfo[bucket].lockPtr);
- cachePtr->buckets[bucket].numLocks++;
- sharedPtr->buckets[bucket].numLocks++;
+#endif
+ ++cachePtr->buckets[bucket].numLocks;
+ ++sharedPtr->buckets[bucket].numLocks;
}
static void
@@ -953,7 +942,7 @@ GetBlocks(
size = bucketInfo[n].blockSize;
blockPtr = cachePtr->buckets[n].firstPtr;
cachePtr->buckets[n].firstPtr = blockPtr->nextBlock;
- cachePtr->buckets[n].numFree--;
+ --cachePtr->buckets[n].numFree;
break;
}
}
@@ -1010,8 +999,8 @@ TclFinalizeThreadAlloc(void)
unsigned int i;
for (i = 0; i < NBUCKETS; ++i) {
- TclpFreeAllocMutex(bucketInfo[i].lockPtr);
- bucketInfo[i].lockPtr = NULL;
+ TclpFreeAllocMutex(bucketInfo[i].lockPtr);
+ bucketInfo[i].lockPtr = NULL;
}
TclpFreeAllocMutex(objLockPtr);
@@ -1023,6 +1012,33 @@ TclFinalizeThreadAlloc(void)
TclpFreeAllocCache(NULL);
}
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclFinalizeThreadAllocThread --
+ *
+ * This procedure is used to destroy single thread private resources used
+ * in this file.
+ * Called in TclpFinalizeThreadData when a thread exits (Tcl_FinalizeThread).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclFinalizeThreadAllocThread(void)
+{
+ Cache *cachePtr = TclpGetAllocCache();
+ if (cachePtr != NULL) {
+ TclpFreeAllocCache(cachePtr);
+ }
+}
+
#else /* !(TCL_THREADS && USE_THREAD_ALLOC) */
/*
*----------------------------------------------------------------------