rt-thread線程源碼分析

rt-thread操作系統是一個多線程的操作系統,線程對於rt-thread來說是一個很重要的概念,因此,必須掌握它。

1 線程控制塊的數據結構

[cpp] view plain copy
  1. /** 
  2.  * Thread structure 
  3.  */  
  4. struct rt_thread  
  5. {  
  6.     /* rt object *///這裏就是rt_object的結構,其實也可以用rt_object parent來定義,估計線程在早些時候並沒有這麼做,後來也就沒改過來  
  7.     char        name[RT_NAME_MAX];                      /**< the name of thread */  
  8.     rt_uint8_t  type;                                   /**< type of object */  
  9.     rt_uint8_t  flags;                                  /**< thread's flags */  
  10.       
  11. #ifdef RT_USING_MODULE//模塊ID  
  12.     void       *module_id;                              /**< id of application module */  
  13. #endif  
  14.     //內核對象鏈表  
  15.     rt_list_t   list;                                   /**< the object list */  
  16.     rt_list_t   tlist;                                  /**< the thread list *///線程鏈表,一般用作就緒隊列元素節點  
  17.   
  18.     /* stack point and entry */  
  19.     void       *sp;                                     /**< stack point *///棧指針  
  20.     void       *entry;                                  /**< entry *///入口函數  
  21.     void       *parameter;                              /**< parameter *///入口函數對應的參數  
  22.     void       *stack_addr;                             /**< stack address *///棧地址  
  23.     rt_uint16_t stack_size;                             /**< stack size *///棧大小  
  24.   
  25.     /* error code */  
  26.     rt_err_t    error;                                  /**< error code *///錯誤代碼,用於IPC機制中,標誌是否已經獲取成功  
  27.   
  28.     rt_uint8_t  stat;                                   /**< thread stat *///線程的當前狀態  
  29.   
  30.     /* priority */  
  31.     rt_uint8_t  current_priority;                       /**< current priority *///當前優先級  
  32.     rt_uint8_t  init_priority;                          /**< initialized priority *///初始優先級  
  33. #if RT_THREAD_PRIORITY_MAX > 32  
  34.     rt_uint8_t  number;  
  35.     rt_uint8_t  high_mask;  
  36. #endif  
  37.     rt_uint32_t number_mask;  
  38.   
  39. #if defined(RT_USING_EVENT)//與IPC機制事件相關的一些參數  
  40.     /* thread event */  
  41.     rt_uint32_t event_set; //此線程接收到的事件  
  42.     rt_uint8_t  event_info;//此線程的事件過濾信息,用於過濾事件,只保留感興趣的事件  
  43. #endif  
  44.   
  45.     rt_ubase_t  init_tick;                              /**< thread's initialized tick *///初始tick  
  46.     rt_ubase_t  remaining_tick;                         /**< remaining tick *///剩餘tick  
  47.   
  48.     struct rt_timer thread_timer;                       /**< built-in thread timer *///線程定時器  
  49.   
  50.     void (*cleanup)(struct rt_thread *tid);             /**< cleanup function when thread exit *///相當於線程的析構函數,用於銷燬線程時做些後續操作  
  51.   
  52.     rt_uint32_t user_data;                              /**< private user data beyond this thread *///析構函數的輸入參數  
  53. };  
  54. typedef struct rt_thread *rt_thread_t;  

上面代碼其中線程控制塊的內部成員number, high_mask, number_mask與線程調度時獲獲取當前最高優先級線程的算法有關,這裏不做介紹,詳情請見:http://blog.csdn.net/flydream0/article/details/8588584

event_set, evernt_info與事件相關,在後續講到IPC機制的事件時將會提出,這裏也先不做介紹.

2 線程創建及初始化

2.1 初始化線程

