Threadx tx_thread_create創建線程

線程控制塊(TCB)

typedef  struct TX_THREAD_STRUCT
{
    /* The first section of the control block contains critical
       information that is referenced by the port-specific 
       assembly language code.  Any changes in this section could
       necessitate changes in the assembly language.  */
    ULONG       tx_thread_id;           /* Control block ID         */
    ULONG       tx_run_count;           /* Thread's run counter     */
    VOID_PTR    tx_stack_ptr;           /* Thread's stack pointer   */
    VOID_PTR    tx_stack_start;         /* Stack starting address   */
    VOID_PTR    tx_stack_end;           /* Stack ending address     */
    ULONG       tx_stack_size;          /* Stack size               */
    ULONG       tx_time_slice;          /* Current time-slice       */
    ULONG       tx_new_time_slice;      /* New time-slice           */

    /* Define pointers to the next and previous ready threads.  */ 
    struct TX_THREAD_STRUCT 
                *tx_ready_next,      
                *tx_ready_previous;

    /* Define the port extension field.  This typically is defined 
       to white space, but some ports of ThreadX may need to have 
       additional fields in the thread control block.  This is 
       defined in the file tx_port.h.  */
    TX_THREAD_PORT_EXTENSION
  
    /***************************************************************/  
         
    /* Nothing after this point is referenced by the target-specific
       assembly language.  Hence, information after this point can 
       be added to the control block providing the complete system 
       is recompiled.  */
    CHAR_PTR    tx_thread_name;         /* Pointer to thread's name */
    UINT        tx_priority;            /* Priority of thread (0-31)*/
    UINT        tx_state;               /* Thread's execution state */
    UINT        tx_delayed_suspend;     /* Delayed suspend flag     */
    UINT        tx_suspending;          /* Thread suspending flag   */
    UINT        tx_preempt_threshold;   /* Preemption threshold     */
    ULONG       tx_priority_bit;        /* Priority ID bit          */

    /* Define the thread's entry point and input parameter.  */
    VOID        (*tx_thread_entry)(ULONG);
    ULONG       tx_entry_parameter;

    /* Define the thread's timer block.   This is used for thread 
       sleep and timeout requests.  */
    TX_INTERNAL_TIMER
                tx_thread_timer;

    /* Define the thread's cleanup function and associated data.  This
       is used to cleanup various data structures when a thread 
       suspension is lifted or terminated either by the user or 
       a timeout.  */
    VOID        (*tx_suspend_cleanup)(struct TX_THREAD_STRUCT *);
    VOID_PTR	tx_suspend_control_block;
    struct TX_THREAD_STRUCT
                *tx_suspended_next,
                *tx_suspended_previous;
    ULONG       tx_suspend_info;
    VOID_PTR    tx_additional_suspend_info;
    UINT        tx_suspend_option;
    UINT        tx_suspend_status;

    /* Define a pointer for Green Hills use.  */
    VOID_PTR    tx_eh_globals;

    /* Define pointers to the next and previous threads in the 
       created list.  */
    struct TX_THREAD_STRUCT 
                *tx_created_next,    
                *tx_created_previous;
} TX_THREAD;

_tx_thread_create

UINT    _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name, 
			    VOID (*entry_function)(ULONG), ULONG entry_input,
			    VOID *stack_start, ULONG stack_size, 
			    UINT priority, UINT preempt_threshold,
			    ULONG time_slice, UINT auto_start)
