_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);
}