[cpp] view plain copy
  1. /*@{*/  
  2.   
  3. /** 
  4.  * This function will initialize a thread, normally it's used to initialize a 
  5.  * static thread object. 
  6.  * 
  7.  * @param thread the static thread object 
  8.  * @param name the name of thread, which shall be unique 
  9.  * @param entry the entry function of thread 
  10.  * @param parameter the parameter of thread enter function 
  11.  * @param stack_start the start address of thread stack 
  12.  * @param stack_size the size of thread stack 
  13.  * @param priority the priority of thread 
  14.  * @param tick the time slice if there are same priority thread 
  15.  * 
  16.  * @return the operation status, RT_EOK on OK, -RT_ERROR on error 
  17.  */  
  18. rt_err_t rt_thread_init(struct rt_thread *thread,  
  19.                         const char       *name,  
  20.                         void (*entry)(void *parameter),  
  21.                         void             *parameter,  
  22.                         void             *stack_start,  
  23.                         rt_uint32_t       stack_size,  
  24.                         rt_uint8_t        priority,  
  25.                         rt_uint32_t       tick)  
  26. {  
  27.     /* thread check *///參數檢查  
  28.     RT_ASSERT(thread != RT_NULL);  
  29.     RT_ASSERT(stack_start != RT_NULL);  
  30.   
  31.     /* init thread object */  
  32.     rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);//初始化內核對象  
  33.   
  34.     return _rt_thread_init(thread,  
  35.                            name,  
  36.                            entry,  
  37.                            parameter,  
  38.                            stack_start,  
  39.                            stack_size,  
  40.                            priority,  
  41.                            tick);  
  42. }  
其中_rt_thread_init的函數如下定義:
[cpp] view plain copy
  1. static rt_err_t _rt_thread_init(struct rt_thread *thread,  
  2.                                 const char       *name,  
  3.                                 void (*entry)(void *parameter),  
  4.                                 void             *parameter,  
  5.                                 void             *stack_start,  
  6.                                 rt_uint32_t       stack_size,  
  7.                                 rt_uint8_t        priority,  
  8.                                 rt_uint32_t       tick)  
  9. {  
  10.     /* init thread list */  
  11.     rt_list_init(&(thread->tlist));//初始化線程節點  
  12.   
  13.     thread->entry = (void *)entry;//入口函數  
  14.     thread->parameter = parameter;//入口函數的參數  
  15.   
  16.     /* stack init */  
  17.     thread->stack_addr = stack_start;//棧地址  
  18.     thread->stack_size = (rt_uint16_t)stack_size;//棧大小  
  19.   
  20.     /* init thread stack */  
  21.     rt_memset(thread->stack_addr, '#'thread->stack_size);//將棧內的所有字節初始化爲'#'號  
  22.     thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,//初始化時設置sp的內容,rt_hw_stack_init是一個與具體MCU相關的函數,這裏就不做介紹  
  23.         (void *)((char *)thread->stack_addr + thread->stack_size - 4),  
  24.         (void *)rt_thread_exit);  
  25.   
  26.     /* priority init */  
  27.     RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);  
  28.     thread->init_priority    = priority;//當前優先級和初始化優先級設置  
  29.     thread->current_priority = priority;  
  30.   
  31.     /* tick init */  
  32.     thread->init_tick      = tick;//初始化tick和剩餘tick  
  33.     thread->remaining_tick = tick;  
  34.   
  35.     /* error and flags */  
  36.     thread->error = RT_EOK;//錯誤的狀態,線程狀態初始化時爲RT_THREAD_INIT  
  37.     thread->stat  = RT_THREAD_INIT;  
  38.   
  39.     /* initialize cleanup function and user data */  
  40.     thread->cleanup   = 0;//線程析構函數及其參數  
  41.     thread->user_data = 0;  
  42.   
  43.     /* init thread timer */  
  44.     rt_timer_init(&(thread->thread_timer),//初始化線程的定時器  
  45.                   thread->name,  
  46.                   rt_thread_timeout,  
  47.                   thread,  
  48.                   0,  
  49.                   RT_TIMER_FLAG_ONE_SHOT);  
  50.   
  51.     return RT_EOK;  
  52. }  

