Home | History | Annotate | Download | only in src
      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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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    */
    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    */
    480   void PortMemBlockSetPoolSize(size_t sizeInBytes)
    481   {}
    482 
    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 
    505   void PortMemBlockTerm(void)
    506   {
    507     TermPools();
    508   }
    509 
    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    */
    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