개요
_tx_byte_allocate에서는 인자로 제시된 memory_ptr에 memory_size만큼 데이터를 할당하는 것을 목적으로 가지는 함수이다.
아래는 코드를 풀어서 표현한 플로우 차트이다.

이때 ‘대기 후 재시도’ 항목은 _tx_byte_allocate함수 내부에서 진행이 이루어지는 것이 아니라 _tx_byte_release가 호출 될 때, 재시도하게 된다.
tx_byte_pool_suspension_list로 들어가서 할당이 되기를 기다리게 된다. 이 큐에는 할당에 실패한 스레드가 들어가기 때문에 release가 이루어진 이후 다시 할당이 가능한지 확인하도록 동작한다.
이제 각 부분에 대해서 코드를 보며 보다 자세한 설명을 해보겠다.
충분한 메모리 발견?
_tx_byte_pool_search를 이해한다면 대부분 쉽게 이해할 수 있는 부분이다. 필요한 메모리를 탐색하고 할당에 성공 혹은 실패함에 따라서 work_ptr이 설정된다.
/* Loop to handle cases where the owner of the pool changed. */
do
{
/* Indicate that this thread is the current owner. */
pool_ptr -> tx_byte_pool_owner = thread_ptr;
/* Restore interrupts. */
TX_RESTORE
/* At this point, the executing thread owns the pool and can perform a search
for free memory. */
work_ptr = _tx_byte_pool_search(pool_ptr, memory_size);
/* Optional processing extension. */
TX_BYTE_ALLOCATE_EXTENSION
/* Lockout interrupts. */
TX_DISABLE
/* Determine if we are finished. */
if (work_ptr != TX_NULL)
{
/* Yes, we have found a block the search is finished. */
finished = TX_TRUE;
}
else
{
/* No block was found, does this thread still own the pool? */
if (pool_ptr -> tx_byte_pool_owner == thread_ptr)
{
/* Yes, then we have looked through the entire pool and haven't found the memory. */
finished = TX_TRUE;
}
}
} while (finished == TX_FALSE);while로 감싸져있는 것이 의아할 수 있는데, 내가 이해하기로는 search에서 실패한 이후 컨텍스트 스위칭이 이루어졌다면 해당 스레드에서 메모리를 release했을 가능성이 있으므로 search과정을 다시 수행하는 것으로 보인다.
코드에서 pool을 search하는 스레드가 소유하고 있다면 while을 탈출하는 것을 볼 수 있다.
할당이 성공적이라면 다음과 같은 status를 반환한다.
status = TX_SUCCESS;
...
...
*memory_ptr = (VOID *) work_ptr;
...
...
/* Return completion status. */
return(status);대기 옵션이 설정되었는가?
대기 옵션이 설정되지 않았다면 실패에 대한 status를 반환하고 함수를 마무리한다.
if (wait_option != TX_NO_WAIT)
{
/* Determine if the preempt disable flag is non-zero. */
if (_tx_thread_preempt_disable != ((UINT) 0))
{
/* Suspension is not allowed if the preempt disable flag is non-zero at this point - return error completion. */
status = TX_NO_MEMORY;
/* Restore interrupts. */
TX_RESTORE
}
else
{
...
...
}
...
...
}대기 옵션이 설정되어 있으면 작업이 조금 복잡해지는데 이후에 보다 자세하게 작성해보겠다.
스레드 일시중단
다음 3가지 데이터를 갱신하고 _tx_thread_system_suspend를 호출하여 스레드를 정지시킨다.
pool_ptr -> tx_byte_pool_suspension_listthread_ptr -> tx_thread_suspended_nextthread_ptr -> tx_thread_suspended_previous
/* Prepare for suspension of this thread. */
/* Setup cleanup routine pointer. */
thread_ptr -> tx_thread_suspend_cleanup = &(_tx_byte_pool_cleanup);
/* Setup cleanup information, i.e. this pool control block. */
thread_ptr -> tx_thread_suspend_control_block = (VOID *) pool_ptr;
/* Save the return memory pointer address as well. */
thread_ptr -> tx_thread_additional_suspend_info = (VOID *) memory_ptr;
/* Save the byte size requested. */
thread_ptr -> tx_thread_suspend_info = memory_size;
/* Pickup the number of suspended threads. */
suspended_count = pool_ptr -> tx_byte_pool_suspended_count;
/* Increment the suspension count. */
(pool_ptr -> tx_byte_pool_suspended_count)++;
/* Setup suspension list. */
if (suspended_count == TX_NO_SUSPENSIONS)
{
/* No other threads are suspended. Setup the head pointer and
just setup this threads pointers to itself. */
pool_ptr -> tx_byte_pool_suspension_list = thread_ptr;
thread_ptr -> tx_thread_suspended_next = thread_ptr;
thread_ptr -> tx_thread_suspended_previous = thread_ptr;
}
else
{
/* This list is not NULL, add current thread to the end. */
next_thread = pool_ptr -> tx_byte_pool_suspension_list;
thread_ptr -> tx_thread_suspended_next = next_thread;
previous_thread = next_thread -> tx_thread_suspended_previous;
thread_ptr -> tx_thread_suspended_previous = previous_thread;
previous_thread -> tx_thread_suspended_next = thread_ptr;
next_thread -> tx_thread_suspended_previous = thread_ptr;
}
/* Set the state to suspended. */
thread_ptr -> tx_thread_state = TX_BYTE_MEMORY;
/* Set the suspending flag. */
thread_ptr -> tx_thread_suspending = TX_TRUE;
/* Setup the timeout period. */
thread_ptr -> tx_thread_timer.tx_timer_internal_remaining_ticks = wait_option;
/* Temporarily disable preemption. */
_tx_thread_preempt_disable++;
/* Restore interrupts. */
TX_RESTORE
/* Call actual thread suspension routine. */
_tx_thread_system_suspend(thread_ptr);
/* Return the completion status. */
status = thread_ptr -> tx_thread_suspend_status;대기 후 재시도
이는 해당 함수의 범위를 벗어나므로 이후 다루도록 하겠다.
할당에 실패한 이상 _tx_byte_allocate에서는 더 이상 시도할 것이 없고 할당된 메모리가 해제되는 것을 기다려야하기 때문이다.