初始化函數將線程棧內容全部初始化爲'#'號.

其中rt_thread_timeout的函數如下定義:

[cpp] view plain copy
  1. /** 
  2.  * This function is the timeout function for thread, normally which is invoked 
  3.  * when thread is timeout to wait some resource. 
  4.  * 
  5.  * @param parameter the parameter of thread timeout function 
  6.  */  
  7. void rt_thread_timeout(void *parameter)  
  8. {  
  9.     struct rt_thread *thread;  
  10.   
  11.     thread = (struct rt_thread *)parameter;  
  12.   
  13.     /* thread check */  
  14.     RT_ASSERT(thread != RT_NULL);  
  15.     RT_ASSERT(thread->stat == RT_THREAD_SUSPEND);  
  16.   
  17.     /* set error number */  
  18.     thread->error = -RT_ETIMEOUT;//設置此線程的error爲超時錯誤,這些IPC機制中非常有用,  
  19.   
  20.     /* remove from suspend list *///從掛起鏈表中移除  
  21.     rt_list_remove(&(thread->tlist));  
  22.   
  23.     /* insert to schedule ready list */  
  24.     rt_schedule_insert_thread(thread);//加入調度器  
  25.   
  26.     /* do schedule */  
  27.     rt_schedule();//重新調度  
  28. }  

注:當線程進入睡眠時,程序將線程對應的定時器加入到定時器超時鏈表,一旦時間到達,則調用此定時器的超時處理函數,即rt_thread_timeout函數,可上源碼可知,在這個線程定時器超時處理函數內,將會將線程加入到調度器。

此外,需要特別注意地是,此函數會將超時的線程的error設置爲-RT_ETIMEOUT,用來標誌此線程並未獲得IPC,這在IPC機制中判斷某個線程是否已成功獲取某個IPC對象時非常有用。

此超時回調函數主要是將掛起的線程加入到調度器中進行重新調度,即喚醒它。

2.2 創建線程

[cpp] view plain copy
  1. /** 
  2.  * This function will create a thread object and allocate thread object memory 
  3.  * and stack. 
  4.  * 
  5.  * @param name the name of thread, which shall be unique 
  6.  * @param entry the entry function of thread 
  7.  * @param parameter the parameter of thread enter function 
  8.  * @param stack_size the size of thread stack 
  9.  * @param priority the priority of thread 
  10.  * @param tick the time slice if there are same priority thread 
  11.  * 
  12.  * @return the created thread object 
  13.  */  
  14. rt_thread_t rt_thread_create(const char *name,  
  15.                              void (*entry)(void *parameter),  
  16.                              void       *parameter,  
  17.                              rt_uint32_t stack_size,  
  18.                              rt_uint8_t  priority,  
  19.                              rt_uint32_t tick)  
  20. {  
  21.     struct rt_thread *thread;  
  22.     void *stack_start;  
  23.   
  24.     thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,//動態分配一個內核對象  
  25.                                                     name);  
  26.     if (thread == RT_NULL)  
  27.         return RT_NULL;  
  28.   
  29.     stack_start = (void *)rt_malloc(stack_size);//動態分配一個線程棧  
  30.     if (stack_start == RT_NULL)  
  31.     {  
  32.         /* allocate stack failure */  
  33.         rt_object_delete((rt_object_t)thread);  
  34.   
  35.         return RT_NULL;  
  36.     }  
  37.   
  38.     _rt_thread_init(thread,//初始化線程  
  39.                     name,  
  40.                     entry,  
  41.                     parameter,  
  42.                     stack_start,  
  43.                     stack_size,  
  44.                     priority,  
  45.                     tick);  
  46.   
  47.     return thread;  
  48. }  

3 線程的脫離及刪除