參數 意義
thread_ptr 線程控制塊指針
name 線程名字
entry_function 線程入口函數
entry_input 線程入口函數參數
stack_start 線程使用的棧起始地址
stack_size 線程棧大小
priority 線程優先級
preempt_threshold 線程搶佔優先級(小於此值線程才能夠搶佔)
time_slice 時間片 (0表示不使用時間片輪轉調度)
auto_start 線程創建後是否自動執行選項
UINT    _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name, 
			    VOID (*entry_function)(ULONG), ULONG entry_input,
			    VOID *stack_start, ULONG stack_size, 
			    UINT priority, UINT preempt_threshold,
			    ULONG time_slice, UINT auto_start)
{

TX_INTERRUPT_SAVE_AREA
REG_1 TX_THREAD_PTR	    tail_ptr;	    /* Created list tail pointer  */

#def 定義局部變量,放在寄存器中


#ifndef TX_DISABLE_STACK_CHECKING

    /* Set the thread stack to a pattern prior to creating the initial
       stack frame.  This pattern is used by the stack checking routines
       to see how much has been used.  */
    memset(stack_start, TX_STACK_FILL, stack_size);

#endif

    /* Prepare the thread control block prior to placing it on the created
       list.  */

#def 設置線程控制塊中變量值
    /* Place the supplied parameters into the thread's control block.  */
    thread_ptr -> tx_thread_name =      name;
    thread_ptr -> tx_thread_entry =     entry_function;
    thread_ptr -> tx_entry_parameter =  entry_input;
    thread_ptr -> tx_stack_ptr =        TX_NULL;
    thread_ptr -> tx_stack_start =      stack_start;
    thread_ptr -> tx_stack_size =       stack_size;
    thread_ptr -> tx_stack_end =        (VOID_PTR) (((CHAR_PTR) stack_start) + (stack_size-1));
    thread_ptr -> tx_priority =         priority & TX_THREAD_PRIORITY_MASK;
    thread_ptr -> tx_preempt_threshold= preempt_threshold & TX_THREAD_PRIORITY_MASK;
    thread_ptr -> tx_time_slice =       time_slice;
    thread_ptr -> tx_new_time_slice =   time_slice;

    /* Now fill in the values that are required for thread initialization.  */
    thread_ptr -> tx_run_count =        0;
    
    #def 初始爲掛起狀態
    thread_ptr -> tx_state =            TX_SUSPENDED; 
    thread_ptr -> tx_delayed_suspend =  TX_FALSE;
    thread_ptr -> tx_suspending =       TX_FALSE;

    /* Setup the necessary fields in the thread timer block.  */
    thread_ptr -> tx_thread_timer.tx_timeout_function =     _tx_thread_timeout;
    thread_ptr -> tx_thread_timer.tx_timeout_param =        (ULONG) thread_ptr;
    thread_ptr -> tx_thread_timer.tx_list_head =            TX_NULL;
    thread_ptr -> tx_thread_timer.tx_re_initialize_ticks =  0;

    /* Clear the suspension information.  */
    thread_ptr -> tx_suspend_cleanup =        TX_NULL;
    thread_ptr -> tx_suspend_control_block =  TX_NULL;
    thread_ptr -> tx_suspended_next =         TX_NULL;
    thread_ptr -> tx_suspended_previous=      TX_NULL;

    /* Setup the priority bit.  */
    thread_ptr -> tx_priority_bit =  (((ULONG) 1) << (priority & TX_THREAD_PRIORITY_MASK));

    /* Call the target specific stack frame building routine to build the 
       thread's initial stack and to setup the actual stack pointer in the
       control block.  */
    #def 爲這個線程創建棧空間,初始化棧內存,設置棧指針tx_stack_ptr 
    _tx_thread_stack_build(thread_ptr, _tx_thread_shell_entry);

    /* Prepare to make this thread a member of the created thread list.  */
    #def 禁止中斷,保證了操作下面全局變量臨界資源;禁止中斷可以讓當前線程不被搶佔;當前線程執行,說明當前線程現在是所有就緒隊列中優先級最高的,其他更高優先級線程可能被掛起了。中斷可能喚醒更高優先級線程
    TX_DISABLE

    /* Load the thread ID field in the thread control block.  */
    thread_ptr -> tx_thread_id =  TX_THREAD_ID;

    /* Place the thread on the list of created threads.  First,
       check for an empty list.  */
      #def 插入到_tx_thread_created_ptr 線程list
    if (_tx_thread_created_ptr)
    {

        /* Pickup tail pointer.  */
        tail_ptr =  _tx_thread_created_ptr -> tx_created_previous;

        /* Place the new thread in the list.  */
        _tx_thread_created_ptr -> tx_created_previous =  thread_ptr;
	    tail_ptr -> tx_created_next =  thread_ptr;

        /* Setup this thread's created links.  */
        thread_ptr -> tx_created_previous =  tail_ptr;
        thread_ptr -> tx_created_next =      _tx_thread_created_ptr;	
    }
    else
    {

        /* The created thread list is empty.  Add thread to empty list.  */
        _tx_thread_created_ptr =            thread_ptr;
        thread_ptr -> tx_created_next =     thread_ptr;
        thread_ptr -> tx_created_previous = thread_ptr;
    }

    /* Increment the created thread counter.  */
    _tx_thread_created_count++;

    /* Temporarily disable preemption.  */
    _tx_thread_preempt_disable++;

    /* Register thread in the thread array structure.  */
    TX_EL_THREAD_REGISTER(thread_ptr);

    /* Log this kernel call.  */
    TX_EL_THREAD_CREATE_INSERT

    /* Green Hills specific code.  */
    {
        #pragma weak __cpp_exception_init
        extern void __cpp_exception_init(void **);
        static void (*const cpp_init_funcp)(void **) = __cpp_exception_init;
        if (cpp_init_funcp) 
            __cpp_exception_init(&(thread_ptr->tx_eh_globals));
    }
    /* End of Green Hills specific code.  */

    /* Restore previous interrupt posture.  */
    TX_RESTORE

    /* Determine if an automatic start was requested.  If so, call the resume
       thread function and then check for a preemption condition.  */
       #def 入參爲自動執行線程
    if (auto_start)
    {

        /* Call the resume thread function to make this thread ready.  Upon 
           return, check for a preemption condition caused by creating
           a thread of higher priority.  */
        #def 把線程放入就緒對應優先級list,如果這個新線程需要立馬執行(例如優先級最高),返回true,並設置了_tx_thread_execute_ptr線程
        if (_tx_thread_resume(thread_ptr))

            /* A preemption condition exists, pass control back to the
               system in order to get the higher priority thread running.  */
              #def 調度進行線程切換,從_tx_thread_current_ptr當前執行前程切換到執行_tx_thread_execute_ptr線程,有彙編實現,與具體cpu體系相關
            _tx_thread_system_return();
    }
    else
    {
     #def 不在動執行線程
        /* Disable interrupts.  */
        TX_DISABLE

        /* Remove temporary disable preemption.  */
        _tx_thread_preempt_disable--;

        /* Restore interrupts.  */
        TX_RESTORE
    }

    /* Always return a success.  */
    return(TX_SUCCESS);
}

