개요

_tx_byte_pool_create은 함수의 인자로 들어오는 pool_start내부 버퍼를 초기화하는 것이 해당 함수의 주 목적이라고 할 수 있다.

초기화 되는 형식은 다음과 같다.

데이터의 형식이 ‘주소, 데이터’ 패턴을 가지는데 이는 데이터 할당 과정에서도 똑같이 이루어진다. 즉, 구조체를 사용하여 초기화가 진행되지는 않지만 연결리스트의 형식을 가진다. (주소 4byte, 데이터 4byte)

초기화 코드에서도 주소의 포인터는 temp_ptr에 저장하고, 데이터의 포인터는 block_ptr에 저장하는 패턴을 가지며 size 또한 주소는 ALIGN_TYPE, 데이터는 UCHAR *를 가지는 것을 볼 수 있다.

이제 코드와 비교하면서 과정을 살펴보자.

세부 과정

  1. 인자로 들어온 pool_ptr 구조체를 초기화한다.

        /* Initialize the byte pool control block to all zeros.  */
        TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL)));
     
        /* Round the pool size down to something that is evenly divisible by
           an ULONG.  */
        pool_size =   (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
     
        /* Setup the basic byte pool fields.  */
        pool_ptr -> tx_byte_pool_name =              name_ptr;
     
        /* Save the start and size of the pool.  */
        pool_ptr -> tx_byte_pool_start =   TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
        pool_ptr -> tx_byte_pool_size =    pool_size;
     
        /* Setup memory list to the beginning as well as the search pointer.  */
        pool_ptr -> tx_byte_pool_list =    TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
        pool_ptr -> tx_byte_pool_search =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
     
        /* Initially, the pool will have two blocks.  One large block at the
           beginning that is available and a small allocated block at the end
           of the pool that is there just for the algorithm.  Be sure to count
           the available block's header in the available bytes count.  */
        pool_ptr -> tx_byte_pool_available =   pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE)));
        pool_ptr -> tx_byte_pool_fragments =   ((UINT) 2);
  2. pool_start의 마지막 4바이트(sizeof(ALIGN_TYPE))에 pool_ptr구조체를 저장한다.

        /* Calculate the end of the pool's memory area.  */
        block_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
        block_ptr =  TX_UCHAR_POINTER_ADD(block_ptr, pool_size);
     
        /* Backup the end of the pool pointer and build the pre-allocated block.  */
        block_ptr =  TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE)));
     
        /* Cast the pool pointer into a ULONG.  */
        temp_ptr =             TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
        block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
        *block_indirect_ptr =  temp_ptr;
  3. 2번 과정에서 사용된 block_ptr에서 4바이트 앞의 주소에 pool_start포인터를 저장한다.

    즉, 시작 위치를 저장한다.

        block_ptr =            TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *)));
        block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
        *block_indirect_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
  4. pool_start의 시작 부분에 block_ptr을 저장하여 서로의 위치를 가리키는 순환형 구조(원형 버퍼)를 생성한다.

        temp_ptr =             TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
        block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr);
        *block_indirect_ptr =  block_ptr;
  5. 다음 4바이트 위치에 TX_BYTE_BLOCK_FREE값을 저장한다.

        block_ptr =            TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
        block_ptr =            TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *)));
        free_ptr =             TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr);
        *free_ptr =            TX_BYTE_BLOCK_FREE;
  6. 추가로 pool_ptr을 초기화 한다. (왜 할당이 끝난 후에 초기화를 하는지는 잘 모르겠다.)

        /* Clear the owner id.  */
        pool_ptr -> tx_byte_pool_owner =  TX_NULL;
     
        /* Disable interrupts to place the byte pool on the created list.  */
        TX_DISABLE
     
        /* Setup the byte pool ID to make it valid.  */
        pool_ptr -> tx_byte_pool_id =  TX_BYTE_POOL_ID;
  7. _tx_byte_pool_created_ptrpool_ptr을 추가한다. (전역으로 관리하는 연결리스트)

        /* Place the byte pool on the list of created byte pools.  First,
           check for an empty list.  */
        if (_tx_byte_pool_created_count == TX_EMPTY)
        {
     
            /* The created byte pool list is empty.  Add byte pool to empty list.  */
            _tx_byte_pool_created_ptr =                  pool_ptr;
            pool_ptr -> tx_byte_pool_created_next =      pool_ptr;
            pool_ptr -> tx_byte_pool_created_previous =  pool_ptr;
        }
        else
        {
     
            /* This list is not NULL, add to the end of the list.  */
            next_pool =      _tx_byte_pool_created_ptr;
            previous_pool =  next_pool -> tx_byte_pool_created_previous;
     
            /* Place the new byte pool in the list.  */
            next_pool -> tx_byte_pool_created_previous =  pool_ptr;
            previous_pool -> tx_byte_pool_created_next =  pool_ptr;
     
            /* Setup this byte pool's created links.  */
            pool_ptr -> tx_byte_pool_created_previous =  previous_pool;
            pool_ptr -> tx_byte_pool_created_next =      next_pool;
        }
     
        /* Increment the number of created byte pools.  */
        _tx_byte_pool_created_count++;

전체 코드

