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");
}
发布了41 篇原创文章 · 获赞 2 · 访问量 3260

猜你喜欢

转载自blog.csdn.net/qq_45683435/article/details/104160754