Threadx 字节内存池内存释放_tx_byte_release

旧城冷巷雨未停 提交于 2020-02-11 12:30:12

_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);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!