3.1 脫離線程

[cpp] view plain copy
  1. /** 
  2.  * This function will detach a thread. The thread object will be removed from 
  3.  * thread queue and detached/deleted from system object management. 
  4.  * 
  5.  * @param thread the thread to be deleted 
  6.  * 
  7.  * @return the operation status, RT_EOK on OK, -RT_ERROR on error 
  8.  */  
  9. rt_err_t rt_thread_detach(rt_thread_t thread)  
  10. {  
  11.     rt_base_t lock;  
  12.   
  13.     /* thread check */  
  14.     RT_ASSERT(thread != RT_NULL);  
  15.   
  16.     /* remove from schedule */  
  17.     rt_schedule_remove_thread(thread);//將線程從調度器中移除  
  18.   
  19.     /* release thread timer */  
  20.     rt_timer_detach(&(thread->thread_timer));//脫離定時器  
  21.   
  22.     /* change stat */  
  23.     thread->stat = RT_THREAD_CLOSE;//將線程的狀態設置爲RT_THREAD_CLOSE  
  24.   
  25.     /* detach object */  
  26.     rt_object_detach((rt_object_t)thread);//脫離內核對象  
  27.   
  28.     if (thread->cleanup != RT_NULL)//如果存在線程析構函數  
  29.     {  
  30.         /* disable interrupt */  
  31.         lock = rt_hw_interrupt_disable();//關中斷  
  32.   
  33.         /* insert to defunct thread list *///rt_thread_defunct鏈表在系統空閒時將被空閒線程來處理  
  34.         rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));//將線程加入到rt_thread_defunct鏈表中  
  35.   
  36.         /* enable interrupt */  
  37.         rt_hw_interrupt_enable(lock);//開中斷  
  38.     }  
  39.   
  40.     return RT_EOK;  
  41. }  

需要注意地是,線程的脫離函數如果當前線程離開進行一些善後工作,即存在cleanup析構函數,此時,會將此線程加入到回收線程鏈表rt_thread_defunct中去,等到系統空閒時再由空閒線程來“回收"此線程,詳情請參考:http://blog.csdn.net/flydream0/article/details/8590415 一文.

3.2 刪除線程

[cpp] view plain copy
  1. /** 
  2.  * This function will delete a thread. The thread object will be removed from 
  3.  * thread queue and detached/deleted from system object management. 
  4.  * 
  5.  * @param thread the thread to be deleted 
  6.  * 
  7.  * @return the operation status, RT_EOK on OK, -RT_ERROR on error 
  8.  */  
  9. rt_err_t rt_thread_delete(rt_thread_t thread)  
  10. {  
  11.     rt_base_t lock;  
  12.   
  13.     /* thread check */  
  14.     RT_ASSERT(thread != RT_NULL);  
  15.   
  16.     /* remove from schedule */  
  17.     rt_schedule_remove_thread(thread);//從調度器中移除線程  
  18.   
  19.     /* release thread timer */  
  20.     rt_timer_detach(&(thread->thread_timer));//脫離定時器  
  21.   
  22.     /* change stat */  
  23.     thread->stat = RT_THREAD_CLOSE;//線程狀態設置爲RT_THREAD_CLOSE  
  24.   
  25.     /* disable interrupt */  
  26.     lock = rt_hw_interrupt_disable();//關中斷  
  27.   
  28.     /* insert to defunct thread list */  
  29.     rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));//將當前線程加入到空閒時纔會處理的鏈表中  
  30.   
  31.     /* enable interrupt */  
  32.     rt_hw_interrupt_enable(lock);//開中斷  
  33.   
  34.     return RT_EOK;  
  35. }  

4 啓動線程

