Threadx 字節內存池內存釋放_tx_byte_release

_tx_byte_release

_tx_byte_release用於內存釋放,原理參考上篇博文:Threadx 內存管理-內存字節池

UINT    _tx_byte_release(VOID *memory_ptr)
{

    TX_INTERRUPT_SAVE_AREA

    REG_1   TX_BYTE_POOL    *pool_ptr;          /* Pool pointer               */
    REG_2   TX_THREAD       *thread_ptr;        /* Working thread pointer     */
    REG_3   CHAR_PTR        work_ptr;           /* Working block pointer      */
    REG_4   TX_THREAD       *susp_thread_ptr;   /* Suspended thread pointer   */
    UINT                    preempt =  0;       /* Preemption counter         */


    /* Determine if the memory pointer is valid.  */
    #def 記錄要釋放內存起始地址
    work_ptr = (CHAR_PTR) memory_ptr;
    if (work_ptr)
    {

        /* Back off the memory pointer to pickup its header.  */
        #def 後退sizeof(CHAR_PTR) +sizeof(ULONG)字節是所在塊內存控制字段首地址
        work_ptr = work_ptr - sizeof(CHAR_PTR) - sizeof(ULONG);

        /* There is a pointer, pickup the pool pointer address.  */
        #def 檢查控制字段,第4到8字節,不等於TX_BYTE_BLOCK_FREE,說明不是空閒內存
        if (*((ULONG_PTR)(work_ptr + sizeof(CHAR_PTR))) != TX_BYTE_BLOCK_FREE)
        {

            /* Pickup the pool pointer.  */
            #def 第4到8字節存儲了內存池管理結構指針
            pool_ptr = (TX_BYTE_POOL *) * ((TX_BYTE_POOL **)(work_ptr + sizeof(CHAR_PTR)));

            /* See if we have a valid pool.  */
            #def 檢查內存池管理結構指針,內存池是否有效
            if ((!pool_ptr) || (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID))
                return (TX_PTR_ERROR);
        }
        else
            return (TX_PTR_ERROR);
    }
    else
        return (TX_PTR_ERROR);

    /* At this point, we know that the pointer is valid.  */

    /* Pickup the thread pointer.  */
    #def 記錄當前線程
    thread_ptr =  _tx_thread_current_ptr;

    /* Indicate that this thread is the current owner.  */
    #def 設置當前線程爲內存池擁有者
    pool_ptr -> tx_byte_pool_owner =  thread_ptr;

    /* Lockout interrupts.  */
    #def 禁止中斷,防止打斷
    TX_DISABLE

    /* Release the memory.  */
    #def 釋放內存,標記爲TX_BYTE_BLOCK_FREE,成爲空閒塊
    *((ULONG_PTR)(work_ptr + sizeof(CHAR_PTR))) =  TX_BYTE_BLOCK_FREE;

    /* Update the number of available bytes in the pool.  */
    #def 增加可用內存*((CHAR_PTR *)(work_ptr))爲相鄰的下一塊內存地址,(*((CHAR_PTR *)(work_ptr)) - work_ptr)就是本塊內存的大小了
    pool_ptr -> tx_byte_pool_available =
        pool_ptr -> tx_byte_pool_available + (*((CHAR_PTR *)(work_ptr)) - work_ptr);

    /* Update the search pointer to the released block.  */
    #def 本塊內存已經釋放,那麼搜索的起始地址更新爲本快內存起始地址,下一次搜索從這一塊空閒內存開始
    pool_ptr -> tx_byte_pool_search =  work_ptr;

    /* Now examine the suspension list to find threads waiting for
       memory.  Maybe it is now available!  */
    #def 釋放完內存後,檢查掛起list中是否有線程掛起,如果有,嘗試爲這些線程申請內存並恢復線程
    while (pool_ptr -> tx_byte_pool_suspended_count)
    {

        /* Pickup the first suspended thread pointer.  */
        susp_thread_ptr =  pool_ptr -> tx_byte_pool_suspension_list;

        /* Restore interrupts.  */
        #def打開中斷,之後高優先級線程可能打斷,也從這個內存池申請內存,導致剛剛釋放的內存被佔用。 
        #def 開中斷後,掛起線程也可能恢復,或中止
        TX_RESTORE

        /* See if the request can be satisfied.  */
        #def 搜索是否有合適內存,susp_thread_ptr -> tx_suspend_info爲之前tx_byte_allocate中線程掛起時保存的申請內存大小
        work_ptr =  _tx_byte_pool_search(pool_ptr, susp_thread_ptr -> tx_suspend_info);

        /* Disable interrupts.  */
        #def 禁止中斷
        TX_DISABLE

        /* If there is not enough memory, break this loop!  */
        #def 申請失敗,直接跳出,不在申請。  
        if (!work_ptr)
            break;

        /* Check to make sure the thread is still suspended.  */
        #def 再次檢查susp_thread_ptr 線程釋放還在掛起list中,因爲前面開中斷,掛起線程可能恢復,中止等。
        if (susp_thread_ptr !=  pool_ptr -> tx_byte_pool_suspension_list)
        {
			#def susp_thread_ptr 不在掛起list中了,把剛剛申請的內存釋放
            /* Put the memory back on the available list since this thread is no longer
               suspended.  */
            
            work_ptr = work_ptr - sizeof(CHAR_PTR) - sizeof(ULONG);
            
            *((ULONG_PTR)(work_ptr + sizeof(CHAR_PTR))) =  TX_BYTE_BLOCK_FREE;

            /* Update the number of available bytes in the pool.  */
            pool_ptr -> tx_byte_pool_available =
                pool_ptr -> tx_byte_pool_available + (*((CHAR_PTR *)(work_ptr)) - work_ptr);

            /* Start at the top of this loop.  */
            #def 繼續處理下一個掛起線程
            continue;
        }

        /* Remove the suspended thread from the list.  */

        /* See if this is the only suspended thread on the list.  */
        #def 申請成功,線程還在掛起list中
        #def 把這個線程從tx_byte_pool_suspension_list移除,並恢復線程
        if (susp_thread_ptr == susp_thread_ptr -> tx_suspended_next)
        {

            /* Yes, the only suspended thread.  */

            /* Update the head pointer.  */
            pool_ptr -> tx_byte_pool_suspension_list =  TX_NULL;
        }
        else
        {

            /* At least one more thread is on the same expiration list.  */

            /* Update the list head pointer.  */
            pool_ptr -> tx_byte_pool_suspension_list =  susp_thread_ptr -> tx_suspended_next;

            /* Update the links of the adjacent threads.  */
            (susp_thread_ptr -> tx_suspended_next) -> tx_suspended_previous =
                susp_thread_ptr -> tx_suspended_previous;
            (susp_thread_ptr -> tx_suspended_previous) -> tx_suspended_next =
                susp_thread_ptr -> tx_suspended_next;
        }

        /* Decrement the suspension count.  */
        pool_ptr -> tx_byte_pool_suspended_count--;

        /* Prepare for resumption of the thread.  */

        /* Clear cleanup routine to avoid timeout.  */
        susp_thread_ptr -> tx_suspend_cleanup =  TX_NULL;

        /* Temporarily disable preemption.  */
        _tx_thread_preempt_disable++;

        /* Restore interrupts.  */
        TX_RESTORE

        /* Return this block pointer to the suspended thread waiting for
           a block.  */
        #def tx_additional_suspend_info中保存了線程調用tx_byte_allocate是記錄內存地址返回的參數
        *((CHAR_PTR *) susp_thread_ptr -> tx_additional_suspend_info) = (CHAR_PTR) work_ptr;

        /* Deactivate the timeout timer if necessary.  */
        if (susp_thread_ptr -> tx_thread_timer.tx_list_head)
        {

            /* Deactivate the thread's timeout timer.  */
            _tx_timer_deactivate(&(susp_thread_ptr -> tx_thread_timer));
        }
        else
        {

            /* Clear the remaining time, just in case it hasn't started yet.  */
            susp_thread_ptr -> tx_thread_timer.tx_remaining_ticks =  0;
        }

        /* Put return status into the thread control block.  */
        #def 設置爲成功,線程恢復後,從tx_byte_allocate函數返回時的返回值
        susp_thread_ptr -> tx_suspend_status =  TX_SUCCESS;

        /* Resume thread.  */
        #def preempt記錄_tx_thread_resume返回true統計
        preempt =  preempt + _tx_thread_resume(susp_thread_ptr);

        /* Lockout interrupts.  */
        TX_DISABLE
    }

    /* Restore interrupts.  */
    TX_RESTORE

    /* Check for preemption.  */
    #def 有高優先級線程恢復,需要切換
    if (preempt)
    {
        /* Preemption is required, transfer control back to
           system.  */
        _tx_thread_system_return();
    }

    /* Return completion status.  */
    return (TX_SUCCESS);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章