RT-Thread—線程掛起與恢復

爲什麼要線程管理

在RTT中,線程是競爭系統運行資源的最小運行單位,而且RTT是一個支持多線程的操作系統,所以就會有各種線程要佔用CPU的資源。由於線程都是獨立的,每個線程都有單獨的堆棧空間、運行狀態…
所以,在線程進行切換的時候就很有必要保存每個線程的相關信息,即線程切換時的上下文環境(寄存器值、堆棧內容),這也是調度器的主要職責,當線程再次運行的時候,就可以從堆棧中找到上次運行的環境,從而恢復運行環境。
瞭解線程管理的必要性後還要知道RTT中的調度方式:

  • 搶佔式調度
  • 支持時間片輪轉調度

也就是不同優先級之間支持搶佔式調度,同一優先級間採用時間片輪轉機制。

線程的五種狀態

RTT中,線程有五種狀態:

  • 初始態:線程創建之初就是初始態,此時還不能被調度
  • 就緒態:此時線程在就緒列表中,可以被調度
  • 運行態:此時線程正在執行,佔用CPU
  • 掛起態:線程不在就緒列表,但也沒有被刪除,處於等待狀態
  • 關閉態:此時線程運行結束,等待系統回收資源

總之RTT的線程就是在這五種狀態之間轉換,轉換規則如圖:
在這裏插入圖片描述

1.以就緒態爲中心,就緒態可以在掛起態和運行態之間切換;
2.運行態可以直接變爲掛起態,但掛起態必須經過就緒態才能轉換爲運行態;
3.只有運行態或者掛起態纔可以直接關閉;
4.線程只有在創建之初纔是初始態,通過rt_thread_startup()函數來進入就緒態。

線程掛起函數rt_thread_suspend()

可以用rt_thread_suspend()函數來實現對指定線程的掛起,當然,rt_thread_delay()函數也可以實現線程的掛起,rt_thread_delay()使線程進入阻塞,效果和掛起一樣。這裏主要熟悉一下rt_thread_suspend()函數,下面是RTT官方源代碼:

/**
 * 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_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;
}

很簡單,使用時只需要把線程控制塊指針傳入形參即可,返回值會反饋掛起成功與否。

線程恢複函數rt_thread_resume()

既然有掛起,就會有恢復。線程恢複函數rt_thread_resume()可以將線程從掛起態之間轉換爲就緒態(如果該線程優先級爲最高,之間轉到運行態),看一下RTT官方的源代碼:

/**
 * 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_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;
}

用法與掛起函數類似,只要傳入指定線程的線程控制塊即可,返回值會反饋恢復的結果。

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