_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);
}
来源:CSDN
作者:osnet
链接:https://blog.csdn.net/qq_45683435/article/details/104259293