2 /* adapted by Eric Bohm from Sanjay Kale's pplKalloc */
5 /* An extremely simple implementation of memory allocation
6 that maintains bins for power-of-two sizes.
7 May waste about 33% memory
8 Does not do recombining or buddies.
9 Maintains stats that can be turned off for performance, but seems
16 CpvStaticDeclare(char **, bins);
17 CpvStaticDeclare(int *, binLengths);
18 CpvStaticDeclare(int, maxBin);
19 CpvStaticDeclare(int, numKallocs);
20 CpvStaticDeclare(int, numMallocs);
21 CpvStaticDeclare(int, numOallocs);
22 CpvStaticDeclare(int, numFrees);
23 CpvStaticDeclare(int, numOFrees);
25 /* Each block has a 8 byte header.
26 This contains the pointer to the next block, when
27 the block is in the free list of a particular bin.
28 When it is allocated to the app, the header doesn't
29 have the pointer, but instead has the bin number to which
30 it belongs. I.e. the lg(block size).
33 /* TODO figure out where we should apply CmiMemLock in here */
35 /* Once it all works inline it */
37 void *malloc_nomigrate(size_t size);
38 void free_nomigrate(void *mem);
40 void CmiPoolAllocInit(int numBins)
43 if (CpvInitialized(bins)) return;
44 CpvInitialize(char **, bins);
45 CpvInitialize(int *, binLengths);
46 CpvInitialize(int, maxBin);
47 CpvInitialize(int, numKallocs);
48 CpvInitialize(int, numMallocs);
49 CpvInitialize(int, numOFrees);
50 CpvInitialize(int, numFrees);
52 CpvAccess(bins) = (char **) malloc_nomigrate( numBins*sizeof(char *));
53 CpvAccess(binLengths) = (int *) malloc_nomigrate( numBins*sizeof(int));
54 CpvAccess(maxBin) = numBins -1;
55 for (i=0; i<numBins; i++) CpvAccess(bins)[i] = NULL;
56 for (i=0; i<numBins; i++) CpvAccess(binLengths)[i] = 0;
58 CpvAccess(numKallocs) = CpvAccess(numMallocs) = CpvAccess(numFrees)=CpvAccess(numOFrees) = 0;
61 void * CmiPoolAlloc(unsigned int numBytes)
65 int n=numBytes+CMI_POOL_HEADER_SIZE;
67 /* get 8 more bytes, so I can store a header to the left*/
69 while (n !=0) /* find the bin*/
74 /* even 0 size messages go in bin 1 leaving 0 bin for oversized */
75 if(bin<CpvAccess(maxBin))
78 if(CpvAccess(bins)[bin] != NULL)
80 /* CmiPrintf("p\n"); */
82 CpvAccess(numKallocs)++;
84 /* store some info in the header*/
85 p = CpvAccess(bins)[bin];
86 /*next pointer from the header*/
88 /* this conditional should not be necessary
89 as the header next pointer should contain NULL
90 for us when there is nothing left in the pool */
92 if(--CpvAccess(binLengths)[bin])
93 CpvAccess(bins)[bin] = (char *) *((char **)(p -CMI_POOL_HEADER_SIZE));
94 else /* there is no next */
95 CpvAccess(bins)[bin] = NULL;
97 CpvAccess(bins)[bin] = (char *) *((char **)(p -CMI_POOL_HEADER_SIZE));
102 /* CmiPrintf("np %d\n",bin); */
104 CpvAccess(numMallocs)++;
106 /* Round up the allocation to the max for this bin */
107 p =(char *) malloc_nomigrate(1 << bin) + CMI_POOL_HEADER_SIZE;
112 /* CmiPrintf("u b%d v %d\n",bin,CpvAccess(maxBin)); */
113 /* just revert to malloc for big things and set bin 0 */
115 CpvAccess(numOallocs)++;
117 p = (char *) malloc_nomigrate(numBytes) + CMI_POOL_HEADER_SIZE;
121 header = (CmiInt8 *) (p-CMI_POOL_HEADER_SIZE);
122 CmiAssert(header !=NULL);
123 *header = bin; /* stamp the bin number on the header.*/
127 void CmiPoolFree(void * p)
129 char **header = (char **)( (char*)p - CMI_POOL_HEADER_SIZE);
130 int bin = *(CmiInt8 *)header;
131 /* CmiPrintf("f%d\n",bin,CpvAccess(maxBin)); */
135 CpvAccess(numOFrees)++;
137 free_nomigrate(header);
139 else if(bin<CpvAccess(maxBin))
142 CpvAccess(numFrees)++;
144 /* add to the begining of the list at CpvAccess(bins)[bin]*/
145 *header = CpvAccess(bins)[bin];
146 CpvAccess(bins)[bin] = (char *)p;
148 CpvAccess(binLengths)[bin]++;
152 CmiAbort("CmiPoolFree: Invalid Bin");
155 void CmiPoolAllocStats(void)
158 CmiPrintf("numKallocs: %d\n", CpvAccess(numKallocs));
159 CmiPrintf("numMallocs: %d\n", CpvAccess(numMallocs));
160 CmiPrintf("numOallocs: %d\n", CpvAccess(numOallocs));
161 CmiPrintf("numOFrees: %d\n", CpvAccess(numOFrees));
162 CmiPrintf("numFrees: %d\n", CpvAccess(numFrees));
164 for (i=0; i<=CpvAccess(maxBin); i++)
165 if(CpvAccess(binLengths)[i])
166 CmiPrintf("%d\t", i);
168 for (i=0; i<=CpvAccess(maxBin); i++)
169 if(CpvAccess(binLengths)[i])
170 CmiPrintf("%d\t", CpvAccess(binLengths)[i]);
174 void CmiPoolPrintList(char *p)
176 CmiPrintf("Free list is: -----------\n");
178 char ** header = (char **) p-CMI_POOL_HEADER_SIZE;
179 CmiPrintf("next ptr is %p. ", p);
180 CmiPrintf("header is at: %p, and contains: %p \n", header, *header);
183 CmiPrintf("End of Free list: -----------\n");
188 /* theoretically we should have a pool cleanup function in here */