[cpp] view plain copy
  1. /** 
  2.  * This function will start a thread and put it to system ready queue 
  3.  * 
  4.  * @param thread the thread to be started 
  5.  * 
  6.  * @return the operation status, RT_EOK on OK, -RT_ERROR on error 
  7.  */  
  8. rt_err_t rt_thread_startup(rt_thread_t thread)  
  9. {  
  10.     /* thread check *///參數檢查  
  11.     RT_ASSERT(thread != RT_NULL);  
  12.     RT_ASSERT(thread->stat == RT_THREAD_INIT);  
  13.   
  14.     /* set current priority to init priority */  
  15.     thread->current_priority = thread->init_priority;//啓動線程時將線程當前的優先級設置爲初始優先級  
  16.   
  17.     /* calculate priority attribute */  
  18. #if RT_THREAD_PRIORITY_MAX > 32  
  19.     thread->number      = thread->current_priority >> 3;            /* 5bit */  
  20.     thread->number_mask = 1L << thread->number;  
  21.     thread->high_mask   = 1L << (thread->current_priority & 0x07);  /* 3bit */  
  22. #else  
  23.     thread->number_mask = 1L << thread->current_priority;  
  24. #endif  
  25.   
  26.     RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n",  
  27.                                    thread->name, thread->init_priority));  
  28.     /* change thread stat */  
  29.     thread->stat = RT_THREAD_SUSPEND;//將線程的狀態設置爲RT_THREAD_SUSPEND  
  30.     /* then resume it */  
  31.     rt_thread_resume(thread);//還原線程  
  32.     if (rt_thread_self() != RT_NULL)//如果當前的線程不爲空,則執行線程調度操作  
  33.     {  
  34.         /* do a scheduling */  
  35.         rt_schedule();  
  36.     }  
  37.   
  38.     return RT_EOK;  
  39. }  

由此可見,啓動線程時,首先會將線程設置爲掛起狀態,然後再喚醒它。

其中rt_thread_self函數爲獲取當前線程,其源碼如下定義:

[cpp] view plain copy
  1. /** 
  2.  * This function will return self thread object 
  3.  * 
  4.  * @return the self thread object 
  5.  */  
  6. rt_thread_t rt_thread_self(void)  
  7. {  
  8.     return rt_current_thread;  
  9. }  
rt_current_thread爲全局變量,保存當前正在運行的線程。

rt_thread_resume函數見後第6章內容,rt_schedule函數見線程調度源碼分析相關章節.

5 線程掛起

[cpp] view plain copy
  1. /** 
  2.  * This function will suspend the specified thread. 
  3.  * 
  4.  * @param thread the thread to be suspended 
  5.  * 
  6.  * @return the operation status, RT_EOK on OK, -RT_ERROR on error 
  7.  * 
  8.  * @note if suspend self thread, after this function call, the 
  9.  * rt_schedule() must be invoked. 
  10.  */  
  11. rt_err_t rt_thread_suspend(rt_thread_t thread)  
  12. {  
  13.     register rt_base_t temp;  
  14.   
  15.     /* thread check */  
  16.     RT_ASSERT(thread != RT_NULL);  
  17.   
  18.     RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend:  %s\n"thread->name));  
  19.   
  20.     if (thread->stat != RT_THREAD_READY)//此函數只對處於就緒狀態的線程操作  
  21.     {  
  22.         RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, %d\n",  
  23.                                        thread->stat));  
  24.           
  25.         return -RT_ERROR;  
  26.     }  
  27.   
  28.     /* disable interrupt */  
  29.     temp = rt_hw_interrupt_disable();//關中斷  
  30.   
  31.     /* change thread stat */  
  32.     thread->stat = RT_THREAD_SUSPEND;//將線程設置爲掛起狀態  
  33.     rt_schedule_remove_thread(thread);//將線程從調試器中移除  
  34.   
  35.     /* enable interrupt */  
  36.     rt_hw_interrupt_enable(temp);//開中斷  
  37.   
  38.     return RT_EOK;  
  39. }  

有關rt_schedule_remove_thread函數見後續在前調度器源碼分析的文章。

此函數比較簡單。

6 線程喚醒

[cpp] view plain copy
  1. /** 
  2.  * This function will resume a thread and put it to system ready queue. 
  3.  * 
  4.  * @param thread the thread to be resumed 
  5.  * 
  6.  * @return the operation status, RT_EOK on OK, -RT_ERROR on error 
  7.  */  
  8. rt_err_t rt_thread_resume(rt_thread_t thread)  
  9. {  
  10.     register rt_base_t temp;  
  11.   
  12.     /* thread check */  
  13.     RT_ASSERT(thread != RT_NULL);  
  14.   
  15.     RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume:  %s\n"thread->name));  
  16.   
  17.     if (thread->stat != RT_THREAD_SUSPEND)//只對處於掛起的線程進行還原操作  
  18.     {  
  19.         RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",  
  20.                                        thread->stat));  
  21.   
  22.         return -RT_ERROR;  
  23.     }  
  24.   
  25.     /* disable interrupt */  
  26.     temp = rt_hw_interrupt_disable();//關中斷  
  27.   
  28.     /* remove from suspend list */  
  29.     rt_list_remove(&(thread->tlist));//從掛起隊列中移除  
  30.   
  31.     /* remove thread timer */  
  32.     rt_list_remove(&(thread->thread_timer.list));//因線程即將運行,所以需要移除定時器,無需再定時  
  33.   
  34.     /* change timer state */  
  35.     thread->thread_timer.parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;//將內核對象的標誌設置爲定時器非激活標誌  
  36.   
  37.     /* enable interrupt */  
  38.     rt_hw_interrupt_enable(temp);//開中斷  
  39.   
  40.     /* insert to schedule ready list */  
  41.     rt_schedule_insert_thread(thread);//將線程加入調度器  
  42.   
  43.     return RT_EOK;  
  44. }  
由上源碼可見,此函數只是將線程加入到調度器就緒隊列中,並沒有真正喚醒它,而真正喚醒線程需要rt_schedule.

7 線程讓出處理機

當前線程的時間片用完或者該線程自動要求讓出處理器資源時,它不再佔有處理機,調度器會選擇下一個最高優先級的線程執行。這時,放棄處理器資源的線程仍然在就緒隊列中,只不過放到就緒隊列末尾去 了.

[cpp] view plain copy
  1. /** 
  2.  * This function will let current thread yield processor, and scheduler will 
  3.  * choose a highest thread to run. After yield processor, the current thread 
  4.  * is still in READY state. 
  5.  * 
  6.  * @return RT_EOK 
  7.  */  
  8. rt_err_t rt_thread_yield(void)  
  9. {  
  10.     register rt_base_t level;  
  11.     struct rt_thread *thread;  
  12.   
  13.     /* disable interrupt */  
  14.     level = rt_hw_interrupt_disable();//關中斷  
  15.   
  16.     /* set to current thread */  
  17.     thread = rt_current_thread;//得到當前線程  
  18.   
  19.     /* if the thread stat is READY and on ready queue list */  
  20.     if (thread->stat == RT_THREAD_READY &&//如果當前線程處於就緒狀態且在就緒隊列  
  21.         thread->tlist.next != thread->tlist.prev)  
  22.     {  
  23.         /* remove thread from thread list */  
  24.         rt_list_remove(&(thread->tlist));//從就緒隊列中移除當前線程  
  25.   
  26.         /* put thread to end of ready queue */  
  27.         rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),//加入到就緒隊列末尾  
  28.                               &(thread->tlist));  
  29.   
  30.         /* enable interrupt */  
  31.         rt_hw_interrupt_enable(level);//開中斷  
  32.   
  33.         rt_schedule();//重新調度線程  
  34.   
  35.         return RT_EOK;  
  36.     }  
  37.   
  38.     /* enable interrupt */  
  39.     rt_hw_interrupt_enable(level);//開中斷  
  40.   
  41.     return RT_EOK;  
  42. }  
此函數用於線程的時間片耗盡時,就此線程掛起後加入到就緒隊列的末端,然後再等待下一次調度。

8 線程睡眠

[cpp] view plain copy
  1. /** 
  2.  * This function will let current thread sleep for some ticks. 
  3.  * 
  4.  * @param tick the sleep ticks 
  5.  * 
  6.  * @return RT_EOK 
  7.  */  
  8. rt_err_t rt_thread_sleep(rt_tick_t tick)  
  9. {  
  10.     register rt_base_t temp;  
  11.     struct rt_thread *thread;  
  12.   
  13.     /* disable interrupt */  
  14.     temp = rt_hw_interrupt_disable();//關中斷  
  15.     /* set to current thread */  
  16.     thread = rt_current_thread;//得到當前線程  
  17.     RT_ASSERT(thread != RT_NULL);  
  18.   
  19.     /* suspend thread */  
  20.     rt_thread_suspend(thread);//掛起當前線程  
  21.   
  22.     /* reset the timeout of thread timer and start it */  
  23.     rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);//設置定時器  
  24.     rt_timer_start(&(thread->thread_timer));//啓動定時器  
  25.   
  26.     /* enable interrupt */  
  27.     rt_hw_interrupt_enable(temp);//開中斷  
  28.   
  29.     rt_schedule();//啓動調度器  
  30.   
  31.     /* clear error number of this thread to RT_EOK */  
  32.     if (thread->error == -RT_ETIMEOUT)//將當前線程的錯誤碼設置爲超時  
  33.         thread->error = RT_EOK;  
  34.   
  35.     return RT_EOK;  
  36. }  

[cpp] view plain copy
  1. /** 
  2.  * This function will let current thread delay for some ticks. 
  3.  * 
  4.  * @param tick the delay ticks 
  5.  * 
  6.  * @return RT_EOK 
  7.  */  
  8. rt_err_t rt_thread_delay(rt_tick_t tick)  
  9. {  
  10.     return rt_thread_sleep(tick);  
  11. }  
此函數是將當前線程掛起後,然後開啓線程中的定時器,並等待定時器時間到達,一旦到達,定時器超時回調函數中將會將此線程重新加入到就緒隊列,並重新調度。見2.1節的rt_thread_timeout函數實現部分。

9 線程控制

[cpp] view plain copy
  1. /** 
  2.  * This function will control thread behaviors according to control command. 
  3.  * 
  4.  * @param thread the specified thread to be controlled 
  5.  * @param cmd the control command, which includes 
  6.  *  RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread; 
  7.  *  RT_THREAD_CTRL_STARTUP for starting a thread; 
  8.  *  RT_THREAD_CTRL_CLOSE for delete a thread. 
  9.  * @param arg the argument of control command 
  10.  * 
  11.  * @return RT_EOK 
  12.  */  
  13. rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void *arg)  
  14. {  
  15.     register rt_base_t temp;  
  16.   
  17.     /* thread check */  
  18.     RT_ASSERT(thread != RT_NULL);  
  19.   
  20.     switch (cmd)  
  21.     {  
  22.     case RT_THREAD_CTRL_CHANGE_PRIORITY://修改優先級  
  23.         /* disable interrupt */  
  24.         temp = rt_hw_interrupt_disable();//關中斷  
  25.   
  26.         /* for ready thread, change queue */  
  27.         if (thread->stat == RT_THREAD_READY)//如果線程處於就緒狀態  
  28.         {  
  29.             /* remove thread from schedule queue first */  
  30.             rt_schedule_remove_thread(thread);//移除  
  31.   
  32.             /* change thread priority */  
  33.             thread->current_priority = *(rt_uint8_t *)arg;//設置優先級  
  34.   
  35.             /* recalculate priority attribute */  
  36. #if RT_THREAD_PRIORITY_MAX > 32  
  37.             thread->number      = thread->current_priority >> 3;            /* 5bit */  
  38.             thread->number_mask = 1 << thread->number;  
  39.             thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */  
  40. #else  
  41.             thread->number_mask = 1 << thread->current_priority;  
  42. #endif  
  43.   
  44.             /* insert thread to schedule queue again */  
  45.             rt_schedule_insert_thread(thread);//加入調度器  
  46.         }  
  47.         else  
  48.         {  
  49.             thread->current_priority = *(rt_uint8_t *)arg;  
  50.   
  51.             /* recalculate priority attribute */  
  52. #if RT_THREAD_PRIORITY_MAX > 32  
  53.             thread->number      = thread->current_priority >> 3;            /* 5bit */  
  54.             thread->number_mask = 1 << thread->number;  
  55.             thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */  
  56. #else  
  57.             thread->number_mask = 1 << thread->current_priority;  
  58. #endif  
  59.         }  
  60.   
  61.         /* enable interrupt */  
  62.         rt_hw_interrupt_enable(temp);  
  63.         break;  
  64.   
  65.     case RT_THREAD_CTRL_STARTUP://啓動  
  66.         return rt_thread_startup(thread);  
  67.   
  68. #ifdef RT_USING_HEAP  
  69.     case RT_THREAD_CTRL_CLOSE://關閉線程  
  70.         return rt_thread_delete(thread);  
  71. #endif  
  72.   
  73.     default:  
  74.         break;  
  75.     }  
  76.   
  77.     return RT_EOK;  
  78. }  
