📄 heap.c
字号:
HEAPNODE * volatile * npp;HEAPNODE * fnode;#ifdef DO_CRITICAL NutEnterCritical( );#endif#ifdef NUTDEBUG if ( block == 0 ) { NutPrintString_P( log_dev, PSTR( "\r\nMEMnull" ) );#ifdef DO_CRITICAL NutExitCritical( );#endif return -1; }#endif /* * Convert our block into a node. */ fnode = (HEAPNODE *)( (u_char *)block - HEAP_HEAD_SIZE ); CheckHeapGuards( fnode, PSTR( "free" ) );#ifdef NUTDEBUG if ( heap_trace != 0 ) NutPrintFormat_P( log_dev, PSTR( "F(%d,%x) " ), fnode->hn_size, (u_short)block );#endif available += fnode->hn_size;#ifdef USED_HEAP_LIST RemoveFromUsedList( fnode );#endif /* * Walk through the linked list of free nodes and try * to link us in. */ node = heapFreeList; npp = &heapFreeList; while ( node != 0 ) { /* * If there' s a free node in front of us, merge it. */ if ( ( (u_short)node + node->hn_size ) == (u_short)fnode ) { CheckHeapGuards( node, PSTR( "prev" ) ); node->hn_size += fnode->hn_size; /* * If a free node is following us, merge it. */ if ( ( (u_short)node + node->hn_size ) == (u_short)node->hn_next ) { CheckHeapGuards( node->hn_next, PSTR( "next" ) ); node->hn_size += node->hn_next->hn_size; node->hn_next = node->hn_next->hn_next; } AddHeapGuards( node ); break; } /* * If we walked past our address, link us to the list. */ if ( (u_short)node > (u_short)fnode ) { *npp = fnode; /* * If a free node is following us, merge it. */ if ( ( (u_short)fnode + fnode->hn_size ) == (u_short)node ) { fnode->hn_size += node->hn_size; fnode->hn_next = node->hn_next; } else fnode->hn_next = node; break; } /* * If we are within a free node, somebody tried * to free a block twice. */ if ( ( (u_short)node + node->hn_size) > (u_short)fnode ) {#ifdef NUTDEBUG if ( heap_trace != 0 ) NutPrintString_P( log_dev, PSTR( "\r\nTWICE\r\n" ) );#endif#ifdef DO_CRITICAL NutExitCritical( );#endif return -1; } npp = &node->hn_next; node = node->hn_next; } /* * If no link was found, put us at the end of the list */ if ( node == 0 ) { fnode->hn_next = node; *npp = fnode; }#ifdef DO_CRITICAL NutExitCritical( );#endif return 0;}//--------------------------------------------------------------------------///*! * \brief * Add a new memory region to the free heap. * * This function is automatically called by Nut/OS during * initialization. * * Applications typically do not call this function. * * \param addr Start address of the memory region. * \param size Number of bytes of the memory region. */void NutHeapAdd( void * addr, u_short size ){HEAPNODE * p_node; p_node = (HEAPNODE *)addr;#ifdef DO_CRITICAL NutEnterCritical( );#endif // Pretend this is a clean block so no errors appear. p_node->hn_size = size; AddHeapGuards( p_node );#ifdef USED_HEAP_LIST InsertInUsedList( p_node );#else p_node->hn_next = 0;#endif#ifdef DO_CRITICAL NutExitCritical( );#endif NutHeapFree( (void *)( (char *)addr + HEAP_HEAD_SIZE ) );}//--------------------------------------------------------------------------///*! * \brief Return the number of bytes available. * * \return Number of bytes. */u_short NutHeapAvailable( void ){ return available;}//--------------------------------------------------------------------------//u_char NutHeapCheckGuards1( void * block ){ return NutHeapCheckGuards2( (HEAPNODE *)( (char *)block - HEAP_HEAD_SIZE ) );}//--------------------------------------------------------------------------//u_char NutHeapCheckGuards2( HEAPNODE * p_node ){u_char ret = 0;#ifdef FRONT_GUARDED_HEAP if ( p_node->hn_guard != deadmeat ) ret = 2;#endif if ( ( (HEAPTAIL *)( (char *)p_node + p_node->hn_size - HEAP_TAIL_SIZE ) )->ht_guard != deadmeat ) ret += 1; return ret;}//--------------------------------------------------------------------------//static void AddHeapGuards( HEAPNODE * p_node ){#ifdef FRONT_GUARDED_HEAP p_node->hn_guard = deadmeat;#endif ( (HEAPTAIL *)( (char *)p_node + p_node->hn_size - HEAP_TAIL_SIZE ) )->ht_guard = deadmeat;}//--------------------------------------------------------------------------//static u_char CheckHeapGuards( HEAPNODE * p_node, PGM_P str ){HEAPTAIL * p_tail;u_char ret = 0;int slime;#ifdef NUTDEBUGchar temp[ 20 ];#endif#ifdef FRONT_GUARDED_HEAP if ( p_node->hn_guard != deadmeat ) { ret = 2; // determine how many bytes got slimed. if ( ( p_node->hn_guard & slime_1 ) == ( deadmeat & slime_1 ) ) slime = 1; else { if ( ( p_node->hn_guard & slime_2 ) == ( deadmeat & slime_2 ) ) slime = 2; else { if ( ( p_node->hn_guard & slime_3 ) == ( deadmeat & slime_3 ) ) slime = 3; else slime = 4; } }#ifdef NUTDEBUG /* This will not work on ICCAVR */ strncpy_P( temp, str, 19 ); NutPrintFormat( 0, "\r\nMEMCORRUPT-%s-%d-%d\r\n", temp, p_node->hn_size, slime );#endif }#endif p_tail = (HEAPTAIL *)( (char *)p_node + p_node->hn_size - HEAP_TAIL_SIZE ); if ( p_tail->ht_guard != deadmeat ) { ret += 1; // determine how many bytes got slimed. if ( ( p_tail->ht_guard & slime_1 ) == ( deadmeat & slime_1 ) ) slime = 1; else { if ( ( p_tail->ht_guard & slime_2 ) == ( deadmeat & slime_2 ) ) slime = 2; else { if ( ( p_tail->ht_guard & slime_3 ) == ( deadmeat & slime_3 ) ) slime = 3; else slime = 4; } }#ifdef NUTDEBUG /* This will not work on ICCAVR */ strncpy_P( temp, str, 19 ); NutPrintFormat( log_dev, "\r\nMemCorrupt-%s-%d-%d\r\n", temp, p_node->hn_size, slime );#endif } return ret;}//--------------------------------------------------------------------------//#ifdef USED_HEAP_LISTstatic void InsertInUsedList( HEAPNODE *p_node ){HEAPNODE * p_used;HEAPNODE * volatile * pp_prev; p_used = heapUsedList; pp_prev = &heapUsedList; while ( p_used != 0 ) { if ( p_used->hn_next > p_node ) { p_node->hn_next = ( *pp_prev )->hn_next; ( *pp_prev )->hn_next = p_node; break; } pp_prev = &p_used->hn_next; p_used = p_used->hn_next; } if ( p_used == 0 ) { p_node->hn_next = heapUsedList; heapUsedList = p_node; }}#endif//--------------------------------------------------------------------------//#ifdef USED_HEAP_LISTstatic void RemoveFromUsedList( HEAPNODE *p_node ){HEAPNODE * volatile * pp_used; pp_used = &heapUsedList; while ( *pp_used != 0 ) { if ( *pp_used == p_node ) { *pp_used = ( *pp_used )->hn_next; break; } pp_used = &( *pp_used )->hn_next; }#ifdef NUTDEBUG if ( *pp_used == 0 ) NutPrintString( log_dev, "\r\nMemCorrupt-used\r\n" );#endif}#endif/*@}*///*************************** end of file HEAP.C ***************************//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -