RTThreadIoTOS · 2021年03月11日

RT-Thread隐藏的宝藏之completion

1. completion 是什么

completion 直接翻译过来是完成,所以我们可以称 rt_completion完成量。在 RT-Thread 的文档中心 中讲线程间同步时,介绍了 信号量互斥量事件集 。 rt_completion 是一个 轻量级的二值信号量

image.png

2.  completion 怎么使用

completion 的使用非常简单

  1. 定义一个完成量

    1struct rt_completion completion;
  2. 初始化完成量

    1rt_completion_init(&completion);
  3. 等待完成量

    1rt_completion_wait(&completion);
  4. 释放完成量
    <br />rt_completion_done(&amp;completion);<br />

3.  completion 的实现

completion 的 API 非常少,可以通过简单的代码去分析

  1. 初始化完成量

     1void rt_completion_init(struct rt_completion *completion) 2{ 3   rt_base_t level; 4   RT_ASSERT(completion != RT_NULL); 5 6   level = rt_hw_interrupt_disable(); 7   completion->flag = RT_UNCOMPLETED; 8   rt_list_init(&completion->suspended_list); 9   rt_hw_interrupt_enable(level);10}

    干了两件事:

  • 设置 flagRT_UNCOMPLETED
  • 初始化完成量的链表

2.等待完成量(以下代码有删减)

 1rt_err_t rt_completion_wait(struct rt_completion *completion, 2                            rt_int32_t            timeout) 3{ 4    result = RT_EOK; 5    thread = rt_thread_self(); 6 7    level = rt_hw_interrupt_disable(); 8    if (completion->flag != RT_COMPLETED) 9    {10        if (timeout == 0)11        {1213        }14        else15        {16            /* reset thread error number */17            thread->error = RT_EOK;1819            /* suspend thread */20            rt_thread_suspend(thread);21            /* add to suspended list */22            rt_list_insert_before(&(completion->suspended_list),23                                  &(thread->tlist));2425            /* current context checking */26            RT_DEBUG_NOT_IN_INTERRUPT;2728            /* start timer */29            if (timeout > 0)30            {31                /* reset the timeout of thread timer and start it */32                rt_timer_control(&(thread->thread_timer),33                                 RT_TIMER_CTRL_SET_TIME,34                                 &timeout);35                rt_timer_start(&(thread->thread_timer));36            }37            /* enable interrupt */38            rt_hw_interrupt_enable(level);3940            /* do schedule */41            rt_schedule();4243            /* thread is waked up */44            result = thread->error;4546            level = rt_hw_interrupt_disable();47        }48    }49    /* clean completed flag */50    completion->flag = RT_UNCOMPLETED;5152    return result;53}

主要做了以下工作:

  • 关中断:rt\_hw\_interrupt\_disable();
  • 挂起当前线程:rt\_thread\_suspend(thread);
  • 把挂起状态插入到线程的链表中:rt\_list\_insert\_before
  • 确保当前函数执行不是在中断中:RT\_DEBUG\_NOT\_IN\_INTERRUPT;
  • 设置并启动定时器:rt\_timer\_start(&(thread->thread\_timer));
  • 开中断:rt\_hw\_interrupt\_enable(level);
  • 开调度器:rt\_schedule();
  • 获取当前线程状态:result = thread->error;
  • 设置完成量的标志位:completion->flag = RT\_UNCOMPLETED;
  • 返回线程状态

    这样就完成了线程的挂起。

3.完成完成量(以下代码有删减)

 1   void rt_completion_done(struct rt_completion *completion) 2   { 3       level = rt_hw_interrupt_disable(); 4       completion->flag = RT_COMPLETED; 5 6       if (!rt_list_isempty(&(completion->suspended_list))) 7       { 8           /* there is one thread in suspended list */ 9           struct rt_thread *thread;1011           /* get thread entry */12        thread = rt_list_entry(completion->suspended_list.next,13                                  struct rt_thread,14                               tlist);1516           /* resume it */17           rt_thread_resume(thread);18           rt_hw_interrupt_enable(level);1920           /* perform a schedule */21           rt_schedule();22       }23   }

主要做了以下工作:

  • 关中断:rt\_hw\_interrupt\_disable();
  • 设置 flagRT_COMPLETED
  • 检查链表不为空:rt\_list\_isempty
  • 获取到当前等待完成量的句柄:rt\_list\_entry
  • 启动被挂起的线程:rt\_thread\_resume(thread);
  • 开中断:rt\_hw\_interrupt\_enable(level);
  • 开调度:rt\_schedule();

4. completion 与信号量的对比

  1. completion API 个数少,资源占用少,只能释放获取,不支持多次释放
  2. semaphore API 个数多,资源占用较多,使用灵活,可以尝试获取,可以多次释放,

5. completion 如何加入工程

  1. 标准版 RT-Thread 中的 completion 源码在 "\rt-thread\components\drivers\src\completion.c"在你要使用的文件中#include completion.h直接就可以使用。
  2. Nano 版 RT-Thread 直接拷贝completion.ccompletion.h 添加到工程就可以使用

推荐阅读
【20210305期AI简报】基于TensorRT完成NanoDet模型部署
【20210219期AI简报】嵌入式机器学习(TinyML)实战教程、谷歌开源计算框架JAX...
【20210205期AI简报】联发科发布二代5G基带芯片发布

文章转载于微信公众号:RTThread物联网操作系统
作者:王海靖
推荐阅读
关注数
8072
内容数
181
小而美的物联网操作系统,经过14年的累积发展,RT-Thread 已经拥有一个国内最大的嵌入式开源社区,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过4亿台,成为国人自主开发、国内最成熟稳定和装机量最大的开源 RTOS。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息