此函數在修改線程優先級時,當線程處於就緒狀態時,爲了安全起見,首先將線程從就緒隊列中移除,然後再修改優先級,最後再次線程重新加入到調度器的就緒隊列中。

10 查找線程

[cpp] view plain copy
  1. /** 
  2.  * This function will find the specified thread. 
  3.  * 
  4.  * @param name the name of thread finding 
  5.  * 
  6.  * @return the found thread 
  7.  * 
  8.  * @note please don't invoke this function in interrupt status. 
  9.  */  
  10. rt_thread_t rt_thread_find(char *name)  
  11. {  
  12.     struct rt_object_information *information;  
  13.     struct rt_object *object;  
  14.     struct rt_list_node *node;  
  15.   
  16.     extern struct rt_object_information rt_object_container[];  
  17.   
  18.     /* enter critical */  
  19.     if (rt_thread_self() != RT_NULL)  
  20.         rt_enter_critical();//進入臨界區  
  21.   
  22.     /* try to find device object */  
  23.     information = &rt_object_container[RT_Object_Class_Thread];//從內核對象容器中獲取內核對象鏈表  
  24.     for (node  = information->object_list.next;  
  25.          node != &(information->object_list);  
  26.          node  = node->next)  
  27.     {  
  28.         object = rt_list_entry(node, struct rt_object, list);//得到內核對象  
  29.         if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)//比較名字  
  30.         {  
  31.             /* leave critical */  
  32.             if (rt_thread_self() != RT_NULL)  
  33.                 rt_exit_critical();//退出臨界區  
  34.   
  35.             return (rt_thread_t)object;//返回內核對象  
  36.         }  
  37.     }  
  38.   
  39.     /* leave critical */  
  40.     if (rt_thread_self() != RT_NULL)  
  41.         rt_exit_critical();//退出臨界區  
  42.   
  43.     /* not found */  
  44.     return RT_NULL;//返回未找到  
  45. }  

查找線程是通過內核對象管理系統來查找的,根據內核對象的類型,找到相應內核對象鏈表,並遍歷它,比較名字,如果找到則返回。

需要注意的是,這裏的進入臨界區的功能只是讓調度器暫時停止工作,即停止調度線程,而退出臨界區則是讓停止工作的調度器重新恢復工作。這樣做的理由是防止臨界區內的執行調度器終止,切換到其它線程去了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章