Clean up C linkage specific to the C++ migration
[charm.git] / src / conv-core / cmipool.C
blob0633d8bab638b20ffb4eda0778c96f23c7cfbb47
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
10    plenty fast.
14 #include "cmipool.h"
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)
42   int i;
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)
63   char *p;
64   int bin=0;
65   int n=numBytes+CMI_POOL_HEADER_SIZE;
66   CmiInt8 *header;
67   /* get 8 more bytes, so I can store a header to the left*/
68   numBytes = n;
69   while (n !=0) /* find the bin*/
70     {     
71       n = n >> 1;
72       bin++;
73     }
74   /* even 0 size messages go in bin 1 leaving 0 bin for oversized */
75   if(bin<CpvAccess(maxBin))
76     {
77       CmiAssert(bin>0);
78       if(CpvAccess(bins)[bin] != NULL) 
79         {
80           /* CmiPrintf("p\n"); */
81 #if CMK_WITH_STATS
82           CpvAccess(numKallocs)++;
83 #endif
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 */
91 #if CMK_WITH_STATS
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;
96 #else
97           CpvAccess(bins)[bin] = (char *) *((char **)(p -CMI_POOL_HEADER_SIZE)); 
98 #endif
99         }
100       else
101         {
102           /* CmiPrintf("np %d\n",bin); */
103 #if CMK_WITH_STATS
104           CpvAccess(numMallocs)++;
105 #endif
106           /* Round up the allocation to the max for this bin */
107            p =(char *) malloc_nomigrate(1 << bin) + CMI_POOL_HEADER_SIZE;
108         }
109     }
110   else
111     {
112       /*  CmiPrintf("u b%d v %d\n",bin,CpvAccess(maxBin));  */
113       /* just revert to malloc for big things and set bin 0 */
114 #if CMK_WITH_STATS
115           CpvAccess(numOallocs)++;
116 #endif
117       p = (char *) malloc_nomigrate(numBytes) + CMI_POOL_HEADER_SIZE;
118       bin=0; 
120     }
121   header = (CmiInt8 *) (p-CMI_POOL_HEADER_SIZE);
122   CmiAssert(header !=NULL);
123   *header = bin; /* stamp the bin number on the header.*/
124   return p;
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));  */
132   if(bin==0)
133     {
134 #if CMK_WITH_STATS
135       CpvAccess(numOFrees)++;
136 #endif
137       free_nomigrate(header);
138     }
139   else if(bin<CpvAccess(maxBin))
140     {
141 #if CMK_WITH_STATS
142       CpvAccess(numFrees)++;
143 #endif
144       /* add to the begining of the list at CpvAccess(bins)[bin]*/
145       *header =  CpvAccess(bins)[bin]; 
146       CpvAccess(bins)[bin] = (char *)p;
147 #if CMK_WITH_STATS
148       CpvAccess(binLengths)[bin]++;
149 #endif
150     }
151   else
152     CmiAbort("CmiPoolFree: Invalid Bin");
155 void  CmiPoolAllocStats(void)
157   int i;
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));
163   CmiPrintf("Bin:");
164   for (i=0; i<=CpvAccess(maxBin); i++)
165     if(CpvAccess(binLengths)[i])
166       CmiPrintf("%d\t", i);
167   CmiPrintf("\nVal:");
168   for (i=0; i<=CpvAccess(maxBin); i++)
169     if(CpvAccess(binLengths)[i])
170       CmiPrintf("%d\t", CpvAccess(binLengths)[i]);
171   CmiPrintf("\n");
174 void CmiPoolPrintList(char *p)
176   CmiPrintf("Free list is: -----------\n");
177   while (p != 0) {
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);
181     p = *header;
182   }
183   CmiPrintf("End of Free list: -----------\n");
188 /* theoretically we should have a pool cleanup function in here */