RT-Thread內核實現(六):時間片

整體思想

  • 假如A、B兩個線程優先級相同,A先啓動,只要A不主動讓出CPU,線程B就沒機會執行。
  • 時間片就是爲了解決相同優先級下多線程的併發問題。

線程控制塊

  • 添加rt_ubase_t init_tick屬性,remaining_tick記錄剩餘的時間片。
struct rt_thread
{
    /* rt 對象 */
    char        name[RT_NAME_MAX];    /* 對象的名字 */
    rt_uint8_t  type;                 /* 對象類型 */
    rt_uint8_t  flags;                /* 對象的狀態 */
    rt_list_t   list;                 /* 對象的列表節點 */
    
    rt_list_t   tlist;            /* 線程鏈表節點 */
    
	void        *sp;	          /* 線程棧指針 */
	void        *entry;	          /* 線程入口地址 */
	void        *parameter;	      /* 線程形參 */	
	void        *stack_addr;      /* 線程起始地址 */
	rt_uint32_t stack_size;       /* 線程棧大小,單位爲字節 */
    
    rt_ubase_t  init_tick;          /* 初始時間片 */
    rt_ubase_t  remaining_tick;     /* 剩餘時間片 */
    
    rt_uint8_t current_priority;    /* 當前優先級 */
    rt_uint8_t init_priority;       /* 初始優先級 */
    rt_uint32_t number_mask;        /* 當前優先級掩碼 */
    
    rt_err_t    error;              /* 錯誤碼 */
    
    rt_uint8_t stat;                /* 線程的狀態 */
    
    struct rt_timer thread_timer;   /* 內置的線程定時器 */
};
typedef struct rt_thread *rt_thread_t;

線程初始化函數修改

/* 初始化線程 */
    rt_thread_init( &rt_flag1_thread,                   /* 線程控制塊 */
                    "rt_flag1_thread",                  /* 線程名字,字符串形式 */
                    flag1_thread_entry,                 /* 線程入口地址 */    
                    RT_NULL,                            /* 線程形參 */
                    &rt_flag1_thread_stack[0],          /* 線程棧起始地址 */    
                    sizeof(rt_flag1_thread_stack),      /* 線程棧大小 */
                    2,                                  /* 線程優先級 */
                    4);                                 /* 時間片 */

時基更新函數修改

  • 如果時間片到了就重置時間片,調用rt_thread_yield()讓出CPU。
void rt_tick_increase(void)
{
    struct rt_thread *thread;
    rt_tick ++;
    
    thread = rt_thread_self();
    --thread->remaining_tick;
    
    if(thread->remaining_tick == 0){
        /* 重置時間片 */
        thread->remaining_tick = thread->init_tick;
        
        /* 讓出CPU */
        rt_thread_yield();
    }
    
    /* 掃描系統定時器列表 */
	rt_timer_check();
}
  • 函數rt_err_t rt_thread_yield(void)
/**
 * 該函數將讓當前線程讓出處理器,調度器選擇最高優先級的線程運行。當前讓出處理器之後,
 * 當前線程還是在就緒態。
 *
 * @return RT_EOK
 */
rt_err_t rt_thread_yield(void)
{
    register rt_base_t level;
    struct rt_thread *thread;

    /* 關中斷 */
    level = rt_hw_interrupt_disable();

    /* 獲取當前線程的線程控制塊 */
    thread = rt_current_thread;
    
    /* 如果線程在就緒態,且同一個優先級下不止一個線程 */
    if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY &&
        thread->tlist.next != thread->tlist.prev)
    {
        /* 將時間片耗完的線程從就緒列表移除 */
        rt_list_remove(&(thread->tlist));
        
        /* 將線程插入到該優先級下的鏈表的尾部 */
        rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
                              &(thread->tlist));

        /* 開中斷 */
        rt_hw_interrupt_enable(level);

        /* 執行調度 */
        rt_schedule();

        return RT_EOK;
    }

    /* 開中斷 */
    rt_hw_interrupt_enable(level);

    return RT_EOK;
}

工程代碼

12_time_slice

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