| ︙ | | | ︙ | |
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#define MAXALLOC (MINALLOC << (NBUCKETS - 1))
/*
* The following structure defines a bucket of blocks with various accounting
* and statistics information.
*/
typedef struct Bucket {
Block *firstPtr; /* First block available */
Block *lastPtr; /* End of block list */
long numFree; /* Number of blocks available */
/* All fields below for accounting only */
size_t numRemoves; /* Number of removes from bucket */
size_t numInserts; /* Number of inserts into bucket */
size_t numLocks; /* Number of locks acquired */
size_t totalAssigned; /* Total space assigned to bucket */
|
|
|
|
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#define MAXALLOC (MINALLOC << (NBUCKETS - 1))
/*
* The following structure defines a bucket of blocks with various accounting
* and statistics information.
*/
typedef struct {
Block *firstPtr; /* First block available */
Block *lastPtr; /* End of block list */
size_t numFree; /* Number of blocks available */
/* All fields below for accounting only */
size_t numRemoves; /* Number of removes from bucket */
size_t numInserts; /* Number of inserts into bucket */
size_t numLocks; /* Number of locks acquired */
size_t totalAssigned; /* Total space assigned to bucket */
|
| ︙ | | | ︙ | |
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
/*
* The following array specifies various per-bucket limits and locks. The
* values are statically initialized to avoid calculating them repeatedly.
*/
static struct {
size_t blockSize; /* Bucket blocksize. */
int maxBlocks; /* Max blocks before move to share. */
int numMove; /* Num blocks to move to share. */
Tcl_Mutex *lockPtr; /* Share bucket lock. */
} bucketInfo[NBUCKETS];
/*
* Static functions defined in this file.
*/
static Cache * GetCache(void);
static void LockBucket(Cache *cachePtr, int bucket);
static void UnlockBucket(Cache *cachePtr, int bucket);
static void PutBlocks(Cache *cachePtr, int bucket, long numMove);
static int GetBlocks(Cache *cachePtr, int bucket);
static Block * Ptr2Block(void *ptr);
static void * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize);
static void MoveObjs(Cache *fromPtr, Cache *toPtr, long numMove);
static void PutObjs(Cache *fromPtr, long numMove);
/*
* Local variables defined in this file and initialized at startup.
*/
static Tcl_Mutex *listLockPtr;
static Tcl_Mutex *objLockPtr;
|
|
|
|
|
|
|
|
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
/*
* The following array specifies various per-bucket limits and locks. The
* values are statically initialized to avoid calculating them repeatedly.
*/
static struct {
size_t blockSize; /* Bucket blocksize. */
size_t maxBlocks; /* Max blocks before move to share. */
size_t numMove; /* Num blocks to move to share. */
Tcl_Mutex *lockPtr; /* Share bucket lock. */
} bucketInfo[NBUCKETS];
/*
* Static functions defined in this file.
*/
static Cache * GetCache(void);
static void LockBucket(Cache *cachePtr, int bucket);
static void UnlockBucket(Cache *cachePtr, int bucket);
static void PutBlocks(Cache *cachePtr, int bucket, size_t numMove);
static int GetBlocks(Cache *cachePtr, int bucket);
static Block * Ptr2Block(void *ptr);
static void * Block2Ptr(Block *blockPtr, int bucket, size_t reqSize);
static void MoveObjs(Cache *fromPtr, Cache *toPtr, size_t numMove);
static void PutObjs(Cache *fromPtr, size_t numMove);
/*
* Local variables defined in this file and initialized at startup.
*/
static Tcl_Mutex *listLockPtr;
static Tcl_Mutex *objLockPtr;
|
| ︙ | | | ︙ | |
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
|
/*
* Get this thread's obj list structure and move or allocate new objs if
* necessary.
*/
if (cachePtr->numObjects == 0) {
long numMove;
Tcl_MutexLock(objLockPtr);
numMove = sharedPtr->numObjects;
if (numMove > 0) {
if (numMove > NOBJALLOC) {
numMove = NOBJALLOC;
}
|
|
|
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
|
/*
* Get this thread's obj list structure and move or allocate new objs if
* necessary.
*/
if (cachePtr->numObjects == 0) {
size_t numMove;
Tcl_MutexLock(objLockPtr);
numMove = sharedPtr->numObjects;
if (numMove > 0) {
if (numMove > NOBJALLOC) {
numMove = NOBJALLOC;
}
|
| ︙ | | | ︙ | |
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
|
if (cachePtr == sharedPtr) {
Tcl_DStringAppendElement(dsPtr, "shared");
} else {
sprintf(buf, "thread%p", cachePtr->owner);
Tcl_DStringAppendElement(dsPtr, buf);
}
for (n = 0; n < NBUCKETS; ++n) {
sprintf(buf, "%" TCL_Z_MODIFIER "u %ld %" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d %" TCL_Z_MODIFIER "d",
bucketInfo[n].blockSize,
cachePtr->buckets[n].numFree,
cachePtr->buckets[n].numRemoves,
cachePtr->buckets[n].numInserts,
cachePtr->buckets[n].totalAssigned,
cachePtr->buckets[n].numLocks);
Tcl_DStringAppendElement(dsPtr, buf);
|
|
>
|
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
|
if (cachePtr == sharedPtr) {
Tcl_DStringAppendElement(dsPtr, "shared");
} else {
sprintf(buf, "thread%p", cachePtr->owner);
Tcl_DStringAppendElement(dsPtr, buf);
}
for (n = 0; n < NBUCKETS; ++n) {
sprintf(buf, "%" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %"
TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u %" TCL_Z_MODIFIER "u",
bucketInfo[n].blockSize,
cachePtr->buckets[n].numFree,
cachePtr->buckets[n].numRemoves,
cachePtr->buckets[n].numInserts,
cachePtr->buckets[n].totalAssigned,
cachePtr->buckets[n].numLocks);
Tcl_DStringAppendElement(dsPtr, buf);
|
| ︙ | | | ︙ | |
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
|
*----------------------------------------------------------------------
*/
static void
MoveObjs(
Cache *fromPtr,
Cache *toPtr,
long numMove)
{
Tcl_Obj *objPtr = fromPtr->firstObjPtr;
Tcl_Obj *fromFirstObjPtr = objPtr;
toPtr->numObjects += numMove;
fromPtr->numObjects -= numMove;
|
|
|
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
|
*----------------------------------------------------------------------
*/
static void
MoveObjs(
Cache *fromPtr,
Cache *toPtr,
size_t numMove)
{
Tcl_Obj *objPtr = fromPtr->firstObjPtr;
Tcl_Obj *fromFirstObjPtr = objPtr;
toPtr->numObjects += numMove;
fromPtr->numObjects -= numMove;
|
| ︙ | | | ︙ | |
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
|
*
*----------------------------------------------------------------------
*/
static void
PutObjs(
Cache *fromPtr,
long numMove)
{
size_t keep = fromPtr->numObjects - numMove;
Tcl_Obj *firstPtr, *lastPtr = NULL;
fromPtr->numObjects = keep;
firstPtr = fromPtr->firstObjPtr;
if (keep == 0) {
|
|
|
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
|
*
*----------------------------------------------------------------------
*/
static void
PutObjs(
Cache *fromPtr,
size_t numMove)
{
size_t keep = fromPtr->numObjects - numMove;
Tcl_Obj *firstPtr, *lastPtr = NULL;
fromPtr->numObjects = keep;
firstPtr = fromPtr->firstObjPtr;
if (keep == 0) {
|
| ︙ | | | ︙ | |
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
|
*----------------------------------------------------------------------
*/
static void *
Block2Ptr(
Block *blockPtr,
int bucket,
unsigned int reqSize)
{
void *ptr;
blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
blockPtr->sourceBucket = bucket;
blockPtr->blockReqSize = reqSize;
ptr = ((void *) (blockPtr + 1));
|
|
|
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
|
*----------------------------------------------------------------------
*/
static void *
Block2Ptr(
Block *blockPtr,
int bucket,
size_t reqSize)
{
void *ptr;
blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
blockPtr->sourceBucket = bucket;
blockPtr->blockReqSize = reqSize;
ptr = ((void *) (blockPtr + 1));
|
| ︙ | | | ︙ | |
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
|
*----------------------------------------------------------------------
*/
static void
PutBlocks(
Cache *cachePtr,
int bucket,
long numMove)
{
/*
* We have numFree. Want to shed numMove. So compute how many
* Blocks to keep.
*/
long keep = cachePtr->buckets[bucket].numFree - numMove;
Block *lastPtr = NULL, *firstPtr;
cachePtr->buckets[bucket].numFree = keep;
firstPtr = cachePtr->buckets[bucket].firstPtr;
if (keep == 0) {
cachePtr->buckets[bucket].firstPtr = NULL;
} else {
|
|
|
|
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
|
*----------------------------------------------------------------------
*/
static void
PutBlocks(
Cache *cachePtr,
int bucket,
size_t numMove)
{
/*
* We have numFree. Want to shed numMove. So compute how many
* Blocks to keep.
*/
size_t keep = cachePtr->buckets[bucket].numFree - numMove;
Block *lastPtr = NULL, *firstPtr;
cachePtr->buckets[bucket].numFree = keep;
firstPtr = cachePtr->buckets[bucket].firstPtr;
if (keep == 0) {
cachePtr->buckets[bucket].firstPtr = NULL;
} else {
|
| ︙ | | | ︙ | |
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
|
static int
GetBlocks(
Cache *cachePtr,
int bucket)
{
Block *blockPtr;
long n;
/*
* First, atttempt to move blocks from the shared cache. Note the
* potentially dirty read of numFree before acquiring the lock which is a
* slight performance enhancement. The value is verified after the lock is
* actually acquired.
*/
|
|
|
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
|
static int
GetBlocks(
Cache *cachePtr,
int bucket)
{
Block *blockPtr;
size_t n;
/*
* First, atttempt to move blocks from the shared cache. Note the
* potentially dirty read of numFree before acquiring the lock which is a
* slight performance enhancement. The value is verified after the lock is
* actually acquired.
*/
|
| ︙ | | | ︙ | |
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
|
* If no blocks could be moved from shared, first look for a larger
* block in this cache to split up.
*/
blockPtr = NULL;
n = NBUCKETS;
size = 0;
while (n-- > bucket + 1) {
if (cachePtr->buckets[n].numFree > 0) {
size = bucketInfo[n].blockSize;
blockPtr = cachePtr->buckets[n].firstPtr;
cachePtr->buckets[n].firstPtr = blockPtr->nextBlock;
cachePtr->buckets[n].numFree--;
break;
}
|
|
|
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
|
* If no blocks could be moved from shared, first look for a larger
* block in this cache to split up.
*/
blockPtr = NULL;
n = NBUCKETS;
size = 0;
while (n-- > (size_t)bucket + 1) {
if (cachePtr->buckets[n].numFree > 0) {
size = bucketInfo[n].blockSize;
blockPtr = cachePtr->buckets[n].firstPtr;
cachePtr->buckets[n].firstPtr = blockPtr->nextBlock;
cachePtr->buckets[n].numFree--;
break;
}
|
| ︙ | | | ︙ | |
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
|
{
unsigned int i;
listLockPtr = TclpNewAllocMutex();
objLockPtr = TclpNewAllocMutex();
for (i = 0; i < NBUCKETS; ++i) {
bucketInfo[i].blockSize = MINALLOC << i;
bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i);
bucketInfo[i].numMove = i < NBUCKETS - 1 ?
1 << (NBUCKETS - 2 - i) : 1;
bucketInfo[i].lockPtr = TclpNewAllocMutex();
}
TclpInitAllocCache();
}
/*
*----------------------------------------------------------------------
|
|
|
|
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
|
{
unsigned int i;
listLockPtr = TclpNewAllocMutex();
objLockPtr = TclpNewAllocMutex();
for (i = 0; i < NBUCKETS; ++i) {
bucketInfo[i].blockSize = MINALLOC << i;
bucketInfo[i].maxBlocks = ((size_t)1) << (NBUCKETS - 1 - i);
bucketInfo[i].numMove = i < NBUCKETS - 1 ?
(size_t)1 << (NBUCKETS - 2 - i) : 1;
bucketInfo[i].lockPtr = TclpNewAllocMutex();
}
TclpInitAllocCache();
}
/*
*----------------------------------------------------------------------
|
| ︙ | | | ︙ | |