doc: Add serial to list of ci file reserved words
[charm.git] / src / conv-core / cmipool.c
1
2 /* adapted by Eric Bohm from Sanjay Kale's pplKalloc */
3
4
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.
11 */
12
13
14 #include "cmipool.h"
15
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);
24
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).
31 */
32
33 /* TODO wrap ifndef CMK_OPTIMIZE around the stats collection bits */
34
35 /* TODO figure out where we should apply CmiMemLock in here */
36
37 /* Once it all works inline it */
38
39 extern void *malloc_nomigrate(size_t size);
40 extern void free_nomigrate(void *mem);
41
42 void CmiPoolAllocInit(int numBins)
43 {
44   int i;
45   if (CpvInitialized(bins)) return;
46   CpvInitialize(char **, bins);
47   CpvInitialize(int *, binLengths);
48   CpvInitialize(int, maxBin);
49   CpvInitialize(int, numKallocs);
50   CpvInitialize(int, numMallocs);
51   CpvInitialize(int, numOFrees);
52   CpvInitialize(int, numFrees);
53
54   CpvAccess(bins) = (char **) malloc_nomigrate(  numBins*sizeof(char *));
55   CpvAccess(binLengths) = (int *) malloc_nomigrate(  numBins*sizeof(int));
56   CpvAccess(maxBin) = numBins -1;
57   for (i=0; i<numBins; i++) CpvAccess(bins)[i] = NULL;
58   for (i=0; i<numBins; i++) CpvAccess(binLengths)[i] = 0;
59
60   CpvAccess(numKallocs) =  CpvAccess(numMallocs) =  CpvAccess(numFrees)=CpvAccess(numOFrees) = 0;
61 }
62
63 void * CmiPoolAlloc(unsigned int numBytes)
64 {
65   char *p;
66   int bin=0;
67   int n=numBytes+CMI_POOL_HEADER_SIZE;
68   CmiInt8 *header;
69   /* get 8 more bytes, so I can store a header to the left*/
70   numBytes = n;
71   while (n !=0) /* find the bin*/
72     {     
73       n = n >> 1;
74       bin++;
75     }
76   /* even 0 size messages go in bin 1 leaving 0 bin for oversized */
77   if(bin<CpvAccess(maxBin))
78     {
79       CmiAssert(bin>0);
80       if(CpvAccess(bins)[bin] != NULL) 
81         {
82           /* CmiPrintf("p\n"); */
83 #if CMK_WITH_STATS
84           CpvAccess(numKallocs)++;
85 #endif
86           /* store some info in the header*/
87           p = CpvAccess(bins)[bin];
88           /*next pointer from the header*/
89
90           /* this conditional should not be necessary
91              as the header next pointer should contain NULL
92              for us when there is nothing left in the pool */
93 #if CMK_WITH_STATS
94           if(--CpvAccess(binLengths)[bin])
95               CpvAccess(bins)[bin] = (char *) *((char **)(p -CMI_POOL_HEADER_SIZE)); 
96           else  /* there is no next */
97               CpvAccess(bins)[bin] = NULL;
98 #else
99           CpvAccess(bins)[bin] = (char *) *((char **)(p -CMI_POOL_HEADER_SIZE)); 
100 #endif
101         }
102       else
103         {
104           /* CmiPrintf("np %d\n",bin); */
105 #if CMK_WITH_STATS
106           CpvAccess(numMallocs)++;
107 #endif
108           /* Round up the allocation to the max for this bin */
109            p =(char *) malloc_nomigrate(1 << bin) + CMI_POOL_HEADER_SIZE;
110         }
111     }
112   else
113     {
114       /*  CmiPrintf("u b%d v %d\n",bin,CpvAccess(maxBin));  */
115       /* just revert to malloc for big things and set bin 0 */
116 #if CMK_WITH_STATS
117           CpvAccess(numOallocs)++;
118 #endif
119       p = (char *) malloc_nomigrate(numBytes) + CMI_POOL_HEADER_SIZE;
120       bin=0; 
121
122     }
123   header = (CmiInt8 *) (p-CMI_POOL_HEADER_SIZE);
124   CmiAssert(header !=NULL);
125   *header = bin; /* stamp the bin number on the header.*/
126   return p;
127 }
128
129 void CmiPoolFree(void * p) 
130 {
131   char **header = (char **)( (char*)p - CMI_POOL_HEADER_SIZE);
132   int bin = *(CmiInt8 *)header;
133   /*  CmiPrintf("f%d\n",bin,CpvAccess(maxBin));  */
134   if(bin==0)
135     {
136 #if CMK_WITH_STATS
137       CpvAccess(numOFrees)++;
138 #endif
139       free_nomigrate(header);
140     }
141   else if(bin<CpvAccess(maxBin))
142     {
143 #if CMK_WITH_STATS
144       CpvAccess(numFrees)++;
145 #endif
146       /* add to the begining of the list at CpvAccess(bins)[bin]*/
147       *header =  CpvAccess(bins)[bin]; 
148       CpvAccess(bins)[bin] = p;
149 #if CMK_WITH_STATS
150       CpvAccess(binLengths)[bin]++;
151 #endif
152     }
153   else
154     CmiAbort("CmiPoolFree: Invalid Bin");
155 }
156
157 void  CmiPoolAllocStats()
158 {
159   int i;
160   CmiPrintf("numKallocs: %d\n", CpvAccess(numKallocs));
161   CmiPrintf("numMallocs: %d\n", CpvAccess(numMallocs));
162   CmiPrintf("numOallocs: %d\n", CpvAccess(numOallocs));
163   CmiPrintf("numOFrees: %d\n", CpvAccess(numOFrees));
164   CmiPrintf("numFrees: %d\n", CpvAccess(numFrees));
165   CmiPrintf("Bin:");
166   for (i=0; i<=CpvAccess(maxBin); i++)
167     if(CpvAccess(binLengths)[i])
168       CmiPrintf("%d\t", i);
169   CmiPrintf("\nVal:");
170   for (i=0; i<=CpvAccess(maxBin); i++)
171     if(CpvAccess(binLengths)[i])
172       CmiPrintf("%d\t", CpvAccess(binLengths)[i]);
173   CmiPrintf("\n");
174 }
175
176 void CmiPoolPrintList(char *p)
177 {
178   CmiPrintf("Free list is: -----------\n");
179   while (p != 0) {
180     char ** header = (char **) p-CMI_POOL_HEADER_SIZE;
181     CmiPrintf("next ptr is %p. ", p);
182     CmiPrintf("header is at: %p, and contains: %p \n", header, *header);
183     p = *header;
184   }
185   CmiPrintf("End of Free list: -----------\n");
186  
187 }
188
189
190 /* theoretically we should have a pool cleanup function in here */