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