让线程既阻塞等待信号量又能执行周期任务的方法

在使用RTOS时,我们可能会遇到这样一种场景:一个线程既要阻塞等待信号量或邮箱,又要执行周期性任务。本文介绍一种简单的方法来实现该需求。

以信号量为例,一般的RTOS提供的信号量请求具有以下3种请求方法:

①. 无限等待,即一直阻塞等待信号量。

②. 超时等待,即设定一个超时时间,如果超时时间内还没有获取到信号量,则不再继续等待,线程继续执行。

③. 尝试等待,即尝试获取信号量,如果获取不到则线程立即继续执行。

我们可以使用超时等待的方法来实现线程既阻塞等待信号量,有能执行周期性任务,体的思路如下:将周期性任务的剩余超时时间作为要等待的信号量的超时时间,如果在超时时间内没有获取到信号量,就会退出信号量的等待,此时周期性任务的超时时间也刚好到了,可以执行一次周期性任务;如果在超时时间内获取到了信号量,则先处理信号量然后重新计算周期性任务的剩余超时时间,然后以该时间为信号量的超时时间重新等待信号量。流程图如下。

线程处理流程图

使用这种方法,既不会错过信号量消息,又可以定时执行周期任务,一举两得。事实上,LWIP中就使用了这种方法,以下代码简化了源码,代码注释中提到的超时事件就是上文指的周期任务。 

static void tcpip_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
{
    u32_t sleeptime, res;

again:
    LWIP_ASSERT_CORE_LOCKED();

    /* 获取超时事件的剩余超时时间 */
    sleeptime = sys_timeouts_sleeptime();

    /* 如果超时事件的超时时间是永久,那么永久等待信号量 */
    if (sleeptime == SYS_TIMEOUTS_SLEEPTIME_INFINITE)
    {
        UNLOCK_TCPIP_CORE();
        sys_arch_mbox_fetch(mbox, msg, 0);
        LOCK_TCPIP_CORE();
        return;
    }
    /* 如果超时事件的超时时间已到,执行一次超时处理 */
    else if (sleeptime == 0)
    {
        sys_check_timeouts(); 
        goto again;
    }

    UNLOCK_TCPIP_CORE();

    /* 以sleeptime作为信号量的请求超时,请求信号量 */
    res = sys_arch_mbox_fetch(mbox, msg, sleeptime); 

    LOCK_TCPIP_CORE();

    /* 信号量等待超时,说明超时事件刚好超时,执行一次超时处理 */
    if (res == SYS_ARCH_TIMEOUT)
    {
        sys_check_timeouts();
        goto again;
    }
}

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dokin丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值