1 /****************************************************************************** 2 3 � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. 4 All rights reserved. 5 6 This is proprietary source code of Freescale Semiconductor Inc., 7 and its use is subject to the NetComm Device Drivers EULA. 8 The copyright notice above does not evidence any actual or intended 9 publication of such source code. 10 11 ALTERNATIVELY, redistribution and use in source and binary forms, with 12 or without modification, are permitted provided that the following 13 conditions are met: 14 * Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 * Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in the 18 documentation and/or other materials provided with the distribution. 19 * Neither the name of Freescale Semiconductor nor the 20 names of its contributors may be used to endorse or promote products 21 derived from this software without specific prior written permission. 22 23 THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 24 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 27 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 35 **************************************************************************/ 36 #include "error_ext.h" 37 #include "part_ext.h" 38 #include "std_ext.h" 39 #include "string_ext.h" 40 #include "mem_ext.h" 41 #include "mem.h" 42 #include "xx_ext.h" 43 44 45 #define PAD_ALIGNMENT(align, x) (((x)%(align)) ? ((align)-((x)%(align))) : 0) 46 47 #define ALIGN_BLOCK(p_Block, prefixSize, alignment) \ 48 do { \ 49 p_Block += (prefixSize); \ 50 p_Block += PAD_ALIGNMENT((alignment), (uintptr_t)(p_Block)); \ 51 } while (0) 52 53 #if defined(__GNUC__) 54 #define GET_CALLER_ADDR \ 55 __asm__ ("mflr %0" : "=r" (callerAddr)) 56 #elif defined(__MWERKS__) 57 /* NOTE: This implementation is only valid for CodeWarrior for PowerPC */ 58 #define GET_CALLER_ADDR \ 59 __asm__("add %0, 0, %0" : : "r" (callerAddr)) 60 #endif /* defined(__GNUC__) */ 61 62 63 /*****************************************************************************/ 64 static __inline__ void * MemGet(t_MemorySegment *p_Mem) 65 { 66 uint8_t *p_Block; 67 68 /* check if there is an available block */ 69 if (p_Mem->current == p_Mem->num) 70 { 71 p_Mem->getFailures++; 72 return NULL; 73 } 74 75 /* get the block */ 76 p_Block = p_Mem->p_BlocksStack[p_Mem->current]; 77 #ifdef DEBUG 78 p_Mem->p_BlocksStack[p_Mem->current] = NULL; 79 #endif /* DEBUG */ 80 /* advance current index */ 81 p_Mem->current++; 82 83 return (void *)p_Block; 84 } 85 86 /*****************************************************************************/ 87 static __inline__ t_Error MemPut(t_MemorySegment *p_Mem, void *p_Block) 88 { 89 /* check if blocks stack is full */ 90 if (p_Mem->current > 0) 91 { 92 /* decrease current index */ 93 p_Mem->current--; 94 /* put the block */ 95 p_Mem->p_BlocksStack[p_Mem->current] = (uint8_t *)p_Block; 96 return E_OK; 97 } 98 99 RETURN_ERROR(MAJOR, E_FULL, NO_MSG); 100 } 101 102 103 #ifdef DEBUG_MEM_LEAKS 104 105 /*****************************************************************************/ 106 static t_Error InitMemDebugDatabase(t_MemorySegment *p_Mem) 107 { 108 p_Mem->p_MemDbg = (void *)XX_Malloc(sizeof(t_MemDbg) * p_Mem->num); 109 if (!p_Mem->p_MemDbg) 110 { 111 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory debug object")); 112 } 113 114 memset(p_Mem->p_MemDbg, ILLEGAL_BASE, sizeof(t_MemDbg) * p_Mem->num); 115 116 return E_OK; 117 } 118 119 120 /*****************************************************************************/ 121 static t_Error DebugMemGet(t_Handle h_Mem, void *p_Block, uintptr_t ownerAddress) 122 { 123 t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 124 t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg; 125 uint32_t blockIndex; 126 127 ASSERT_COND(ownerAddress != ILLEGAL_BASE); 128 129 /* Find block num */ 130 if (p_Mem->consecutiveMem) 131 { 132 blockIndex = 133 (((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize); 134 } 135 else 136 { 137 blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4); 138 } 139 140 ASSERT_COND(blockIndex < p_Mem->num); 141 ASSERT_COND(p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE); 142 143 p_MemDbg[blockIndex].ownerAddress = ownerAddress; 144 145 return E_OK; 146 } 147 148 /*****************************************************************************/ 149 static t_Error DebugMemPut(t_Handle h_Mem, void *p_Block) 150 { 151 t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 152 t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg; 153 uint32_t blockIndex; 154 uint8_t *p_Temp; 155 156 /* Find block num */ 157 if (p_Mem->consecutiveMem) 158 { 159 blockIndex = 160 (((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize); 161 162 if (blockIndex >= p_Mem->num) 163 { 164 RETURN_ERROR(MAJOR, E_INVALID_ADDRESS, 165 ("Freed address (0x%08x) does not belong to this pool", p_Block)); 166 } 167 } 168 else 169 { 170 blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4); 171 172 if (blockIndex >= p_Mem->num) 173 { 174 RETURN_ERROR(MAJOR, E_INVALID_ADDRESS, 175 ("Freed address (0x%08x) does not belong to this pool", p_Block)); 176 } 177 178 /* Verify that the block matches the corresponding base */ 179 p_Temp = p_Mem->p_Bases[blockIndex]; 180 181 ALIGN_BLOCK(p_Temp, p_Mem->prefixSize, p_Mem->alignment); 182 183 if (p_Temp == p_Mem->p_Bases[blockIndex]) 184 p_Temp += p_Mem->alignment; 185 186 if (p_Temp != p_Block) 187 { 188 RETURN_ERROR(MAJOR, E_INVALID_ADDRESS, 189 ("Freed address (0x%08x) does not belong to this pool", p_Block)); 190 } 191 } 192 193 if (p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE) 194 { 195 RETURN_ERROR(MAJOR, E_ALREADY_FREE, 196 ("Attempt to free unallocated address (0x%08x)", p_Block)); 197 } 198 199 p_MemDbg[blockIndex].ownerAddress = (uintptr_t)ILLEGAL_BASE; 200 201 return E_OK; 202 } 203 204 #endif /* DEBUG_MEM_LEAKS */ 205 206 207 /*****************************************************************************/ 208 uint32_t MEM_ComputePartitionSize(uint32_t num, 209 uint16_t dataSize, 210 uint16_t prefixSize, 211 uint16_t postfixSize, 212 uint16_t alignment) 213 { 214 uint32_t blockSize = 0, pad1 = 0, pad2 = 0; 215 216 /* Make sure that the alignment is at least 4 */ 217 if (alignment < 4) 218 { 219 alignment = 4; 220 } 221 222 pad1 = (uint32_t)PAD_ALIGNMENT(4, prefixSize); 223 /* Block size not including 2nd padding */ 224 blockSize = pad1 + prefixSize + dataSize + postfixSize; 225 pad2 = PAD_ALIGNMENT(alignment, blockSize); 226 /* Block size including 2nd padding */ 227 blockSize += pad2; 228 229 return ((num * blockSize) + alignment); 230 } 231 232 /*****************************************************************************/ 233 t_Error MEM_Init(char name[], 234 t_Handle *p_Handle, 235 uint32_t num, 236 uint16_t dataSize, 237 uint16_t prefixSize, 238 uint16_t postfixSize, 239 uint16_t alignment) 240 { 241 uint8_t *p_Memory; 242 uint32_t allocSize; 243 t_Error errCode; 244 245 allocSize = MEM_ComputePartitionSize(num, 246 dataSize, 247 prefixSize, 248 postfixSize, 249 alignment); 250 251 p_Memory = (uint8_t *)XX_Malloc(allocSize); 252 if (!p_Memory) 253 { 254 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment")); 255 } 256 257 errCode = MEM_InitByAddress(name, 258 p_Handle, 259 num, 260 dataSize, 261 prefixSize, 262 postfixSize, 263 alignment, 264 p_Memory); 265 if (errCode != E_OK) 266 { 267 RETURN_ERROR(MAJOR, errCode, NO_MSG); 268 } 269 270 ((t_MemorySegment *)(*p_Handle))->allocOwner = e_MEM_ALLOC_OWNER_LOCAL; 271 272 return E_OK; 273 } 274 275 276 /*****************************************************************************/ 277 t_Error MEM_InitByAddress(char name[], 278 t_Handle *p_Handle, 279 uint32_t num, 280 uint16_t dataSize, 281 uint16_t prefixSize, 282 uint16_t postfixSize, 283 uint16_t alignment, 284 uint8_t *p_Memory) 285 { 286 t_MemorySegment *p_Mem; 287 uint32_t i, blockSize; 288 uint16_t alignPad, endPad; 289 uint8_t *p_Blocks; 290 291 /* prepare in case of error */ 292 *p_Handle = NULL; 293 294 if (!p_Memory) 295 { 296 RETURN_ERROR(MAJOR, E_NULL_POINTER, ("Memory blocks")); 297 } 298 299 p_Blocks = p_Memory; 300 301 /* make sure that the alignment is at least 4 and power of 2 */ 302 if (alignment < 4) 303 { 304 alignment = 4; 305 } 306 else if (!POWER_OF_2(alignment)) 307 { 308 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)")); 309 } 310 311 /* first allocate the segment descriptor */ 312 p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment)); 313 if (!p_Mem) 314 { 315 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure")); 316 } 317 318 /* allocate the blocks stack */ 319 p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*)); 320 if (!p_Mem->p_BlocksStack) 321 { 322 XX_Free(p_Mem); 323 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack")); 324 } 325 326 /* allocate the blocks bases array */ 327 p_Mem->p_Bases = (uint8_t **)XX_Malloc(sizeof(uint8_t*)); 328 if (!p_Mem->p_Bases) 329 { 330 MEM_Free(p_Mem); 331 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array")); 332 } 333 memset(p_Mem->p_Bases, 0, sizeof(uint8_t*)); 334 335 /* store info about this segment */ 336 p_Mem->num = num; 337 p_Mem->current = 0; 338 p_Mem->dataSize = dataSize; 339 p_Mem->p_Bases[0] = p_Blocks; 340 p_Mem->getFailures = 0; 341 p_Mem->allocOwner = e_MEM_ALLOC_OWNER_EXTERNAL; 342 p_Mem->consecutiveMem = TRUE; 343 p_Mem->prefixSize = prefixSize; 344 p_Mem->postfixSize = postfixSize; 345 p_Mem->alignment = alignment; 346 /* store name */ 347 strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1); 348 349 p_Mem->h_Spinlock = XX_InitSpinlock(); 350 if (!p_Mem->h_Spinlock) 351 { 352 MEM_Free(p_Mem); 353 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!")); 354 } 355 356 alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize); 357 /* Make sure the entire size is a multiple of alignment */ 358 endPad = (uint16_t)PAD_ALIGNMENT(alignment, (alignPad + prefixSize + dataSize + postfixSize)); 359 360 /* The following manipulation places the data of block[0] in an aligned address, 361 since block size is aligned the following block datas will all be aligned */ 362 ALIGN_BLOCK(p_Blocks, prefixSize, alignment); 363 364 blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad); 365 366 /* initialize the blocks */ 367 for (i=0; i < num; i++) 368 { 369 p_Mem->p_BlocksStack[i] = p_Blocks; 370 p_Blocks += blockSize; 371 } 372 373 /* return handle to caller */ 374 *p_Handle = (t_Handle)p_Mem; 375 376 #ifdef DEBUG_MEM_LEAKS 377 { 378 t_Error errCode = InitMemDebugDatabase(p_Mem); 379 380 if (errCode != E_OK) 381 RETURN_ERROR(MAJOR, errCode, NO_MSG); 382 383 p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]); 384 p_Mem->blockSize = blockSize; 385 } 386 #endif /* DEBUG_MEM_LEAKS */ 387 388 return E_OK; 389 } 390 391 392 /*****************************************************************************/ 393 t_Error MEM_InitSmart(char name[], 394 t_Handle *p_Handle, 395 uint32_t num, 396 uint16_t dataSize, 397 uint16_t prefixSize, 398 uint16_t postfixSize, 399 uint16_t alignment, 400 uint8_t memPartitionId, 401 bool consecutiveMem) 402 { 403 t_MemorySegment *p_Mem; 404 uint32_t i, blockSize; 405 uint16_t alignPad, endPad; 406 407 /* prepare in case of error */ 408 *p_Handle = NULL; 409 410 /* make sure that size is always a multiple of 4 */ 411 if (dataSize & 3) 412 { 413 dataSize &= ~3; 414 dataSize += 4; 415 } 416 417 /* make sure that the alignment is at least 4 and power of 2 */ 418 if (alignment < 4) 419 { 420 alignment = 4; 421 } 422 else if (!POWER_OF_2(alignment)) 423 { 424 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)")); 425 } 426 427 /* first allocate the segment descriptor */ 428 p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment)); 429 if (!p_Mem) 430 { 431 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure")); 432 } 433 434 /* allocate the blocks stack */ 435 p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*)); 436 if (!p_Mem->p_BlocksStack) 437 { 438 MEM_Free(p_Mem); 439 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack")); 440 } 441 442 /* allocate the blocks bases array */ 443 p_Mem->p_Bases = (uint8_t **)XX_Malloc((consecutiveMem ? 1 : num) * sizeof(uint8_t*)); 444 if (!p_Mem->p_Bases) 445 { 446 MEM_Free(p_Mem); 447 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array")); 448 } 449 memset(p_Mem->p_Bases, 0, (consecutiveMem ? 1 : num) * sizeof(uint8_t*)); 450 451 /* store info about this segment */ 452 p_Mem->num = num; 453 p_Mem->current = 0; 454 p_Mem->dataSize = dataSize; 455 p_Mem->getFailures = 0; 456 p_Mem->allocOwner = e_MEM_ALLOC_OWNER_LOCAL_SMART; 457 p_Mem->consecutiveMem = consecutiveMem; 458 p_Mem->prefixSize = prefixSize; 459 p_Mem->postfixSize = postfixSize; 460 p_Mem->alignment = alignment; 461 462 p_Mem->h_Spinlock = XX_InitSpinlock(); 463 if (!p_Mem->h_Spinlock) 464 { 465 MEM_Free(p_Mem); 466 RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!")); 467 } 468 469 alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize); 470 /* Make sure the entire size is a multiple of alignment */ 471 endPad = (uint16_t)PAD_ALIGNMENT(alignment, alignPad + prefixSize + dataSize + postfixSize); 472 473 /* Calculate blockSize */ 474 blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad); 475 476 /* Now allocate the blocks */ 477 if (p_Mem->consecutiveMem) 478 { 479 /* |alignment - 1| bytes at most will be discarded in the beginning of the 480 received segment for alignment reasons, therefore the allocation is of: 481 (alignment + (num * block size)). */ 482 uint8_t *p_Blocks = (uint8_t *) 483 XX_MallocSmart((uint32_t)((num * blockSize) + alignment), memPartitionId, 1); 484 if (!p_Blocks) 485 { 486 MEM_Free(p_Mem); 487 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks")); 488 } 489 490 /* Store the memory segment address */ 491 p_Mem->p_Bases[0] = p_Blocks; 492 493 /* The following manipulation places the data of block[0] in an aligned address, 494 since block size is aligned the following block datas will all be aligned.*/ 495 ALIGN_BLOCK(p_Blocks, prefixSize, alignment); 496 497 /* initialize the blocks */ 498 for (i = 0; i < num; i++) 499 { 500 p_Mem->p_BlocksStack[i] = p_Blocks; 501 p_Blocks += blockSize; 502 } 503 504 #ifdef DEBUG_MEM_LEAKS 505 p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]); 506 p_Mem->blockSize = blockSize; 507 #endif /* DEBUG_MEM_LEAKS */ 508 } 509 else 510 { 511 /* |alignment - 1| bytes at most will be discarded in the beginning of the 512 received segment for alignment reasons, therefore the allocation is of: 513 (alignment + block size). */ 514 for (i = 0; i < num; i++) 515 { 516 uint8_t *p_Block = (uint8_t *) 517 XX_MallocSmart((uint32_t)(blockSize + alignment), memPartitionId, 1); 518 if (!p_Block) 519 { 520 MEM_Free(p_Mem); 521 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks")); 522 } 523 524 /* Store the memory segment address */ 525 p_Mem->p_Bases[i] = p_Block; 526 527 /* The following places the data of each block in an aligned address */ 528 ALIGN_BLOCK(p_Block, prefixSize, alignment); 529 530 #ifdef DEBUG_MEM_LEAKS 531 /* Need 4 bytes before the meaningful bytes to store the block index. 532 We know we have them because alignment is at least 4 bytes. */ 533 if (p_Block == p_Mem->p_Bases[i]) 534 p_Block += alignment; 535 536 *(uint32_t *)(p_Block - 4) = i; 537 #endif /* DEBUG_MEM_LEAKS */ 538 539 p_Mem->p_BlocksStack[i] = p_Block; 540 } 541 } 542 543 /* store name */ 544 strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1); 545 546 /* return handle to caller */ 547 *p_Handle = (t_Handle)p_Mem; 548 549 #ifdef DEBUG_MEM_LEAKS 550 { 551 t_Error errCode = InitMemDebugDatabase(p_Mem); 552 553 if (errCode != E_OK) 554 RETURN_ERROR(MAJOR, errCode, NO_MSG); 555 } 556 #endif /* DEBUG_MEM_LEAKS */ 557 558 return E_OK; 559 } 560 561 562 /*****************************************************************************/ 563 void MEM_Free(t_Handle h_Mem) 564 { 565 t_MemorySegment *p_Mem = (t_MemorySegment*)h_Mem; 566 uint32_t num, i; 567 568 /* Check MEM leaks */ 569 MEM_CheckLeaks(h_Mem); 570 571 if (p_Mem) 572 { 573 num = p_Mem->consecutiveMem ? 1 : p_Mem->num; 574 575 if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL_SMART) 576 { 577 for (i=0; i < num; i++) 578 { 579 if (p_Mem->p_Bases[i]) 580 { 581 XX_FreeSmart(p_Mem->p_Bases[i]); 582 } 583 } 584 } 585 else if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL) 586 { 587 for (i=0; i < num; i++) 588 { 589 if (p_Mem->p_Bases[i]) 590 { 591 XX_Free(p_Mem->p_Bases[i]); 592 } 593 } 594 } 595 596 if (p_Mem->h_Spinlock) 597 XX_FreeSpinlock(p_Mem->h_Spinlock); 598 599 if (p_Mem->p_Bases) 600 XX_Free(p_Mem->p_Bases); 601 602 if (p_Mem->p_BlocksStack) 603 XX_Free(p_Mem->p_BlocksStack); 604 605 #ifdef DEBUG_MEM_LEAKS 606 if (p_Mem->p_MemDbg) 607 XX_Free(p_Mem->p_MemDbg); 608 #endif /* DEBUG_MEM_LEAKS */ 609 610 XX_Free(p_Mem); 611 } 612 } 613 614 615 /*****************************************************************************/ 616 void * MEM_Get(t_Handle h_Mem) 617 { 618 t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 619 uint8_t *p_Block; 620 uint32_t intFlags; 621 #ifdef DEBUG_MEM_LEAKS 622 uintptr_t callerAddr = 0; 623 624 GET_CALLER_ADDR; 625 #endif /* DEBUG_MEM_LEAKS */ 626 627 ASSERT_COND(h_Mem); 628 629 intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock); 630 /* check if there is an available block */ 631 if ((p_Block = (uint8_t *)MemGet(p_Mem)) == NULL) 632 { 633 XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 634 return NULL; 635 } 636 637 #ifdef DEBUG_MEM_LEAKS 638 DebugMemGet(p_Mem, p_Block, callerAddr); 639 #endif /* DEBUG_MEM_LEAKS */ 640 XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 641 642 return (void *)p_Block; 643 } 644 645 646 /*****************************************************************************/ 647 uint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[]) 648 { 649 t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 650 uint32_t availableBlocks; 651 register uint32_t i; 652 uint32_t intFlags; 653 #ifdef DEBUG_MEM_LEAKS 654 uintptr_t callerAddr = 0; 655 656 GET_CALLER_ADDR; 657 #endif /* DEBUG_MEM_LEAKS */ 658 659 ASSERT_COND(h_Mem); 660 661 intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock); 662 /* check how many blocks are available */ 663 availableBlocks = (uint32_t)(p_Mem->num - p_Mem->current); 664 if (num > availableBlocks) 665 { 666 num = availableBlocks; 667 } 668 669 for (i=0; i < num; i++) 670 { 671 /* get pointer to block */ 672 if ((array[i] = MemGet(p_Mem)) == NULL) 673 { 674 break; 675 } 676 677 #ifdef DEBUG_MEM_LEAKS 678 DebugMemGet(p_Mem, array[i], callerAddr); 679 #endif /* DEBUG_MEM_LEAKS */ 680 } 681 XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 682 683 return (uint16_t)i; 684 } 685 686 687 /*****************************************************************************/ 688 t_Error MEM_Put(t_Handle h_Mem, void *p_Block) 689 { 690 t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 691 t_Error rc; 692 uint32_t intFlags; 693 694 ASSERT_COND(h_Mem); 695 696 intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock); 697 /* check if blocks stack is full */ 698 if ((rc = MemPut(p_Mem, p_Block)) != E_OK) 699 { 700 XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 701 RETURN_ERROR(MAJOR, rc, NO_MSG); 702 } 703 704 #ifdef DEBUG_MEM_LEAKS 705 DebugMemPut(p_Mem, p_Block); 706 #endif /* DEBUG_MEM_LEAKS */ 707 XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 708 709 return E_OK; 710 } 711 712 713 #ifdef DEBUG_MEM_LEAKS 714 715 /*****************************************************************************/ 716 void MEM_CheckLeaks(t_Handle h_Mem) 717 { 718 t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 719 t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg; 720 uint8_t *p_Block; 721 int i; 722 723 ASSERT_COND(h_Mem); 724 725 if (p_Mem->consecutiveMem) 726 { 727 for (i=0; i < p_Mem->num; i++) 728 { 729 if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE) 730 { 731 /* Find the block address */ 732 p_Block = ((p_Mem->p_Bases[0] + p_Mem->blockOffset) + 733 (i * p_Mem->blockSize)); 734 735 XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n", 736 p_Block, p_MemDbg[i].ownerAddress); 737 } 738 } 739 } 740 else 741 { 742 for (i=0; i < p_Mem->num; i++) 743 { 744 if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE) 745 { 746 /* Find the block address */ 747 p_Block = p_Mem->p_Bases[i]; 748 749 ALIGN_BLOCK(p_Block, p_Mem->prefixSize, p_Mem->alignment); 750 751 if (p_Block == p_Mem->p_Bases[i]) 752 p_Block += p_Mem->alignment; 753 754 XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n", 755 p_Block, p_MemDbg[i].ownerAddress); 756 } 757 } 758 } 759 } 760 761 #endif /* DEBUG_MEM_LEAKS */ 762 763 764