UINT  _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size)
{
 
TX_INTERRUPT_SAVE_AREA
 
UCHAR               *block_ptr;
UCHAR               **block_indirect_ptr;
UCHAR               *temp_ptr;
TX_BYTE_POOL        *next_pool;
TX_BYTE_POOL        *previous_pool;
ALIGN_TYPE          *free_ptr;
 
    /* Initialize the byte pool control block to all zeros.  */
    TX_MEMSET(pool_ptr, 0, (sizeof(TX_BYTE_POOL)));
 
    /* Round the pool size down to something that is evenly divisible by
       an ULONG.  */
    pool_size =   (pool_size/(sizeof(ALIGN_TYPE))) * (sizeof(ALIGN_TYPE));
 
    /* Setup the basic byte pool fields.  */
    pool_ptr -> tx_byte_pool_name =              name_ptr;
 
    /* Save the start and size of the pool.  */
    pool_ptr -> tx_byte_pool_start =   TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
    pool_ptr -> tx_byte_pool_size =    pool_size;
 
    /* Setup memory list to the beginning as well as the search pointer.  */
    pool_ptr -> tx_byte_pool_list =    TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
    pool_ptr -> tx_byte_pool_search =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
 
    /* Initially, the pool will have two blocks.  One large block at the
       beginning that is available and a small allocated block at the end
       of the pool that is there just for the algorithm.  Be sure to count
       the available block's header in the available bytes count.  */
    pool_ptr -> tx_byte_pool_available =   pool_size - ((sizeof(VOID *)) + (sizeof(ALIGN_TYPE)));
    pool_ptr -> tx_byte_pool_fragments =   ((UINT) 2);
 
    /* Each block contains a "next" pointer that points to the next block in the pool followed by a ALIGN_TYPE
       field that contains either the constant TX_BYTE_BLOCK_FREE (if the block is free) or a pointer to the
       owning pool (if the block is allocated).  */
 
    /* Calculate the end of the pool's memory area.  */
    block_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
    block_ptr =  TX_UCHAR_POINTER_ADD(block_ptr, pool_size);
 
    /* Backup the end of the pool pointer and build the pre-allocated block.  */
    block_ptr =  TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(ALIGN_TYPE)));
 
    /* Cast the pool pointer into a ULONG.  */
    temp_ptr =             TX_BYTE_POOL_TO_UCHAR_POINTER_CONVERT(pool_ptr);
    block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
    *block_indirect_ptr =  temp_ptr;
 
    block_ptr =            TX_UCHAR_POINTER_SUB(block_ptr, (sizeof(UCHAR *)));
    block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(block_ptr);
    *block_indirect_ptr =  TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
 
    /* Now setup the large available block in the pool.  */
    temp_ptr =             TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
    block_indirect_ptr =   TX_UCHAR_TO_INDIRECT_UCHAR_POINTER_CONVERT(temp_ptr);
    *block_indirect_ptr =  block_ptr;
    block_ptr =            TX_VOID_TO_UCHAR_POINTER_CONVERT(pool_start);
    block_ptr =            TX_UCHAR_POINTER_ADD(block_ptr, (sizeof(UCHAR *)));
    free_ptr =             TX_UCHAR_TO_ALIGN_TYPE_POINTER_CONVERT(block_ptr);
    *free_ptr =            TX_BYTE_BLOCK_FREE;
 
    /* Clear the owner id.  */
    pool_ptr -> tx_byte_pool_owner =  TX_NULL;
 
    /* Disable interrupts to place the byte pool on the created list.  */
    TX_DISABLE
 
    /* Setup the byte pool ID to make it valid.  */
    pool_ptr -> tx_byte_pool_id =  TX_BYTE_POOL_ID;
 
    /* Place the byte pool on the list of created byte pools.  First,
       check for an empty list.  */
    if (_tx_byte_pool_created_count == TX_EMPTY)
    {
 
        /* The created byte pool list is empty.  Add byte pool to empty list.  */
        _tx_byte_pool_created_ptr =                  pool_ptr;
        pool_ptr -> tx_byte_pool_created_next =      pool_ptr;
        pool_ptr -> tx_byte_pool_created_previous =  pool_ptr;
    }
    else
    {
 
        /* This list is not NULL, add to the end of the list.  */
        next_pool =      _tx_byte_pool_created_ptr;
        previous_pool =  next_pool -> tx_byte_pool_created_previous;
 
        /* Place the new byte pool in the list.  */
        next_pool -> tx_byte_pool_created_previous =  pool_ptr;
        previous_pool -> tx_byte_pool_created_next =  pool_ptr;
 
        /* Setup this byte pool's created links.  */
        pool_ptr -> tx_byte_pool_created_previous =  previous_pool;
        pool_ptr -> tx_byte_pool_created_next =      next_pool;
    }
 
    /* Increment the number of created byte pools.  */
    _tx_byte_pool_created_count++;
 
    /* Optional byte pool create extended processing.  */
    TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr)
 
    /* If trace is enabled, register this object.  */
    TX_TRACE_OBJECT_REGISTER(TX_TRACE_OBJECT_TYPE_BYTE_POOL, pool_ptr, name_ptr, pool_size, 0)
 
    /* If trace is enabled, insert this event into the trace buffer.  */
    TX_TRACE_IN_LINE_INSERT(TX_TRACE_BYTE_POOL_CREATE, pool_ptr, TX_POINTER_TO_ULONG_CONVERT(pool_start), pool_size, TX_POINTER_TO_ULONG_CONVERT(&block_ptr), TX_TRACE_BYTE_POOL_EVENTS)
 
    /* Log this kernel call.  */
    TX_EL_BYTE_POOL_CREATE_INSERT
 
    /* Restore interrupts.  */
    TX_RESTORE
 
    /* Return TX_SUCCESS.  */
    return(TX_SUCCESS);
}