The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ncsw/etc/ncsw_mem.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 /*****************************************************************************/
   65 static __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 /*****************************************************************************/
   88 static __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 /*****************************************************************************/
  107 static 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 /*****************************************************************************/
  122 static 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 /*****************************************************************************/
  150 static 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 /*****************************************************************************/
  209 uint32_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 /*****************************************************************************/
  234 t_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 /*****************************************************************************/
  278 t_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 /*****************************************************************************/
  394 t_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 /*****************************************************************************/
  564 void 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 /*****************************************************************************/
  617 void * 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 /*****************************************************************************/
  648 uint16_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 /*****************************************************************************/
  689 t_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 /*****************************************************************************/
  717 void 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

Cache object: e5a46013e47732b8cc99bcfd64ddeaa2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.