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/*****************************************************************************/
64static __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/*****************************************************************************/
87static __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/*****************************************************************************/
106static 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/*****************************************************************************/
121static 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/*****************************************************************************/
149static 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/*****************************************************************************/
208uint32_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/*****************************************************************************/
233t_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/*****************************************************************************/
277t_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/*****************************************************************************/
393t_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/*****************************************************************************/
563void 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/*****************************************************************************/
616void * 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/*****************************************************************************/
647uint16_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/*****************************************************************************/
688t_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/*****************************************************************************/
716void 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