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