1296177Sjhibbits/****************************************************************************** 2296177Sjhibbits 3296177Sjhibbits � 1995-2003, 2004, 2005-2011 Freescale Semiconductor, Inc. 4296177Sjhibbits All rights reserved. 5296177Sjhibbits 6296177Sjhibbits This is proprietary source code of Freescale Semiconductor Inc., 7296177Sjhibbits and its use is subject to the NetComm Device Drivers EULA. 8296177Sjhibbits The copyright notice above does not evidence any actual or intended 9296177Sjhibbits publication of such source code. 10296177Sjhibbits 11296177Sjhibbits ALTERNATIVELY, redistribution and use in source and binary forms, with 12296177Sjhibbits or without modification, are permitted provided that the following 13296177Sjhibbits conditions are met: 14296177Sjhibbits * Redistributions of source code must retain the above copyright 15296177Sjhibbits notice, this list of conditions and the following disclaimer. 16296177Sjhibbits * Redistributions in binary form must reproduce the above copyright 17296177Sjhibbits notice, this list of conditions and the following disclaimer in the 18296177Sjhibbits documentation and/or other materials provided with the distribution. 19296177Sjhibbits * Neither the name of Freescale Semiconductor nor the 20296177Sjhibbits names of its contributors may be used to endorse or promote products 21296177Sjhibbits derived from this software without specific prior written permission. 22296177Sjhibbits 23296177Sjhibbits THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 24296177Sjhibbits EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25296177Sjhibbits WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26296177Sjhibbits DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 27296177Sjhibbits DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28296177Sjhibbits (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29296177Sjhibbits LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30296177Sjhibbits ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31296177Sjhibbits (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32296177Sjhibbits SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33296177Sjhibbits * 34296177Sjhibbits 35296177Sjhibbits **************************************************************************/ 36296177Sjhibbits#include "error_ext.h" 37296177Sjhibbits#include "part_ext.h" 38296177Sjhibbits#include "std_ext.h" 39296177Sjhibbits#include "string_ext.h" 40296177Sjhibbits#include "mem_ext.h" 41296177Sjhibbits#include "mem.h" 42296177Sjhibbits#include "xx_ext.h" 43296177Sjhibbits 44296177Sjhibbits 45296177Sjhibbits#define PAD_ALIGNMENT(align, x) (((x)%(align)) ? ((align)-((x)%(align))) : 0) 46296177Sjhibbits 47296177Sjhibbits#define ALIGN_BLOCK(p_Block, prefixSize, alignment) \ 48296177Sjhibbits do { \ 49296177Sjhibbits p_Block += (prefixSize); \ 50296177Sjhibbits p_Block += PAD_ALIGNMENT((alignment), (uintptr_t)(p_Block)); \ 51296177Sjhibbits } while (0) 52296177Sjhibbits 53296177Sjhibbits#if defined(__GNUC__) 54296177Sjhibbits#define GET_CALLER_ADDR \ 55296177Sjhibbits __asm__ ("mflr %0" : "=r" (callerAddr)) 56296177Sjhibbits#elif defined(__MWERKS__) 57296177Sjhibbits/* NOTE: This implementation is only valid for CodeWarrior for PowerPC */ 58296177Sjhibbits#define GET_CALLER_ADDR \ 59296177Sjhibbits __asm__("add %0, 0, %0" : : "r" (callerAddr)) 60296177Sjhibbits#endif /* defined(__GNUC__) */ 61296177Sjhibbits 62296177Sjhibbits 63296177Sjhibbits/*****************************************************************************/ 64296177Sjhibbitsstatic __inline__ void * MemGet(t_MemorySegment *p_Mem) 65296177Sjhibbits{ 66296177Sjhibbits uint8_t *p_Block; 67296177Sjhibbits 68296177Sjhibbits /* check if there is an available block */ 69296177Sjhibbits if (p_Mem->current == p_Mem->num) 70296177Sjhibbits { 71296177Sjhibbits p_Mem->getFailures++; 72296177Sjhibbits return NULL; 73296177Sjhibbits } 74296177Sjhibbits 75296177Sjhibbits /* get the block */ 76296177Sjhibbits p_Block = p_Mem->p_BlocksStack[p_Mem->current]; 77296177Sjhibbits#ifdef DEBUG 78296177Sjhibbits p_Mem->p_BlocksStack[p_Mem->current] = NULL; 79296177Sjhibbits#endif /* DEBUG */ 80296177Sjhibbits /* advance current index */ 81296177Sjhibbits p_Mem->current++; 82296177Sjhibbits 83296177Sjhibbits return (void *)p_Block; 84296177Sjhibbits} 85296177Sjhibbits 86296177Sjhibbits/*****************************************************************************/ 87296177Sjhibbitsstatic __inline__ t_Error MemPut(t_MemorySegment *p_Mem, void *p_Block) 88296177Sjhibbits{ 89296177Sjhibbits /* check if blocks stack is full */ 90296177Sjhibbits if (p_Mem->current > 0) 91296177Sjhibbits { 92296177Sjhibbits /* decrease current index */ 93296177Sjhibbits p_Mem->current--; 94296177Sjhibbits /* put the block */ 95296177Sjhibbits p_Mem->p_BlocksStack[p_Mem->current] = (uint8_t *)p_Block; 96296177Sjhibbits return E_OK; 97296177Sjhibbits } 98296177Sjhibbits 99296177Sjhibbits RETURN_ERROR(MAJOR, E_FULL, NO_MSG); 100296177Sjhibbits} 101296177Sjhibbits 102296177Sjhibbits 103296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 104296177Sjhibbits 105296177Sjhibbits/*****************************************************************************/ 106296177Sjhibbitsstatic t_Error InitMemDebugDatabase(t_MemorySegment *p_Mem) 107296177Sjhibbits{ 108296177Sjhibbits p_Mem->p_MemDbg = (void *)XX_Malloc(sizeof(t_MemDbg) * p_Mem->num); 109296177Sjhibbits if (!p_Mem->p_MemDbg) 110296177Sjhibbits { 111296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory debug object")); 112296177Sjhibbits } 113296177Sjhibbits 114296177Sjhibbits memset(p_Mem->p_MemDbg, ILLEGAL_BASE, sizeof(t_MemDbg) * p_Mem->num); 115296177Sjhibbits 116296177Sjhibbits return E_OK; 117296177Sjhibbits} 118296177Sjhibbits 119296177Sjhibbits 120296177Sjhibbits/*****************************************************************************/ 121296177Sjhibbitsstatic t_Error DebugMemGet(t_Handle h_Mem, void *p_Block, uintptr_t ownerAddress) 122296177Sjhibbits{ 123296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 124296177Sjhibbits t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg; 125296177Sjhibbits uint32_t blockIndex; 126296177Sjhibbits 127296177Sjhibbits ASSERT_COND(ownerAddress != ILLEGAL_BASE); 128296177Sjhibbits 129296177Sjhibbits /* Find block num */ 130296177Sjhibbits if (p_Mem->consecutiveMem) 131296177Sjhibbits { 132296177Sjhibbits blockIndex = 133296177Sjhibbits (((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize); 134296177Sjhibbits } 135296177Sjhibbits else 136296177Sjhibbits { 137296177Sjhibbits blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4); 138296177Sjhibbits } 139296177Sjhibbits 140296177Sjhibbits ASSERT_COND(blockIndex < p_Mem->num); 141296177Sjhibbits ASSERT_COND(p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE); 142296177Sjhibbits 143296177Sjhibbits p_MemDbg[blockIndex].ownerAddress = ownerAddress; 144296177Sjhibbits 145296177Sjhibbits return E_OK; 146296177Sjhibbits} 147296177Sjhibbits 148296177Sjhibbits/*****************************************************************************/ 149296177Sjhibbitsstatic t_Error DebugMemPut(t_Handle h_Mem, void *p_Block) 150296177Sjhibbits{ 151296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 152296177Sjhibbits t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg; 153296177Sjhibbits uint32_t blockIndex; 154296177Sjhibbits uint8_t *p_Temp; 155296177Sjhibbits 156296177Sjhibbits /* Find block num */ 157296177Sjhibbits if (p_Mem->consecutiveMem) 158296177Sjhibbits { 159296177Sjhibbits blockIndex = 160296177Sjhibbits (((uint8_t *)p_Block - (p_Mem->p_Bases[0] + p_Mem->blockOffset)) / p_Mem->blockSize); 161296177Sjhibbits 162296177Sjhibbits if (blockIndex >= p_Mem->num) 163296177Sjhibbits { 164296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_ADDRESS, 165296177Sjhibbits ("Freed address (0x%08x) does not belong to this pool", p_Block)); 166296177Sjhibbits } 167296177Sjhibbits } 168296177Sjhibbits else 169296177Sjhibbits { 170296177Sjhibbits blockIndex = *(uint32_t *)((uint8_t *)p_Block - 4); 171296177Sjhibbits 172296177Sjhibbits if (blockIndex >= p_Mem->num) 173296177Sjhibbits { 174296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_ADDRESS, 175296177Sjhibbits ("Freed address (0x%08x) does not belong to this pool", p_Block)); 176296177Sjhibbits } 177296177Sjhibbits 178296177Sjhibbits /* Verify that the block matches the corresponding base */ 179296177Sjhibbits p_Temp = p_Mem->p_Bases[blockIndex]; 180296177Sjhibbits 181296177Sjhibbits ALIGN_BLOCK(p_Temp, p_Mem->prefixSize, p_Mem->alignment); 182296177Sjhibbits 183296177Sjhibbits if (p_Temp == p_Mem->p_Bases[blockIndex]) 184296177Sjhibbits p_Temp += p_Mem->alignment; 185296177Sjhibbits 186296177Sjhibbits if (p_Temp != p_Block) 187296177Sjhibbits { 188296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_ADDRESS, 189296177Sjhibbits ("Freed address (0x%08x) does not belong to this pool", p_Block)); 190296177Sjhibbits } 191296177Sjhibbits } 192296177Sjhibbits 193296177Sjhibbits if (p_MemDbg[blockIndex].ownerAddress == ILLEGAL_BASE) 194296177Sjhibbits { 195296177Sjhibbits RETURN_ERROR(MAJOR, E_ALREADY_FREE, 196296177Sjhibbits ("Attempt to free unallocated address (0x%08x)", p_Block)); 197296177Sjhibbits } 198296177Sjhibbits 199296177Sjhibbits p_MemDbg[blockIndex].ownerAddress = (uintptr_t)ILLEGAL_BASE; 200296177Sjhibbits 201296177Sjhibbits return E_OK; 202296177Sjhibbits} 203296177Sjhibbits 204296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 205296177Sjhibbits 206296177Sjhibbits 207296177Sjhibbits/*****************************************************************************/ 208296177Sjhibbitsuint32_t MEM_ComputePartitionSize(uint32_t num, 209296177Sjhibbits uint16_t dataSize, 210296177Sjhibbits uint16_t prefixSize, 211296177Sjhibbits uint16_t postfixSize, 212296177Sjhibbits uint16_t alignment) 213296177Sjhibbits{ 214296177Sjhibbits uint32_t blockSize = 0, pad1 = 0, pad2 = 0; 215296177Sjhibbits 216296177Sjhibbits /* Make sure that the alignment is at least 4 */ 217296177Sjhibbits if (alignment < 4) 218296177Sjhibbits { 219296177Sjhibbits alignment = 4; 220296177Sjhibbits } 221296177Sjhibbits 222296177Sjhibbits pad1 = (uint32_t)PAD_ALIGNMENT(4, prefixSize); 223296177Sjhibbits /* Block size not including 2nd padding */ 224296177Sjhibbits blockSize = pad1 + prefixSize + dataSize + postfixSize; 225296177Sjhibbits pad2 = PAD_ALIGNMENT(alignment, blockSize); 226296177Sjhibbits /* Block size including 2nd padding */ 227296177Sjhibbits blockSize += pad2; 228296177Sjhibbits 229296177Sjhibbits return ((num * blockSize) + alignment); 230296177Sjhibbits} 231296177Sjhibbits 232296177Sjhibbits/*****************************************************************************/ 233296177Sjhibbitst_Error MEM_Init(char name[], 234296177Sjhibbits t_Handle *p_Handle, 235296177Sjhibbits uint32_t num, 236296177Sjhibbits uint16_t dataSize, 237296177Sjhibbits uint16_t prefixSize, 238296177Sjhibbits uint16_t postfixSize, 239296177Sjhibbits uint16_t alignment) 240296177Sjhibbits{ 241296177Sjhibbits uint8_t *p_Memory; 242296177Sjhibbits uint32_t allocSize; 243296177Sjhibbits t_Error errCode; 244296177Sjhibbits 245296177Sjhibbits allocSize = MEM_ComputePartitionSize(num, 246296177Sjhibbits dataSize, 247296177Sjhibbits prefixSize, 248296177Sjhibbits postfixSize, 249296177Sjhibbits alignment); 250296177Sjhibbits 251296177Sjhibbits p_Memory = (uint8_t *)XX_Malloc(allocSize); 252296177Sjhibbits if (!p_Memory) 253296177Sjhibbits { 254296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment")); 255296177Sjhibbits } 256296177Sjhibbits 257296177Sjhibbits errCode = MEM_InitByAddress(name, 258296177Sjhibbits p_Handle, 259296177Sjhibbits num, 260296177Sjhibbits dataSize, 261296177Sjhibbits prefixSize, 262296177Sjhibbits postfixSize, 263296177Sjhibbits alignment, 264296177Sjhibbits p_Memory); 265296177Sjhibbits if (errCode != E_OK) 266296177Sjhibbits { 267296177Sjhibbits RETURN_ERROR(MAJOR, errCode, NO_MSG); 268296177Sjhibbits } 269296177Sjhibbits 270296177Sjhibbits ((t_MemorySegment *)(*p_Handle))->allocOwner = e_MEM_ALLOC_OWNER_LOCAL; 271296177Sjhibbits 272296177Sjhibbits return E_OK; 273296177Sjhibbits} 274296177Sjhibbits 275296177Sjhibbits 276296177Sjhibbits/*****************************************************************************/ 277296177Sjhibbitst_Error MEM_InitByAddress(char name[], 278296177Sjhibbits t_Handle *p_Handle, 279296177Sjhibbits uint32_t num, 280296177Sjhibbits uint16_t dataSize, 281296177Sjhibbits uint16_t prefixSize, 282296177Sjhibbits uint16_t postfixSize, 283296177Sjhibbits uint16_t alignment, 284296177Sjhibbits uint8_t *p_Memory) 285296177Sjhibbits{ 286296177Sjhibbits t_MemorySegment *p_Mem; 287296177Sjhibbits uint32_t i, blockSize; 288296177Sjhibbits uint16_t alignPad, endPad; 289296177Sjhibbits uint8_t *p_Blocks; 290296177Sjhibbits 291296177Sjhibbits /* prepare in case of error */ 292296177Sjhibbits *p_Handle = NULL; 293296177Sjhibbits 294296177Sjhibbits if (!p_Memory) 295296177Sjhibbits { 296296177Sjhibbits RETURN_ERROR(MAJOR, E_NULL_POINTER, ("Memory blocks")); 297296177Sjhibbits } 298296177Sjhibbits 299296177Sjhibbits p_Blocks = p_Memory; 300296177Sjhibbits 301296177Sjhibbits /* make sure that the alignment is at least 4 and power of 2 */ 302296177Sjhibbits if (alignment < 4) 303296177Sjhibbits { 304296177Sjhibbits alignment = 4; 305296177Sjhibbits } 306296177Sjhibbits else if (!POWER_OF_2(alignment)) 307296177Sjhibbits { 308296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)")); 309296177Sjhibbits } 310296177Sjhibbits 311296177Sjhibbits /* first allocate the segment descriptor */ 312296177Sjhibbits p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment)); 313296177Sjhibbits if (!p_Mem) 314296177Sjhibbits { 315296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure")); 316296177Sjhibbits } 317296177Sjhibbits 318296177Sjhibbits /* allocate the blocks stack */ 319296177Sjhibbits p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*)); 320296177Sjhibbits if (!p_Mem->p_BlocksStack) 321296177Sjhibbits { 322296177Sjhibbits XX_Free(p_Mem); 323296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack")); 324296177Sjhibbits } 325296177Sjhibbits 326296177Sjhibbits /* allocate the blocks bases array */ 327296177Sjhibbits p_Mem->p_Bases = (uint8_t **)XX_Malloc(sizeof(uint8_t*)); 328296177Sjhibbits if (!p_Mem->p_Bases) 329296177Sjhibbits { 330296177Sjhibbits MEM_Free(p_Mem); 331296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array")); 332296177Sjhibbits } 333296177Sjhibbits memset(p_Mem->p_Bases, 0, sizeof(uint8_t*)); 334296177Sjhibbits 335296177Sjhibbits /* store info about this segment */ 336296177Sjhibbits p_Mem->num = num; 337296177Sjhibbits p_Mem->current = 0; 338296177Sjhibbits p_Mem->dataSize = dataSize; 339296177Sjhibbits p_Mem->p_Bases[0] = p_Blocks; 340296177Sjhibbits p_Mem->getFailures = 0; 341296177Sjhibbits p_Mem->allocOwner = e_MEM_ALLOC_OWNER_EXTERNAL; 342296177Sjhibbits p_Mem->consecutiveMem = TRUE; 343296177Sjhibbits p_Mem->prefixSize = prefixSize; 344296177Sjhibbits p_Mem->postfixSize = postfixSize; 345296177Sjhibbits p_Mem->alignment = alignment; 346296177Sjhibbits /* store name */ 347296177Sjhibbits strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1); 348296177Sjhibbits 349296177Sjhibbits p_Mem->h_Spinlock = XX_InitSpinlock(); 350296177Sjhibbits if (!p_Mem->h_Spinlock) 351296177Sjhibbits { 352296177Sjhibbits MEM_Free(p_Mem); 353296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!")); 354296177Sjhibbits } 355296177Sjhibbits 356296177Sjhibbits alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize); 357296177Sjhibbits /* Make sure the entire size is a multiple of alignment */ 358296177Sjhibbits endPad = (uint16_t)PAD_ALIGNMENT(alignment, (alignPad + prefixSize + dataSize + postfixSize)); 359296177Sjhibbits 360296177Sjhibbits /* The following manipulation places the data of block[0] in an aligned address, 361296177Sjhibbits since block size is aligned the following block datas will all be aligned */ 362296177Sjhibbits ALIGN_BLOCK(p_Blocks, prefixSize, alignment); 363296177Sjhibbits 364296177Sjhibbits blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad); 365296177Sjhibbits 366296177Sjhibbits /* initialize the blocks */ 367296177Sjhibbits for (i=0; i < num; i++) 368296177Sjhibbits { 369296177Sjhibbits p_Mem->p_BlocksStack[i] = p_Blocks; 370296177Sjhibbits p_Blocks += blockSize; 371296177Sjhibbits } 372296177Sjhibbits 373296177Sjhibbits /* return handle to caller */ 374296177Sjhibbits *p_Handle = (t_Handle)p_Mem; 375296177Sjhibbits 376296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 377296177Sjhibbits { 378296177Sjhibbits t_Error errCode = InitMemDebugDatabase(p_Mem); 379296177Sjhibbits 380296177Sjhibbits if (errCode != E_OK) 381296177Sjhibbits RETURN_ERROR(MAJOR, errCode, NO_MSG); 382296177Sjhibbits 383296177Sjhibbits p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]); 384296177Sjhibbits p_Mem->blockSize = blockSize; 385296177Sjhibbits } 386296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 387296177Sjhibbits 388296177Sjhibbits return E_OK; 389296177Sjhibbits} 390296177Sjhibbits 391296177Sjhibbits 392296177Sjhibbits/*****************************************************************************/ 393296177Sjhibbitst_Error MEM_InitSmart(char name[], 394296177Sjhibbits t_Handle *p_Handle, 395296177Sjhibbits uint32_t num, 396296177Sjhibbits uint16_t dataSize, 397296177Sjhibbits uint16_t prefixSize, 398296177Sjhibbits uint16_t postfixSize, 399296177Sjhibbits uint16_t alignment, 400296177Sjhibbits uint8_t memPartitionId, 401296177Sjhibbits bool consecutiveMem) 402296177Sjhibbits{ 403296177Sjhibbits t_MemorySegment *p_Mem; 404296177Sjhibbits uint32_t i, blockSize; 405296177Sjhibbits uint16_t alignPad, endPad; 406296177Sjhibbits 407296177Sjhibbits /* prepare in case of error */ 408296177Sjhibbits *p_Handle = NULL; 409296177Sjhibbits 410296177Sjhibbits /* make sure that size is always a multiple of 4 */ 411296177Sjhibbits if (dataSize & 3) 412296177Sjhibbits { 413296177Sjhibbits dataSize &= ~3; 414296177Sjhibbits dataSize += 4; 415296177Sjhibbits } 416296177Sjhibbits 417296177Sjhibbits /* make sure that the alignment is at least 4 and power of 2 */ 418296177Sjhibbits if (alignment < 4) 419296177Sjhibbits { 420296177Sjhibbits alignment = 4; 421296177Sjhibbits } 422296177Sjhibbits else if (!POWER_OF_2(alignment)) 423296177Sjhibbits { 424296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Alignment (should be power of 2)")); 425296177Sjhibbits } 426296177Sjhibbits 427296177Sjhibbits /* first allocate the segment descriptor */ 428296177Sjhibbits p_Mem = (t_MemorySegment *)XX_Malloc(sizeof(t_MemorySegment)); 429296177Sjhibbits if (!p_Mem) 430296177Sjhibbits { 431296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment structure")); 432296177Sjhibbits } 433296177Sjhibbits 434296177Sjhibbits /* allocate the blocks stack */ 435296177Sjhibbits p_Mem->p_BlocksStack = (uint8_t **)XX_Malloc(num * sizeof(uint8_t*)); 436296177Sjhibbits if (!p_Mem->p_BlocksStack) 437296177Sjhibbits { 438296177Sjhibbits MEM_Free(p_Mem); 439296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment block pointers stack")); 440296177Sjhibbits } 441296177Sjhibbits 442296177Sjhibbits /* allocate the blocks bases array */ 443296177Sjhibbits p_Mem->p_Bases = (uint8_t **)XX_Malloc((consecutiveMem ? 1 : num) * sizeof(uint8_t*)); 444296177Sjhibbits if (!p_Mem->p_Bases) 445296177Sjhibbits { 446296177Sjhibbits MEM_Free(p_Mem); 447296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment base pointers array")); 448296177Sjhibbits } 449296177Sjhibbits memset(p_Mem->p_Bases, 0, (consecutiveMem ? 1 : num) * sizeof(uint8_t*)); 450296177Sjhibbits 451296177Sjhibbits /* store info about this segment */ 452296177Sjhibbits p_Mem->num = num; 453296177Sjhibbits p_Mem->current = 0; 454296177Sjhibbits p_Mem->dataSize = dataSize; 455296177Sjhibbits p_Mem->getFailures = 0; 456296177Sjhibbits p_Mem->allocOwner = e_MEM_ALLOC_OWNER_LOCAL_SMART; 457296177Sjhibbits p_Mem->consecutiveMem = consecutiveMem; 458296177Sjhibbits p_Mem->prefixSize = prefixSize; 459296177Sjhibbits p_Mem->postfixSize = postfixSize; 460296177Sjhibbits p_Mem->alignment = alignment; 461296177Sjhibbits 462296177Sjhibbits p_Mem->h_Spinlock = XX_InitSpinlock(); 463296177Sjhibbits if (!p_Mem->h_Spinlock) 464296177Sjhibbits { 465296177Sjhibbits MEM_Free(p_Mem); 466296177Sjhibbits RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't create spinlock!")); 467296177Sjhibbits } 468296177Sjhibbits 469296177Sjhibbits alignPad = (uint16_t)PAD_ALIGNMENT(4, prefixSize); 470296177Sjhibbits /* Make sure the entire size is a multiple of alignment */ 471296177Sjhibbits endPad = (uint16_t)PAD_ALIGNMENT(alignment, alignPad + prefixSize + dataSize + postfixSize); 472296177Sjhibbits 473296177Sjhibbits /* Calculate blockSize */ 474296177Sjhibbits blockSize = (uint32_t)(alignPad + prefixSize + dataSize + postfixSize + endPad); 475296177Sjhibbits 476296177Sjhibbits /* Now allocate the blocks */ 477296177Sjhibbits if (p_Mem->consecutiveMem) 478296177Sjhibbits { 479296177Sjhibbits /* |alignment - 1| bytes at most will be discarded in the beginning of the 480296177Sjhibbits received segment for alignment reasons, therefore the allocation is of: 481296177Sjhibbits (alignment + (num * block size)). */ 482296177Sjhibbits uint8_t *p_Blocks = (uint8_t *) 483296177Sjhibbits XX_MallocSmart((uint32_t)((num * blockSize) + alignment), memPartitionId, 1); 484296177Sjhibbits if (!p_Blocks) 485296177Sjhibbits { 486296177Sjhibbits MEM_Free(p_Mem); 487296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks")); 488296177Sjhibbits } 489296177Sjhibbits 490296177Sjhibbits /* Store the memory segment address */ 491296177Sjhibbits p_Mem->p_Bases[0] = p_Blocks; 492296177Sjhibbits 493296177Sjhibbits /* The following manipulation places the data of block[0] in an aligned address, 494296177Sjhibbits since block size is aligned the following block datas will all be aligned.*/ 495296177Sjhibbits ALIGN_BLOCK(p_Blocks, prefixSize, alignment); 496296177Sjhibbits 497296177Sjhibbits /* initialize the blocks */ 498296177Sjhibbits for (i = 0; i < num; i++) 499296177Sjhibbits { 500296177Sjhibbits p_Mem->p_BlocksStack[i] = p_Blocks; 501296177Sjhibbits p_Blocks += blockSize; 502296177Sjhibbits } 503296177Sjhibbits 504296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 505296177Sjhibbits p_Mem->blockOffset = (uint32_t)(p_Mem->p_BlocksStack[0] - p_Mem->p_Bases[0]); 506296177Sjhibbits p_Mem->blockSize = blockSize; 507296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 508296177Sjhibbits } 509296177Sjhibbits else 510296177Sjhibbits { 511296177Sjhibbits /* |alignment - 1| bytes at most will be discarded in the beginning of the 512296177Sjhibbits received segment for alignment reasons, therefore the allocation is of: 513296177Sjhibbits (alignment + block size). */ 514296177Sjhibbits for (i = 0; i < num; i++) 515296177Sjhibbits { 516296177Sjhibbits uint8_t *p_Block = (uint8_t *) 517296177Sjhibbits XX_MallocSmart((uint32_t)(blockSize + alignment), memPartitionId, 1); 518296177Sjhibbits if (!p_Block) 519296177Sjhibbits { 520296177Sjhibbits MEM_Free(p_Mem); 521296177Sjhibbits RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory segment blocks")); 522296177Sjhibbits } 523296177Sjhibbits 524296177Sjhibbits /* Store the memory segment address */ 525296177Sjhibbits p_Mem->p_Bases[i] = p_Block; 526296177Sjhibbits 527296177Sjhibbits /* The following places the data of each block in an aligned address */ 528296177Sjhibbits ALIGN_BLOCK(p_Block, prefixSize, alignment); 529296177Sjhibbits 530296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 531296177Sjhibbits /* Need 4 bytes before the meaningful bytes to store the block index. 532296177Sjhibbits We know we have them because alignment is at least 4 bytes. */ 533296177Sjhibbits if (p_Block == p_Mem->p_Bases[i]) 534296177Sjhibbits p_Block += alignment; 535296177Sjhibbits 536296177Sjhibbits *(uint32_t *)(p_Block - 4) = i; 537296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 538296177Sjhibbits 539296177Sjhibbits p_Mem->p_BlocksStack[i] = p_Block; 540296177Sjhibbits } 541296177Sjhibbits } 542296177Sjhibbits 543296177Sjhibbits /* store name */ 544296177Sjhibbits strncpy(p_Mem->name, name, MEM_MAX_NAME_LENGTH-1); 545296177Sjhibbits 546296177Sjhibbits /* return handle to caller */ 547296177Sjhibbits *p_Handle = (t_Handle)p_Mem; 548296177Sjhibbits 549296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 550296177Sjhibbits { 551296177Sjhibbits t_Error errCode = InitMemDebugDatabase(p_Mem); 552296177Sjhibbits 553296177Sjhibbits if (errCode != E_OK) 554296177Sjhibbits RETURN_ERROR(MAJOR, errCode, NO_MSG); 555296177Sjhibbits } 556296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 557296177Sjhibbits 558296177Sjhibbits return E_OK; 559296177Sjhibbits} 560296177Sjhibbits 561296177Sjhibbits 562296177Sjhibbits/*****************************************************************************/ 563296177Sjhibbitsvoid MEM_Free(t_Handle h_Mem) 564296177Sjhibbits{ 565296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment*)h_Mem; 566296177Sjhibbits uint32_t num, i; 567296177Sjhibbits 568296177Sjhibbits /* Check MEM leaks */ 569296177Sjhibbits MEM_CheckLeaks(h_Mem); 570296177Sjhibbits 571296177Sjhibbits if (p_Mem) 572296177Sjhibbits { 573296177Sjhibbits num = p_Mem->consecutiveMem ? 1 : p_Mem->num; 574296177Sjhibbits 575296177Sjhibbits if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL_SMART) 576296177Sjhibbits { 577296177Sjhibbits for (i=0; i < num; i++) 578296177Sjhibbits { 579296177Sjhibbits if (p_Mem->p_Bases[i]) 580296177Sjhibbits { 581296177Sjhibbits XX_FreeSmart(p_Mem->p_Bases[i]); 582296177Sjhibbits } 583296177Sjhibbits } 584296177Sjhibbits } 585296177Sjhibbits else if (p_Mem->allocOwner == e_MEM_ALLOC_OWNER_LOCAL) 586296177Sjhibbits { 587296177Sjhibbits for (i=0; i < num; i++) 588296177Sjhibbits { 589296177Sjhibbits if (p_Mem->p_Bases[i]) 590296177Sjhibbits { 591296177Sjhibbits XX_Free(p_Mem->p_Bases[i]); 592296177Sjhibbits } 593296177Sjhibbits } 594296177Sjhibbits } 595296177Sjhibbits 596296177Sjhibbits if (p_Mem->h_Spinlock) 597296177Sjhibbits XX_FreeSpinlock(p_Mem->h_Spinlock); 598296177Sjhibbits 599296177Sjhibbits if (p_Mem->p_Bases) 600296177Sjhibbits XX_Free(p_Mem->p_Bases); 601296177Sjhibbits 602296177Sjhibbits if (p_Mem->p_BlocksStack) 603296177Sjhibbits XX_Free(p_Mem->p_BlocksStack); 604296177Sjhibbits 605296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 606296177Sjhibbits if (p_Mem->p_MemDbg) 607296177Sjhibbits XX_Free(p_Mem->p_MemDbg); 608296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 609296177Sjhibbits 610296177Sjhibbits XX_Free(p_Mem); 611296177Sjhibbits } 612296177Sjhibbits} 613296177Sjhibbits 614296177Sjhibbits 615296177Sjhibbits/*****************************************************************************/ 616296177Sjhibbitsvoid * MEM_Get(t_Handle h_Mem) 617296177Sjhibbits{ 618296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 619296177Sjhibbits uint8_t *p_Block; 620296177Sjhibbits uint32_t intFlags; 621296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 622296177Sjhibbits uintptr_t callerAddr = 0; 623296177Sjhibbits 624296177Sjhibbits GET_CALLER_ADDR; 625296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 626296177Sjhibbits 627296177Sjhibbits ASSERT_COND(h_Mem); 628296177Sjhibbits 629296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock); 630296177Sjhibbits /* check if there is an available block */ 631296177Sjhibbits if ((p_Block = (uint8_t *)MemGet(p_Mem)) == NULL) 632296177Sjhibbits { 633296177Sjhibbits XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 634296177Sjhibbits return NULL; 635296177Sjhibbits } 636296177Sjhibbits 637296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 638296177Sjhibbits DebugMemGet(p_Mem, p_Block, callerAddr); 639296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 640296177Sjhibbits XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 641296177Sjhibbits 642296177Sjhibbits return (void *)p_Block; 643296177Sjhibbits} 644296177Sjhibbits 645296177Sjhibbits 646296177Sjhibbits/*****************************************************************************/ 647296177Sjhibbitsuint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[]) 648296177Sjhibbits{ 649296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 650296177Sjhibbits uint32_t availableBlocks; 651296177Sjhibbits register uint32_t i; 652296177Sjhibbits uint32_t intFlags; 653296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 654296177Sjhibbits uintptr_t callerAddr = 0; 655296177Sjhibbits 656296177Sjhibbits GET_CALLER_ADDR; 657296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 658296177Sjhibbits 659296177Sjhibbits ASSERT_COND(h_Mem); 660296177Sjhibbits 661296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock); 662296177Sjhibbits /* check how many blocks are available */ 663296177Sjhibbits availableBlocks = (uint32_t)(p_Mem->num - p_Mem->current); 664296177Sjhibbits if (num > availableBlocks) 665296177Sjhibbits { 666296177Sjhibbits num = availableBlocks; 667296177Sjhibbits } 668296177Sjhibbits 669296177Sjhibbits for (i=0; i < num; i++) 670296177Sjhibbits { 671296177Sjhibbits /* get pointer to block */ 672296177Sjhibbits if ((array[i] = MemGet(p_Mem)) == NULL) 673296177Sjhibbits { 674296177Sjhibbits break; 675296177Sjhibbits } 676296177Sjhibbits 677296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 678296177Sjhibbits DebugMemGet(p_Mem, array[i], callerAddr); 679296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 680296177Sjhibbits } 681296177Sjhibbits XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 682296177Sjhibbits 683296177Sjhibbits return (uint16_t)i; 684296177Sjhibbits} 685296177Sjhibbits 686296177Sjhibbits 687296177Sjhibbits/*****************************************************************************/ 688296177Sjhibbitst_Error MEM_Put(t_Handle h_Mem, void *p_Block) 689296177Sjhibbits{ 690296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 691296177Sjhibbits t_Error rc; 692296177Sjhibbits uint32_t intFlags; 693296177Sjhibbits 694296177Sjhibbits ASSERT_COND(h_Mem); 695296177Sjhibbits 696296177Sjhibbits intFlags = XX_LockIntrSpinlock(p_Mem->h_Spinlock); 697296177Sjhibbits /* check if blocks stack is full */ 698296177Sjhibbits if ((rc = MemPut(p_Mem, p_Block)) != E_OK) 699296177Sjhibbits { 700296177Sjhibbits XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 701296177Sjhibbits RETURN_ERROR(MAJOR, rc, NO_MSG); 702296177Sjhibbits } 703296177Sjhibbits 704296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 705296177Sjhibbits DebugMemPut(p_Mem, p_Block); 706296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 707296177Sjhibbits XX_UnlockIntrSpinlock(p_Mem->h_Spinlock, intFlags); 708296177Sjhibbits 709296177Sjhibbits return E_OK; 710296177Sjhibbits} 711296177Sjhibbits 712296177Sjhibbits 713296177Sjhibbits#ifdef DEBUG_MEM_LEAKS 714296177Sjhibbits 715296177Sjhibbits/*****************************************************************************/ 716296177Sjhibbitsvoid MEM_CheckLeaks(t_Handle h_Mem) 717296177Sjhibbits{ 718296177Sjhibbits t_MemorySegment *p_Mem = (t_MemorySegment *)h_Mem; 719296177Sjhibbits t_MemDbg *p_MemDbg = (t_MemDbg *)p_Mem->p_MemDbg; 720296177Sjhibbits uint8_t *p_Block; 721296177Sjhibbits int i; 722296177Sjhibbits 723296177Sjhibbits ASSERT_COND(h_Mem); 724296177Sjhibbits 725296177Sjhibbits if (p_Mem->consecutiveMem) 726296177Sjhibbits { 727296177Sjhibbits for (i=0; i < p_Mem->num; i++) 728296177Sjhibbits { 729296177Sjhibbits if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE) 730296177Sjhibbits { 731296177Sjhibbits /* Find the block address */ 732296177Sjhibbits p_Block = ((p_Mem->p_Bases[0] + p_Mem->blockOffset) + 733296177Sjhibbits (i * p_Mem->blockSize)); 734296177Sjhibbits 735296177Sjhibbits XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n", 736296177Sjhibbits p_Block, p_MemDbg[i].ownerAddress); 737296177Sjhibbits } 738296177Sjhibbits } 739296177Sjhibbits } 740296177Sjhibbits else 741296177Sjhibbits { 742296177Sjhibbits for (i=0; i < p_Mem->num; i++) 743296177Sjhibbits { 744296177Sjhibbits if (p_MemDbg[i].ownerAddress != ILLEGAL_BASE) 745296177Sjhibbits { 746296177Sjhibbits /* Find the block address */ 747296177Sjhibbits p_Block = p_Mem->p_Bases[i]; 748296177Sjhibbits 749296177Sjhibbits ALIGN_BLOCK(p_Block, p_Mem->prefixSize, p_Mem->alignment); 750296177Sjhibbits 751296177Sjhibbits if (p_Block == p_Mem->p_Bases[i]) 752296177Sjhibbits p_Block += p_Mem->alignment; 753296177Sjhibbits 754296177Sjhibbits XX_Print("MEM leak: 0x%08x, Caller address: 0x%08x\n", 755296177Sjhibbits p_Block, p_MemDbg[i].ownerAddress); 756296177Sjhibbits } 757296177Sjhibbits } 758296177Sjhibbits } 759296177Sjhibbits} 760296177Sjhibbits 761296177Sjhibbits#endif /* DEBUG_MEM_LEAKS */ 762296177Sjhibbits 763296177Sjhibbits 764