# RT-Thread Thread ## 結構 :::success **File:** rtdef.h ::: ```c=492 /** * Thread structure */ struct rt_thread { /* rt object */ char name[RT_NAME_MAX]; /**< the name of thread */ rt_uint8_t type; /**< type of object */ rt_uint8_t flags; /**< thread's flags */ #ifdef RT_USING_MODULE void *module_id; /**< id of application module */ #endif ``` - 一些基本資料,如名字等 ```c=+ rt_list_t list; /**< the object list */ rt_list_t tlist; /**< the thread list */ ``` - 兩條鏈:thread list、object list ```c=+ /* stack point and entry */ void *sp; /**< stack point */ void *entry; /**< entry */ void *parameter; /**< parameter */ void *stack_addr; /**< stack address */ rt_uint32_t stack_size; /**< stack size */ ``` - stack 相關的 ```c=+ /* error code */ rt_err_t error; /**< error code */ rt_uint8_t stat; /**< thread status */ ``` - 狀態,下面會列出來所有可能 ```c=+ /* priority */ rt_uint8_t current_priority; /**< current priority */ rt_uint8_t init_priority; /**< initialized priority */ #if RT_THREAD_PRIORITY_MAX > 32 rt_uint8_t number; rt_uint8_t high_mask; #endif rt_uint32_t number_mask; ``` - 與權限相關的 ```c=+ #if defined(RT_USING_EVENT) /* thread event */ rt_uint32_t event_set; rt_uint8_t event_info; #endif #if defined(RT_USING_SIGNALS) rt_sigset_t sig_pending; /**< the pending signals */ rt_sigset_t sig_mask; /**< the mask bits of signal */ void *sig_ret; /**< the return stack pointer from signal */ rt_sighandler_t *sig_vectors; /**< vectors of signal handler */ void *si_list; /**< the signal infor list */ #endif rt_ubase_t init_tick; /**< thread's initialized tick */ rt_ubase_t remaining_tick; /**< remaining tick */ struct rt_timer thread_timer; /**< built-in thread timer */ ``` - event、sig、tick ```c=+ void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */ /* light weight process if present */ #ifdef RT_USING_LWP void *lwp; #endif rt_uint32_t user_data; /**< private user data beyond this thread */ }; typedef struct rt_thread *rt_thread_t; ``` - `cleanup` 函數及 `user_data` --- ## 狀態 - 一共有 6 種狀態 ```c=471 #define RT_THREAD_INIT 0x00 /**< Initialized status */ #define RT_THREAD_READY 0x01 /**< Ready status */ #define RT_THREAD_SUSPEND 0x02 /**< Suspend status */ #define RT_THREAD_RUNNING 0x03 /**< Running status */ #define RT_THREAD_BLOCK RT_THREAD_SUSPEND /**< Blocked status */ #define RT_THREAD_CLOSE 0x04 /**< Closed status */ #define RT_THREAD_STAT_MASK 0x0f ``` --- :::success **File:** thread.h ::: - 下圖為官方文本的 thread 流向圖,接著一個一個的看下去 ![](https://i.imgur.com/bysM6mg.png) --- ## 初始化、建立 thread ### 靜態記憶體管理 #### `rt_thread_init` | 功能 | 回傳值 | | --- | ------ | | 初始化 thread | `RT-EOK` | | `*thread` | `*name` | `*entry` | `*parameter` | | --------- | ------- | -------- | ------------ | | thread 本體 | 名字 | 要執行的副程式 | 副程式參數 | | `*stack_start` | `stack_size` | `priority` | `tick` | | -------------- | ------------ | ---------- | ------ | | thread 堆疊起點 | thread 堆疊大小 | 優先級 | 可執行的 tick 數 | ```c=199 /** * This function will initialize a thread, normally it's used to initialize a * static thread object. * * @param thread the static thread object * @param name the name of thread, which shall be unique * @param entry the entry function of thread * @param parameter the parameter of thread enter function * @param stack_start the start address of thread stack * @param stack_size the size of thread stack * @param priority the priority of thread * @param tick the time slice if there are same priority thread * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_init(struct rt_thread *thread, const char *name, void (*entry)(void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick) { /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(stack_start != RT_NULL); /* init thread object */ rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name); return _rt_thread_init(thread, name, entry, parameter, stack_start, stack_size, priority, tick); } RTM_EXPORT(rt_thread_init); ``` - 透過 `_rt_thread_init` 完成初始化 --- #### `_rt_thread_init` | 功能 | 回傳值 | | --- | ------ | | 初始化 thread | RT_EOK | | `*thread` | `*name` | `*entry` | `*parameter` | | --------- | ------- | -------- | ------------ | | thread 本體 | 名字 | 要執行的副程式 | 副程式參數 | | `*stack_start` | `stack_size` | `priority` | `tick` | | -------------- | ------------ | ---------- | ------ | | thread 堆疊起點 | thread 堆疊大小 | 優先級 | 可執行的 tick 數 | ```c=118 static rt_err_t _rt_thread_init(struct rt_thread *thread, const char *name, void (*entry)(void *parameter), void *parameter, void *stack_start, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick) { /* init thread list */ rt_list_init(&(thread->tlist)); thread->entry = (void *)entry; thread->parameter = parameter; /* stack init */ thread->stack_addr = stack_start; thread->stack_size = stack_size; ``` - 首先將傳入的資料填入結構 ```c=+ /* init thread stack */ rt_memset(thread->stack_addr, '#', thread->stack_size); thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, (void *)((char *)thread->stack_addr + thread->stack_size - 4), (void *)rt_thread_exit); ``` - 接著設定堆疊,使用 `rt_hw_stack_init` 來完成(根據不同 cpu 有不同的方式,`rt_hw_stack_init` 在 /libcpu 中針對不同的 cpu 有不同的函式宣告) ```c=+ /* priority init */ RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); thread->init_priority = priority; thread->current_priority = priority; thread->number_mask = 0; #if RT_THREAD_PRIORITY_MAX > 32 thread->number = 0; thread->high_mask = 0; #endif ``` - 設定 priority 及 mask ```c=+ /* tick init */ thread->init_tick = tick; thread->remaining_tick = tick; /* error and flags */ thread->error = RT_EOK; thread->stat = RT_THREAD_INIT; /* initialize cleanup function and user data */ thread->cleanup = 0; thread->user_data = 0; /* init thread timer */ rt_timer_init(&(thread->thread_timer), thread->name, rt_thread_timeout, thread, 0, RT_TIMER_FLAG_ONE_SHOT); /* initialize signal */ #ifdef RT_USING_SIGNALS thread->sig_mask = 0x00; thread->sig_pending = 0x00; thread->sig_ret = RT_NULL; thread->sig_vectors = RT_NULL; thread->si_list = RT_NULL; #endif #ifdef RT_USING_LWP thread->lwp = RT_NULL; #endif RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); return RT_EOK; } ``` - 最後依序完成 tick、sig、hook 等的初始化 --- ### 動態記憶體管理 #### `rt_thread_create` | 功能 | 回傳值 | | --- | ------ | | 建立 thread | thread | | `*name` | `*entry` | `*parameter` | | ------- | -------- | ------------ | | 名字 | 要執行的副程式 | 副程式參數 | | `*stack_start` | `stack_size` | `priority` | `tick` | | -------------- | ------------ | ---------- | ------ | | thread 堆疊起點 | thread 堆疊大小 | 優先級 | 可執行的 tick 數 | ```c=344 /** * This function will create a thread object and allocate thread object memory * and stack. * * @param name the name of thread, which shall be unique * @param entry the entry function of thread * @param parameter the parameter of thread enter function * @param stack_size the size of thread stack * @param priority the priority of thread * @param tick the time slice if there are same priority thread * * @return the created thread object */ rt_thread_t rt_thread_create(const char *name, void (*entry)(void *parameter), void *parameter, rt_uint32_t stack_size, rt_uint8_t priority, rt_uint32_t tick) { struct rt_thread *thread; void *stack_start; thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread, name); if (thread == RT_NULL) return RT_NULL; stack_start = (void *)RT_KERNEL_MALLOC(stack_size); if (stack_start == RT_NULL) { /* allocate stack failure */ rt_object_delete((rt_object_t)thread); return RT_NULL; } _rt_thread_init(thread, name, entry, parameter, stack_start, stack_size, priority, tick); return thread; } RTM_EXPORT(rt_thread_create); ``` - 首先 allocate 一塊給 thread,一塊給堆疊 - 再呼叫 `_rt_thread_init` 完成初始化 --- ## 啟動 thread #### `rt_thread_startup` | 功能 | 回傳值 | | --- | ------ | | 啟動 thread | `RT_EOK` | | `thread` | | -------- | | 欲啟動的 thread | ```c=252 /** * This function will start a thread and put it to system ready queue * * @param thread the thread to be started * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_startup(rt_thread_t thread) { /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); /* set current priority to init priority */ thread->current_priority = thread->init_priority; ``` - 設定 priority ```c=+ /* calculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1L << thread->number; thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1L << thread->current_priority; #endif ``` - 這些參數是用來計算權限的,`scheudler` 會用到 ```c=+ RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n", thread->name, thread->init_priority)); /* change thread stat */ thread->stat = RT_THREAD_SUSPEND; /* then resume it */ rt_thread_resume(thread); if (rt_thread_self() != RT_NULL) { /* do a scheduling */ rt_schedule(); } return RT_EOK; } RTM_EXPORT(rt_thread_startup); ``` - 最後將 stat 設為 `RT_THREAD_SUSPEND`,再透過 `rt_thread_resume` 來完成啟動 - 啟動完成後呼叫 `rt_scheduler()` 來執行一次調度 --- ## 暫停、復原 thread #### `rt_thread_suspend` | 功能 | 回傳值 | | --- | ------ | | 暫停 thread | `RT-EOK` | | `*thread` | | --------- | | 欲暫停的 thread | ```c=630 /** * This function will suspend the specified thread. * * @param thread the thread to be suspended * * @return the operation status, RT_EOK on OK, -RT_ERROR on error * * @note if suspend self thread, after this function call, the * rt_schedule() must be invoked. */ rt_err_t rt_thread_suspend(rt_thread_t thread) { register rt_base_t temp; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name)); if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY) { RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n", thread->stat)); return -RT_ERROR; } /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* change thread stat */ thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK); rt_schedule_remove_thread(thread); /* stop thread timer anyway */ rt_timer_stop(&(thread->thread_timer)); /* enable interrupt */ rt_hw_interrupt_enable(temp); RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread)); return RT_EOK; } RTM_EXPORT(rt_thread_suspend); ``` - 首先將狀態修改為 `RT_THREAD_SUSPEND`,接著將 thread 從 tlist 移除,結束 timer --- #### `rt_thread_delay` | 功能 | 回傳值 | | --- | ------ | | 延遲 thread | `RT-EOK` | | `tick` | | --------- | | 欲延遲的時間 | ```c=519 /** * This function will let current thread delay for some ticks. * * @param tick the delay ticks * * @return RT_EOK */ rt_err_t rt_thread_delay(rt_tick_t tick) { return rt_thread_sleep(tick); } RTM_EXPORT(rt_thread_delay); ``` - 透過 `rt_thread_sleep` 實作 --- #### `rt_thread_sleep` | 功能 | 回傳值 | | --- | ------ | | 使 thread 休眠 | `RT-EOK` | | `tick` | | --------- | | 欲睡眠的時間 | ```c=481 /** * This function will let current thread sleep for some ticks. * * @param tick the sleep ticks * * @return RT_EOK */ rt_err_t rt_thread_sleep(rt_tick_t tick) { register rt_base_t temp; struct rt_thread *thread; /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* set to current thread */ thread = rt_current_thread; RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); /* suspend thread */ rt_thread_suspend(thread); /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick); rt_timer_start(&(thread->thread_timer)); /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); /* clear error number of this thread to RT_EOK */ if (thread->error == -RT_ETIMEOUT) thread->error = RT_EOK; return RT_EOK; } ``` --- ### 復原 thread #### `rt_thread_resume` | 功能 | 回傳值 | | --- | ------ | | 復原 thread | `RT-EOK` | | `*thread` | | --------- | | 欲復原的 thread | ```c=676 /** * This function will resume a thread and put it to system ready queue. * * @param thread the thread to be resumed * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_resume(rt_thread_t thread) { register rt_base_t temp; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name)); if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND) { RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n", thread->stat)); return -RT_ERROR; } /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* remove from suspend list */ rt_list_remove(&(thread->tlist)); rt_timer_stop(&thread->thread_timer); /* enable interrupt */ rt_hw_interrupt_enable(temp); /* insert to schedule ready list */ rt_schedule_insert_thread(thread); RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread)); return RT_EOK; } RTM_EXPORT(rt_thread_resume); ``` - 首先從 suspend list 移除,停止 timer,掛回去 ready list - `rt_schedule_insert_thread` 會將狀態修改成 `RT_THREAD_READY` --- ## 離開、刪除 thread ### `rt_thread_exit` | 功能 | 回傳值 | | --- | ------ | | 暫停 thread | void | ```c=81 void rt_thread_exit(void) { struct rt_thread *thread; register rt_base_t level; /* get current thread */ thread = rt_current_thread; /* disable interrupt */ level = rt_hw_interrupt_disable(); /* remove from schedule */ rt_schedule_remove_thread(thread); /* change stat */ thread->stat = RT_THREAD_CLOSE; /* remove it from timer list */ rt_timer_detach(&thread->thread_timer); ``` - 首先從 ready list 中移除,修改狀態為 `RT_THREAD_CLOSE`,從 timer list 中移除 ```c=+ if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) && thread->cleanup == RT_NULL) { rt_object_detach((rt_object_t)thread); } else { /* insert to defunct thread list */ rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* switch to next task */ rt_schedule(); } ``` - 如果為系統的 thread,且 `cleanup` 函式沒有被定義時,呼叫 `rt_object_detach` 來完成移除的動作 - 否則,將 thread 插入至 `rt_thread_defunct`,此鏈上面的 thread 會由 idle 清除。 --- ### 刪除 thread #### 動態記憶體管理 ##### `rt_thread_delete` | 功能 | 回傳值 | | --- | ------ | | 刪除 thread | `RT-EOK` | | `*thread` | | --------- | | 欲刪除的 thread | ```c=394 /** * This function will delete a thread. The thread object will be removed from * thread queue and deleted from system object management in the idle thread. * * @param thread the thread to be deleted * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_delete(rt_thread_t thread) { rt_base_t lock; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE); if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) { /* remove from schedule */ rt_schedule_remove_thread(thread); } ``` - 如果此 thread 已經啟動過了,將此 thread 從 ready list 移除 ```c=+ /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); /* change stat */ thread->stat = RT_THREAD_CLOSE; /* disable interrupt */ lock = rt_hw_interrupt_disable(); /* insert to defunct thread list */ rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); /* enable interrupt */ rt_hw_interrupt_enable(lock); return RT_EOK; } RTM_EXPORT(rt_thread_delete); ``` - 接著將 timer 還回去,修改狀態為 `RT_THREAD_CLOSE`,插入至 `rt_thread_defunct` --- #### 靜態記憶體管理 ##### `rt_thread_detach` | 功能 | 回傳值 | | --- | ------ | | 刪除 thread | `RT-EOK` | | `*thread` | | --------- | | 欲刪除的 thread | ```c=294 /** * This function will detach a thread. The thread object will be removed from * thread queue and detached/deleted from system object management. * * @param thread the thread to be deleted * * @return the operation status, RT_EOK on OK, -RT_ERROR on error */ rt_err_t rt_thread_detach(rt_thread_t thread) { rt_base_t lock; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread)); if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) { /* remove from schedule */ rt_schedule_remove_thread(thread); } /* release thread timer */ rt_timer_detach(&(thread->thread_timer)); /* change stat */ thread->stat = RT_THREAD_CLOSE; /* detach object */ rt_object_detach((rt_object_t)thread); if (thread->cleanup != RT_NULL) { /* disable interrupt */ lock = rt_hw_interrupt_disable(); /* insert to defunct thread list */ rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); /* enable interrupt */ rt_hw_interrupt_enable(lock); } return RT_EOK; } RTM_EXPORT(rt_thread_detach); ``` - 與 delete 不同的差在第32行 ## 控制 thread ### `rt_thread_control` | 功能 | 回傳值 | | --- | ------ | | 控制 thread | `RT-EOK` | | `*thread` | `cmd` | `*argv` | | --------- | ----- | ------- | | 欲控制的 thread | 需執行的動作 | 伴隨動作的參數 | ```c=549 /** * This function will control thread behaviors according to control command. * * @param thread the specified thread to be controlled * @param cmd the control command, which includes * RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread; * RT_THREAD_CTRL_STARTUP for starting a thread; * RT_THREAD_CTRL_CLOSE for delete a thread. * @param arg the argument of control command * * @return RT_EOK */ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) { register rt_base_t temp; /* thread check */ RT_ASSERT(thread != RT_NULL); RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); switch (cmd) { case RT_THREAD_CTRL_CHANGE_PRIORITY: /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* for ready thread, change queue */ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY) { /* remove thread from schedule queue first */ rt_schedule_remove_thread(thread); /* change thread priority */ thread->current_priority = *(rt_uint8_t *)arg; /* recalculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1 << thread->number; thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; #endif /* insert thread to schedule queue again */ rt_schedule_insert_thread(thread); } else { thread->current_priority = *(rt_uint8_t *)arg; /* recalculate priority attribute */ #if RT_THREAD_PRIORITY_MAX > 32 thread->number = thread->current_priority >> 3; /* 5bit */ thread->number_mask = 1 << thread->number; thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ #else thread->number_mask = 1 << thread->current_priority; #endif } /* enable interrupt */ rt_hw_interrupt_enable(temp); break; case RT_THREAD_CTRL_STARTUP: return rt_thread_startup(thread); #ifdef RT_USING_HEAP case RT_THREAD_CTRL_CLOSE: return rt_thread_delete(thread); #endif default: break; } return RT_EOK; } RTM_EXPORT(rt_thread_control); ``` ###### tags: `RT-Thread` `kernel` `thread`