tx_block_allocate
应用程序调用tx_block_allocate申请分配内存。
pool_ptr指向内存池指针
block_ptr指向指针的指针,用于存储申请的内存起始地址
wait_option等待选项,
如果没有足够内存,wait_option为0,直接返回;wait_option为TX_WAIT_FOREVER,永久挂起;
wait_option不为0,也不是TX_WAIT_FOREVER,开启定时器,定时值为wait_option。定时器超时,线程恢复,并清除相关数据。
如果有空闲内存,直接返回tx_block_pool_available_list指向的内存块;
如果内存不够,可以挂起线程到tx_block_pool_suspension_list链表,其他线程内存释放后,恢复挂起的线程。
UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option)
{
TX_INTERRUPT_SAVE_AREA
REG_1 UINT status; /* Return status */
REG_2 TX_THREAD *thread_ptr; /* Working thread pointer */
REG_3 CHAR_PTR work_ptr; /* Working block pointer */
/* Disable interrupts to get a block from the pool. */
#def 禁止中断,防止打断
TX_DISABLE
/* Determine if there is an available block. */
#def 检查是否还有可用内存块
if (pool_ptr -> tx_block_pool_available)
{
#def 有可用内存块
/* Yes, a block is available. Decrement the available count. */
#def 可用内存块个数减1
pool_ptr -> tx_block_pool_available--;
/* Pickup the current block pointer. */
#def tx_block_pool_available_list指向可用内存链表中最前面块,返回给最前面块给用户
work_ptr = pool_ptr -> tx_block_pool_available_list;
/* Return the first available block to the caller. */
#def 设置入参,址传递, 需要跨过控制字段sizeof(CHAR_PTR)
*((CHAR_PTR *) block_ptr) = work_ptr + sizeof(CHAR_PTR);
/* Modify the available list to point at the next block in the pool. */
#def *((CHAR_PTR *) work_ptr)中存储的是下一空闲块,下一空变为头部
pool_ptr -> tx_block_pool_available_list =
*((CHAR_PTR *) work_ptr);
/* Save the pool's address in the block for when it is released! */
#def 把刚刚分配的块控制字段存储内存池管理结构指针
*((CHAR_PTR *) work_ptr) = (CHAR_PTR) pool_ptr;
/* Set status to success. */
status = TX_SUCCESS;
}
else
{
#def 没有可用的内存空间
/* Determine if the request specifies suspension. */
#def wait_option不为0,就挂起线程到tx_block_pool_suspension_list列表
if (wait_option)
{
/* Prepare for suspension of this thread. */
/* Pickup thread pointer. */
thread_ptr = _tx_thread_current_ptr;
/* Setup cleanup routine pointer. */
thread_ptr -> tx_suspend_cleanup = _tx_block_pool_cleanup;
/* Setup cleanup information, i.e. this pool control
block. */
#def 存储挂起时内存池指针
thread_ptr -> tx_suspend_control_block = (VOID_PTR) pool_ptr;
/* Save the return block pointer address as well. */
#def 保存应用程序传入的用于存储分配的内存地址的 指针,等到有其他线程释放内存时,恢复本线程重新申请内存时使用
thread_ptr -> tx_additional_suspend_info = (VOID_PTR) block_ptr;
/* Setup suspension list. */
#def 插入挂起list
if (pool_ptr -> tx_block_pool_suspension_list)
{
/* This list is not NULL, add current thread to the end. */
thread_ptr -> tx_suspended_next =
pool_ptr -> tx_block_pool_suspension_list;
thread_ptr -> tx_suspended_previous =
(pool_ptr -> tx_block_pool_suspension_list) -> tx_suspended_previous;
((pool_ptr -> tx_block_pool_suspension_list) -> tx_suspended_previous) -> tx_suspended_next =
thread_ptr;
(pool_ptr -> tx_block_pool_suspension_list) -> tx_suspended_previous = thread_ptr;
}
else
{
/* No other threads are suspended. Setup the head pointer and
just setup this threads pointers to itself. */
pool_ptr -> tx_block_pool_suspension_list = thread_ptr;
thread_ptr -> tx_suspended_next = thread_ptr;
thread_ptr -> tx_suspended_previous = thread_ptr;
}
/* Increment the suspended thread count. */
pool_ptr -> tx_block_pool_suspended_count++;
/* Set the state to suspended. */
thread_ptr -> tx_state = TX_BLOCK_MEMORY;
/* Set the suspending flag. */
thread_ptr -> tx_suspending = TX_TRUE;
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Save the timeout value. */
thread_ptr -> tx_thread_timer.tx_remaining_ticks = wait_option;
/* Restore interrupts. */
TX_RESTORE
/* See if we need to start a timer. */
#def 开启定时器,定时器超时清除相关结构,恢复线程
if (wait_option != TX_WAIT_FOREVER)
{
/* A timeout is required. */
/* Activate the thread timer for the timeout. */
_tx_timer_activate(&(thread_ptr -> tx_thread_timer));
}
/* Call actual thread suspension routine. */
#def 挂起线程
_tx_thread_suspend(thread_ptr);
/* Return the completion status. */
#def 线程恢复后,函数从这里返回,tx_suspend_status值在tx_block_pool_delete,tx_block_release或_tx_block_pool_cleanup函数设置,这些函数设置这个值,然后恢复了本线程
return (thread_ptr -> tx_suspend_status);
}
else
/* Immediate return, return error completion. */
status = TX_NO_MEMORY;
}
/* Restore interrupts. */
TX_RESTORE
/* Return completion status. */
return (status);
}