• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*---------------------------------------------------------------------------*
2  *  pmemblock.c  *
3  *                                                                           *
4  *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5  *                                                                           *
6  *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7  *  you may not use this file except in compliance with the License.         *
8  *                                                                           *
9  *  You may obtain a copy of the License at                                  *
10  *      http://www.apache.org/licenses/LICENSE-2.0                           *
11  *                                                                           *
12  *  Unless required by applicable law or agreed to in writing, software      *
13  *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15  *  See the License for the specific language governing permissions and      *
16  *  limitations under the License.                                           *
17  *                                                                           *
18  *---------------------------------------------------------------------------*/
19 
20 
21 
22 #include "pmemory.h"
23 #include "ptypes.h"
24 
25 #if PORTABLE_MEM_MGR == PORTABLE_PSOS_BLOCK_SCHEME_MEM_MGR
26 
27 #ifdef PSOSIM
28 #define PSOS
29 #endif
30 
31 #ifdef PSOS
32 #include <stdlib.h>
33 #include <psos.h>
34 #endif
35 
36 #ifdef __cplusplus
37 extern "C"
38 {
39 #endif
40 
41   /* Data *****************************************************************/
42 
43 #define NUM_POOL_BINS 32
44 #define NUM_POOL_SLOTS  8
45 
46   typedef struct memory_pools
47   {
48     uint32   currentNumberOfPools;
49 
50     struct pool_info
51     {
52       unsigned long poolId;
53       void*   pMemory;
54       unsigned long size;
55     }
56     poolInfo[NUM_POOL_SLOTS];
57 
58   }
59   MEMORY_POOL;
60 
61   static MEMORY_POOL memoryPool[NUM_POOL_BINS];
62 
63 #define NUM_TRACKING_BINS NUM_POOL_BINS
64 
65   /* Object tracking variables */
66   static struct tracking_struct
67   {
68     uint32 sCurrentAllocationSize;
69     uint32 sMaximumAllocationSize;
70     uint32 sTotalAllocationSize;
71 
72     uint32  sCurrentAllocRealSize;
73     uint32  sMaximumAllocRealSize;
74     uint32  sTotalAllocRealSize;
75 
76     uint32 sCurrentAllocationNumber;
77     uint32 sMaximumAllocationNumber;
78     uint32 sTotalAllocationNumber;
79 
80     uint32 sCurrentAllocationNumberArray[NUM_TRACKING_BINS];
81     uint32 sMaximumAllocationNumberArray[NUM_TRACKING_BINS];
82     uint32 sTotalAllocationNumberArray[NUM_TRACKING_BINS];
83 
84     uint32 sCurrentAllocationSizeArray[NUM_TRACKING_BINS];
85     uint32 sMaximumAllocationSizeArray[NUM_TRACKING_BINS];
86     uint32 sTotalAllocationSizeArray[NUM_TRACKING_BINS];
87   }
88   gMemoryTracking;
89 
90 
91   /* Functions *********************************************************/
92 
findBin(size_t size)93   static uint32 findBin(size_t size)
94   {
95     int i, bin;
96     for (i = 0, bin = 1; i < NUM_TRACKING_BINS; i++, bin <<= 1)
97     {
98       if ((int)size <= bin)
99         return i;
100     }
101 
102     return 0;
103   }
104 
105 
MemoryTrackingInit(void)106   static void MemoryTrackingInit(void)
107   {
108     int i;
109     /* Initialization of object tracking variables */
110     gMemoryTracking.sCurrentAllocationSize = 0;
111     gMemoryTracking.sMaximumAllocationSize = 0;
112     gMemoryTracking.sTotalAllocationSize = 0;
113 
114     gMemoryTracking.sCurrentAllocationNumber = 0;
115     gMemoryTracking.sMaximumAllocationNumber = 0;
116     gMemoryTracking.sTotalAllocationNumber = 0;
117 
118     gMemoryTracking.sCurrentAllocRealSize = 0;
119     gMemoryTracking.sMaximumAllocRealSize = 0;
120     gMemoryTracking.sTotalAllocRealSize = 0;
121 
122     for (i = 0; i < NUM_TRACKING_BINS; i++)
123     {
124       gMemoryTracking.sCurrentAllocationNumberArray[i] = 0;
125       gMemoryTracking.sMaximumAllocationNumberArray[i] = 0;
126       gMemoryTracking.sTotalAllocationNumberArray[i] = 0;
127 
128       gMemoryTracking.sCurrentAllocationSizeArray[i] = 0;
129       gMemoryTracking.sMaximumAllocationSizeArray[i] = 0;
130       gMemoryTracking.sTotalAllocationSizeArray[i] = 0;
131     }
132   }
133 
134 
MemoryTrackingAdd(size_t size)135   static void MemoryTrackingAdd(size_t size)
136   {
137     /* Memory tracking code */
138     uint32 bin = findBin(size);
139     uint32 binsize = 1 << bin;
140     uint32 dummy;
141 
142     /* for breakpoint setting */
143 #ifdef PSOSIM
144     if (bin == 0)
145       dummy = 0;
146     if (bin == 1)
147       dummy = 0;
148     if (bin == 2)
149       dummy = 0;
150     if (bin == 3)
151       dummy = 0;
152     if (bin == 4)
153       dummy = 0;
154     if (bin == 5)
155       dummy = 0;
156     if (bin == 6)
157       dummy = 0;
158     if (bin == 7)
159       dummy = 0;
160     if (bin == 8)
161       dummy = 0;
162     if (bin == 9)
163       dummy = 0;
164     if (bin == 10)
165       dummy = 0;
166     if (bin == 11)
167       dummy = 0;
168     if (bin == 12)
169       dummy = 0;
170     if (bin == 13)
171       dummy = 0;
172     if (bin == 14)
173       dummy = 0;
174     if (bin == 15)
175       dummy = 0;
176     if (bin == 16)
177       dummy = 0;
178     if (bin == 17)
179       dummy = 0;
180     if (bin == 18)
181       dummy = 0;
182     if (bin == 19)
183       dummy = 0;
184     if (bin == 20)
185       dummy = 0;
186     if (bin == 21)
187       dummy = 0;
188     if (bin >  21)
189       dummy = 0;
190 #endif /* PSOSIM */
191 
192     gMemoryTracking.sCurrentAllocationSize += size;
193     gMemoryTracking.sTotalAllocationSize += size;
194     if (gMemoryTracking.sCurrentAllocationSize > gMemoryTracking.sMaximumAllocationSize)
195       gMemoryTracking.sMaximumAllocationSize = gMemoryTracking.sCurrentAllocationSize;
196 
197     gMemoryTracking.sCurrentAllocRealSize += binsize;
198     gMemoryTracking.sTotalAllocRealSize += binsize;
199     if (gMemoryTracking.sCurrentAllocRealSize > gMemoryTracking.sMaximumAllocRealSize)
200       gMemoryTracking.sMaximumAllocRealSize = gMemoryTracking.sCurrentAllocRealSize;
201 
202     gMemoryTracking.sCurrentAllocationNumber++;
203     gMemoryTracking.sTotalAllocationNumber++;
204     if (gMemoryTracking.sCurrentAllocationNumber > gMemoryTracking.sMaximumAllocationNumber)
205       gMemoryTracking.sMaximumAllocationNumber = gMemoryTracking.sCurrentAllocationNumber;
206 
207     gMemoryTracking.sCurrentAllocationSizeArray[bin] += size;
208     gMemoryTracking.sTotalAllocationSizeArray[bin] += size;
209     if (gMemoryTracking.sCurrentAllocationSizeArray[bin] > gMemoryTracking.sMaximumAllocationSizeArray[bin])
210       gMemoryTracking.sMaximumAllocationSizeArray[bin] = gMemoryTracking.sCurrentAllocationSizeArray[bin];
211 
212     gMemoryTracking.sCurrentAllocationNumberArray[bin]++;
213     gMemoryTracking.sTotalAllocationNumberArray[bin]++;
214     if (gMemoryTracking.sCurrentAllocationNumberArray[bin] > gMemoryTracking.sMaximumAllocationNumberArray[bin])
215       gMemoryTracking.sMaximumAllocationNumberArray[bin] = gMemoryTracking.sCurrentAllocationNumberArray[bin];
216   }
217 
218 
MemoryTrackingDelete(unsigned long size)219   static void MemoryTrackingDelete(unsigned long size)
220   {
221     /* Memory tracking code */
222     uint32 bin = findBin(size);
223     uint32 binsize = 1 << bin;
224 
225     gMemoryTracking.sCurrentAllocationSize -= size;
226     gMemoryTracking.sCurrentAllocationNumber--;
227 
228     gMemoryTracking.sCurrentAllocationSizeArray[bin] -= size;
229     gMemoryTracking.sCurrentAllocationNumberArray[bin]--;
230 
231     gMemoryTracking.sCurrentAllocRealSize -= binsize;
232   }
233 
234 
InitPools(void)235   static void InitPools(void)
236   {
237     int i, j;
238     for (i = 0; i < NUM_POOL_BINS; i++)
239     {
240       memoryPool[i].currentNumberOfPools = 0;
241 
242       for (j = 0; j < NUM_POOL_SLOTS; j++)
243       {
244         memoryPool[i].poolInfo[j].poolId = 0;
245         memoryPool[i].poolInfo[j].pMemory = NULL;
246         memoryPool[i].poolInfo[j].size = 0;
247       }
248     }
249   }
250 
251 
TermPools(void)252   static void TermPools(void)
253   {
254     int i, j;
255     /* For some reason, deleting the region then freeing the memory causes a failure */
256     /* TODO: Figure out why??? */
257     for (i = 1; i < NUM_POOL_BINS; i++)
258     {
259       for (j = 0; j < (int)memoryPool[i].currentNumberOfPools; j++)
260       {
261         if (memoryPool[i].poolInfo[j].pMemory != NULL)
262         {
263           unsigned long retval = pt_delete(memoryPool[i].poolInfo[j].poolId);
264           PORT_ASSERT(retval == 0);
265 
266           PORT_ASSERT_GOOD_WRITE_POINTER(memoryPool[i].poolInfo[j].pMemory);
267           free(memoryPool[i].poolInfo[j].pMemory);
268 
269           memoryPool[i].poolInfo[j].poolId = 0;
270           memoryPool[i].poolInfo[j].pMemory = NULL;
271           memoryPool[i].poolInfo[j].size = 0;
272         }
273       }
274 
275       memoryPool[i].currentNumberOfPools = 0;
276     }
277   }
278 
279 
280 #define PARTITION_CONTROL_BLOCK_SIZE 0x400
281 
CreatePool(uint32 whichPool,uint32 poolSize)282   static BOOL CreatePool(uint32 whichPool, uint32 poolSize)
283   {
284     static uint32 poolNumber = 0;
285 
286     void*   pMemory = NULL;
287     unsigned long poolId, unused;
288 
289     uint32 currentNumberOfPools = memoryPool[whichPool].currentNumberOfPools;
290 
291     PORT_ASSERT((whichPool >= 0) && (whichPool < NUM_POOL_BINS));
292 
293     if (currentNumberOfPools == NUM_POOL_SLOTS)
294       return FALSE;
295 
296 
297     if (whichPool < 2)
298     {
299       /* Invalid partition size */
300       return FALSE;
301     }
302     else
303     {
304       char name[5];
305       unsigned long retval;
306 
307       pMemory = malloc(poolSize * (1 << whichPool) + PARTITION_CONTROL_BLOCK_SIZE);
308       PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
309 
310       /* No memory protection */
311       if (pMemory == NULL)
312       {
313         /* No memory left in system */
314         return FALSE;
315       }
316 
317 
318       sprintf(name, "DP%02d", poolNumber);
319 
320       retval = pt_create(name, pMemory, 0, poolSize * (1 << whichPool) + PARTITION_CONTROL_BLOCK_SIZE,
321                          1 << whichPool, PT_LOCAL | PT_DEL, &poolId, &unused);
322       if (retval != 0)
323       {
324         /* Unable to create a pSOS partition */
325         return FALSE;
326       }
327     }
328 
329     memoryPool[whichPool].poolInfo[currentNumberOfPools].poolId = poolId;
330     memoryPool[whichPool].poolInfo[currentNumberOfPools].pMemory = pMemory;
331     memoryPool[whichPool].poolInfo[currentNumberOfPools].size = poolSize;
332     memoryPool[whichPool].currentNumberOfPools++;
333 
334     poolNumber++;
335 
336     return TRUE;
337   }
338 
AddPool(uint32 whichPool,uint32 poolSize)339   static BOOL AddPool(uint32 whichPool, uint32 poolSize)
340   {
341     if (memoryPool[whichPool].poolInfo[0].pMemory == NULL)
342       return FALSE;
343 
344     return CreatePool(whichPool, poolSize);
345   }
346 
AllocateFromPsos(uint32 whichPool,uint32 poolIndex,uint32 size)347   static void* AllocateFromPsos(uint32 whichPool, uint32 poolIndex, uint32 size)
348   {
349     uint32 retval;
350     void* pMemory;
351 
352     PORT_ASSERT(memoryPool[whichPool].poolInfo[poolIndex].poolId);
353 
354     retval = pt_getbuf(memoryPool[whichPool].poolInfo[poolIndex].poolId, &pMemory);
355 
356     /* If we got memory, then return */
357     if (retval == 0)
358     {
359       PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
360       *((unsigned long *)pMemory) = (whichPool << 27) + (poolIndex << 24) + size;
361       return (unsigned long *)pMemory + 1;
362     }
363     else
364       return NULL;
365   }
366 
SearchPoolsForMemory(uint32 whichPool,uint32 size)367   static void* SearchPoolsForMemory(uint32 whichPool, uint32 size)
368   {
369     void*   pMemory;
370     uint32    poolIndex;
371     /* Get memory from main region */
372     if (whichPool == 0)
373     {
374       pMemory = malloc(size);
375 
376       /* No memory protection */
377       if (pMemory == NULL)
378       {
379         /* No memory left in system */
380         return NULL;
381       }
382 
383       PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
384       *((unsigned long *)pMemory) = (whichPool << 27) + size;
385       return (unsigned long *)pMemory + 1;
386     }
387 
388     /* Allocate memory from the first available bin (partition) */
389     for (poolIndex = 0; poolIndex < memoryPool[whichPool].currentNumberOfPools; poolIndex++)
390     {
391       pMemory = AllocateFromPsos(whichPool, poolIndex, size);
392       if (pMemory != NULL)
393         return pMemory;
394     }
395 
396     /* Made it here because we ran out of memory in the pool, so try to add more pools */
397     if (AddPool(whichPool, memoryPool[whichPool].poolInfo[0].size >> 1) == FALSE)
398     {
399       /* All pools of this size have been consumed */
400       return NULL;
401     }
402 
403     /* Allocate memory from newly created pool */
404     pMemory = AllocateFromPsos(whichPool, memoryPool[whichPool].currentNumberOfPools - 1, size);
405     if (pMemory != NULL)
406       return pMemory;
407 
408     /* If we can't allocate from the newly created pool, then we have problems */
409     /* No memory protection */
410 
411     /* No memory left in system */
412     return NULL;
413   }
414 
PortMemBlockAllocateFromPool(uint32 size)415   void* PortMemBlockAllocateFromPool(uint32 size)
416   {
417     void*   pMemory = NULL;
418     int    poolIndex;
419     BOOL foundPool = FALSE;
420     uint32 whichPool;
421 
422     PORT_ASSERT((size & 0xff000000) == 0);
423 
424     size += 4;
425     whichPool = findBin(size); /* Add 4 so I can store info with data */
426     MemoryTrackingAdd(size);
427 
428     /* If pool exists for the size needed, then use it, else find next largest pool */
429     for (poolIndex = whichPool; poolIndex < 32; poolIndex++)
430       if (memoryPool[poolIndex].poolInfo[0].pMemory != NULL)
431       {
432         foundPool = TRUE;
433         whichPool = poolIndex;
434         break;
435       }
436 
437     /* If next largest pool doesn't exist, then use pool 0 (regions) */
438     if (!foundPool)
439       whichPool = 0;
440 
441     /* Allocate memory from the first available bin */
442     pMemory = SearchPoolsForMemory(whichPool, size);
443     PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
444     return pMemory;
445   }
446 
PortMemBlockDeleteFromPool(void * pMemory)447   void PortMemBlockDeleteFromPool(void* pMemory)
448   {
449     unsigned long *pRealMemory = (unsigned long *)pMemory - 1;
450 
451     uint32 whichPool = (*pRealMemory >> 27) & 0x0000001f;
452     uint32 whichBin = (*pRealMemory >> 24) & 0x00000007;
453 
454     PORT_ASSERT_GOOD_WRITE_POINTER(pMemory);
455     MemoryTrackingDelete(*pRealMemory & 0x00ffffff);
456 
457 
458     if (whichPool == 0)
459     {
460       free(pRealMemory);
461     }
462     else
463     {
464       uint32 retval = pt_retbuf(memoryPool[whichPool].poolInfo[whichBin].poolId, pRealMemory);
465       PORT_ASSERT(retval == 0);
466     }
467   }
468 
469   /* PortMemGetPoolSize() : return size of portable memory pool, or 0 if
470    * unknown.
471    */
PortMemBlockGetPoolSize(void)472   int  PortMemBlockGetPoolSize(void)
473   {
474     return 0; /* TODO: Find size of pool: 4Mar02 */
475   }
476 
477   /* PortMemBlockSetPoolSize() : set size of portable memory pool on PSOS.
478    * This must be called before PortMemoryInit(), which is called by PortInit().
479    */
PortMemBlockSetPoolSize(size_t sizeInBytes)480   void PortMemBlockSetPoolSize(size_t sizeInBytes)
481   {}
482 
PortMemBlockInit(void)483   int  PortMemBlockInit(void)
484   {
485     InitPools();
486     CreatePool(findBin(1 <<  3),  3000);
487     CreatePool(findBin(1 <<  4), 10000);
488     CreatePool(findBin(1 <<  5),  8000);
489     CreatePool(findBin(1 <<  6), 16000);
490     CreatePool(findBin(1 <<  7),  5000);
491     CreatePool(findBin(1 <<  8),  1000);
492     CreatePool(findBin(1 <<  9),  2000);
493     CreatePool(findBin(1 << 10),    50);
494     CreatePool(findBin(1 << 11),    20);
495     CreatePool(findBin(1 << 12),    24);
496     CreatePool(findBin(1 << 13),    16);
497     CreatePool(findBin(1 << 14),    10);
498     CreatePool(findBin(1 << 15),    16);
499     CreatePool(findBin(1 << 16),     4);
500     CreatePool(findBin(1 << 18),     6);
501 
502     MemoryTrackingInit();
503   }
504 
PortMemBlockTerm(void)505   void PortMemBlockTerm(void)
506   {
507     TermPools();
508   }
509 
PortMemBlockTrackDump(void)510   void PortMemBlockTrackDump(void)
511   {
512     int i;
513 
514     printf("\nCurrent Memory Usage = %d\nMaximum Memory Usage = %d\nTotal Memory Allocation = %d\n\n",
515            gMemoryTracking.sCurrentAllocationSize, gMemoryTracking.sMaximumAllocationSize, gMemoryTracking.sTotalAllocationSize);
516 
517     printf("\nCurrent Real Memory Usage = %d\nMaximum Real Memory Usage = %d\nTotal Real Memory Allocation = %d\n\n",
518            gMemoryTracking.sCurrentAllocRealSize, gMemoryTracking.sMaximumAllocRealSize, gMemoryTracking.sTotalAllocRealSize);
519 
520     for (i = 0; i < NUM_TRACKING_BINS; i++)
521       printf("Max size of 2^%2d byte objects = %d\n", i, gMemoryTracking.sMaximumAllocationSizeArray[i]);
522 
523     printf("\nCurrent Memory Objects = %d\nMaximum Memory Objects = %d\nTotal Memory Objects = %d\n\n",
524            gMemoryTracking.sCurrentAllocationNumber, gMemoryTracking.sMaximumAllocationNumber, gMemoryTracking.sTotalAllocationNumber);
525 
526     for (i = 0; i < NUM_TRACKING_BINS; i++)
527       printf("Max number for 2^%2d byte objects = %d\n", i, gMemoryTracking.sMaximumAllocationNumberArray[i]);
528   }
529 
530   /* PortMemBlockGetMaxMemUsed() : return the maximum real memory allocated.
531    * There is another function of the same name in pmalloc.c, for tracking
532    * non-psos block memory.
533    */
PortMemBlockGetMaxMemUsed(void)534   int PortMemBlockGetMaxMemUsed(void)
535   {
536     return gMemoryTracking.sMaximumAllocRealSize;
537   }
538 
539 #ifdef __cplusplus
540 }
541 #endif
542 
543 #endif /* PORTABLE_MEM_MGR == PORTABLE_PSOS_BLOCK_SCHEME_MEM_MGR */
544 
545