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;
}

用法与挂起函数类似,只要传入指定线程的线程控制块即可,返回值会反馈恢复的结果。

发布了62 篇原创文章 · 获赞 188 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_43743762/article/details/103154099