示例

void    tx_application_define(void *first_unused_memory)
{

	CHAR    *pointer;

    /* Put first available memory address into a character pointer.  */
    pointer =  (CHAR *) first_unused_memory;

    /* Put system definition stuff in here, e.g. thread creates and other assorted
       create information.  */

    /* Create the main thread.  */
    tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,  
			pointer, DEMO_STACK_SIZE, 
			1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);
    pointer = pointer + DEMO_STACK_SIZE;

    /* Create threads 1 and 2. These threads pass information through a ThreadX 
       message queue.  It is also interesting to note that these threads have a time
       slice.  */
   	tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1,  
			pointer, DEMO_STACK_SIZE, 
			16, 16, 4, TX_AUTO_START);
  	pointer = pointer + DEMO_STACK_SIZE;

   	tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2,  
			pointer, DEMO_STACK_SIZE, 
			16, 16, 4, TX_AUTO_START);
   	pointer = pointer + DEMO_STACK_SIZE;

    /* Create threads 3 and 4.  These threads compete for a ThreadX counting semaphore.  
       An interesting thing here is that both threads share the same instruction area.  */
    tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3,  
			pointer, DEMO_STACK_SIZE, 
			8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
    pointer = pointer + DEMO_STACK_SIZE;

    tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4,  
			pointer, DEMO_STACK_SIZE, 
			8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
    pointer = pointer + DEMO_STACK_SIZE;

    /* Create thread 5.  This thread simply pends on an event flag which will be set
       by thread_0.  */
    tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5,  
			pointer, DEMO_STACK_SIZE, 
			4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
    pointer = pointer + DEMO_STACK_SIZE;

    /* Create the message queue shared by threads 1 and 2.  */
    tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, 100*sizeof(ULONG));
    pointer = pointer + (100*sizeof(ULONG));

    /* Create the semaphore used by threads 3 and 4.  */
   	tx_semaphore_create(&semaphore_0, "semaphore 0", 1);

    /* Create the event flags group used by threads 1 and 5.  */
    tx_event_flags_create(&event_flags_0, "event flags 0");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章