Пример #1
0
/*********************************************************************
 * @fn      osal_mem_free
 *
 * @brief   Implementation of the de-allocator functionality.
 *
 * @param   ptr - pointer to the memory to free.
 *
 * @return  void
 */
void osal_mem_free( void *ptr )
{
  osalMemHdr_t *currHdr;
  halIntState_t intState;

#if ( OSALMEM_GUARD )
  // Try to protect against premature use by HAL / OSAL.
  if ( ready != OSALMEM_READY )
  {
    osal_mem_init();
  }
#endif

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  OSALMEM_ASSERT( ptr );

  currHdr = (osalMemHdr_t *)ptr - 1;

  // Has this block already been freed?
  OSALMEM_ASSERT( *currHdr & OSALMEM_IN_USE );

  *currHdr &= ~OSALMEM_IN_USE;

#if ( OSALMEM_PROFILER )
  {
    uint16 size = *currHdr;
    byte idx;

    for ( idx = 0; idx < OSALMEM_PROMAX; idx++ )
    {
      if ( size <= proCnt[idx] )
      {
        break;
      }
    }

    proCur[idx]--;
  }
#endif

#if ( OSALMEM_METRICS )
  memAlo -= *currHdr;
  blkFree++;
#endif

  if ( ff1 > currHdr )
  {
    ff1 = currHdr;
  }

#if ( OSALMEM_PROFILER )
  osal_memset( (byte *)currHdr+HDRSZ, OSALMEM_REIN, (*currHdr - HDRSZ) );
#endif

  HAL_EXIT_CRITICAL_SECTION( intState );  // Re-enable interrupts.
}
Пример #2
0
/*********************************************************************
 * @fn      osal_mem_alloc
 *
 * @brief   Implementation of the allocator functionality.
 *
 * @param   size - number of bytes to allocate from the heap.
 *
 * @return  void * - pointer to the heap allocation; NULL if error or failure.
 */
void *osal_mem_alloc( uint16 size )
{
  osalMemHdr_t *prev = NULL;
  osalMemHdr_t *hdr;
  halIntState_t intState;
  uint16 tmp;
  uint8 coal = 0;

  OSALMEM_ASSERT( size );

  size += HDRSZ;

  // Calculate required bytes to add to 'size' to align to halDataAlign_t.
  if ( sizeof( halDataAlign_t ) == 2 )
  {
    size += (size & 0x01);
  }
  else if ( sizeof( halDataAlign_t ) != 1 )
  {
    const uint8 mod = size % sizeof( halDataAlign_t );

    if ( mod != 0 )
    {
      size += (sizeof( halDataAlign_t ) - mod);
    }
  }

  HAL_ENTER_CRITICAL_SECTION( intState );  // Hold off interrupts.

  // Smaller allocations are first attempted in the small-block bucket.
  if ( size <= OSALMEM_SMALL_BLKSZ )
  {
    hdr = ff1;
  }
  else
  {
    hdr = ff2;
  }
  tmp = *hdr;

  do
  {
    if ( tmp & OSALMEM_IN_USE )
    {
      tmp ^= OSALMEM_IN_USE;
      coal = 0;
    }
    else
    {
      if ( coal != 0 )
      {
#if ( OSALMEM_METRICS )
        blkCnt--;
        blkFree--;
#endif

        *prev += *hdr;

        if ( *prev >= size )
        {
          hdr = prev;
          tmp = *hdr;
          break;
        }
      }
      else
      {
        if ( tmp >= size )
        {
          break;
        }

        coal = 1;
        prev = hdr;
      }
    }

    hdr = (osalMemHdr_t *)((uint8 *)hdr + tmp);

    tmp = *hdr;
    if ( tmp == 0 )
    {
      hdr = NULL;
      break;
    }


  } while ( 1 );

  if ( hdr != NULL )
  {
    tmp -= size;

    // Determine whether the threshold for splitting is met.
    if ( tmp >= OSALMEM_MIN_BLKSZ )
    {
      // Split the block before allocating it.
      osalMemHdr_t *next = (osalMemHdr_t *)((uint8 *)hdr + size);
      *next = tmp;
      *hdr = (size | OSALMEM_IN_USE);

#if ( OSALMEM_METRICS )
      blkCnt++;
      if ( blkMax < blkCnt )
      {
        blkMax = blkCnt;
      }
      memAlo += size;
#endif
    }
    else
    {
#if ( OSALMEM_METRICS )
      memAlo += *hdr;
      blkFree--;
#endif

      *hdr |= OSALMEM_IN_USE;
    }

#if ( OSALMEM_METRICS )
    if ( memMax < memAlo )
    {
      memMax = memAlo;
    }
#endif

#if ( OSALMEM_PROFILER )
  {
    uint8 idx;
    size = *hdr ^ OSALMEM_IN_USE;

    for ( idx = 0; idx < OSALMEM_PROMAX; idx++ )
    {
      if ( size <= proCnt[idx] )
      {
        break;
      }
    }
    proCur[idx]++;
    if ( proMax[idx] < proCur[idx] )
    {
      proMax[idx] = proCur[idx];
    }
    proTot[idx]++;
  }
#endif

    hdr++;

#if ( OSALMEM_PROFILER )
    (void)osal_memset( (uint8 *)hdr, OSALMEM_ALOC, (size - HDRSZ) );

    /* A small-block could not be allocated in the small-block bucket.
     * When this occurs significantly frequently, increase the size of the
     * bucket in order to restore better worst case run times. Set the first
     * profiling bucket size in proCnt[] to the small-block bucket size and
     * divide proSmallBlkMiss by the corresponding proTot[] size to get % miss.
     * Best worst case time on TrasmitApp was achieved at a 0-15% miss rate
     * during steady state Tx load, 0% during idle and steady state Rx load.
     */
    if ( (size <= OSALMEM_SMALL_BLKSZ) && (hdr > ff2) )
    {
      proSmallBlkMiss++;
    }
#endif
  }

  HAL_EXIT_CRITICAL_SECTION( intState );  // Re-enable interrupts.

  return (void *)hdr;
}