/********************************************************************* * @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. }
/********************************************************************* * @fn osal_init_system * * @brief * * This function initializes the "task" system by creating the * tasks defined in the task table (OSAL_Tasks.h). * * @param void * * @return ZSUCCESS */ uint8 osal_init_system( void ) { // Initialize the Memory Allocation System osal_mem_init(); // Initialize the message queue osal_qHead = NULL; #if defined( OSAL_TOTAL_MEM ) osal_msg_cnt = 0; #endif osalTimerInit(); osal_init_TaskHead(); return ( ZSUCCESS ); }
/********************************************************************* * @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; osalMemHdr_t *hdr; halIntState_t intState; uint16 tmp; byte coal = 0; #if ( OSALMEM_GUARD ) // Try to protect against premature use by HAL / OSAL. if ( ready != OSALMEM_READY ) { osal_mem_init(); } #endif 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 byte 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 *)((byte *)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 *)((byte *)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 ) { byte 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 ) osal_memset( (byte *)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; }