completion是什么?completion怎么使用呢?

电子说

1.3w人已加入

描述

1.completion 是什么

completion 直接翻译过来是完成,所以我更愿意称 rt_completion 为 完成量。在 RT-Thread 的文档中心 中讲线程间通讯(IPC)时,只介绍了,信号量, 互斥量, 事件集,其实 rt_completion 可以认为是轻量级的二值信号量。

2.completion 怎么使用

completion 的使用非常简单

定义一个完成量

struct rt_completion completion;

初始化完成量

rt_completion_init(&completion);

等待完成量

rt_completion_wait(&completion);

释放完成量

rt_completion_done(&completion);

3.completion 的实现

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

初始化完成量

void rt_completion_init(struct rt_completion *completion)

{

rt_base_t level;

RT_ASSERT(completion != RT_NULL);

level = rt_hw_interrupt_disable();

completion->flag = RT_UNCOMPLETED;

rt_list_init(&completion->suspended_list);

rt_hw_interrupt_enable(level);

}

干了两件事:

设置 flag 为 RT_UNCOMPLETED

初始化完成量的链表

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

rt_err_t rt_completion_wait(struct rt_completion *completion,

rt_int32_t timeout)

{

result = RT_EOK;

thread = rt_thread_self();

level = rt_hw_interrupt_disable();

if (completion->flag != RT_COMPLETED)

{

if (timeout == 0)

{

}

else

{

/* reset thread error number */

thread->error = RT_EOK;

/* suspend thread */

rt_thread_suspend(thread);

/* add to suspended list */

rt_list_insert_before(&(completion->suspended_list),

&(thread->tlist));

/* current context checking */

RT_DEBUG_NOT_IN_INTERRUPT;

/* start timer */

if (timeout > 0)

{

/* reset the timeout of thread timer and start it */

rt_timer_control(&(thread->thread_timer),

RT_TIMER_CTRL_SET_TIME,

&timeout);

rt_timer_start(&(thread->thread_timer));

}

/* enable interrupt */

rt_hw_interrupt_enable(level);

/* do schedule */

rt_schedule();

/* thread is waked up */

result = thread->error;

level = rt_hw_interrupt_disable();

}

}

/* clean completed flag */

completion->flag = RT_UNCOMPLETED;

return result;

}

主要做了以下工作:

关中断: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;

返回线程状态

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

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

void rt_completion_done(struct rt_completion *completion)

{

level = rt_hw_interrupt_disable();

completion->flag = RT_COMPLETED;

if (!rt_list_isempty(&(completion->suspended_list)))

{

/* there is one thread in suspended list */

struct rt_thread *thread;

/* get thread entry */

thread = rt_list_entry(completion->suspended_list.next,

struct rt_thread,

tlist);

/* resume it */

rt_thread_resume(thread);

rt_hw_interrupt_enable(level);

/* perform a schedule */

rt_schedule();

}

}

主要做了以下工作:

关中断:rt_hw_interrupt_disable();

设置 flag 为 RT_COMPLETED

检查链表不为空:rt_list_isempty

获取到当前等待完成量的句柄:rt_list_entry

启动被挂起的线程:rt_thread_resume(thread);

开中断:rt_hw_interrupt_enable(level);

开调度:rt_schedule();

4.completion 与信号量的对比

completion API 个数少,资源占用少,只能释放获取,不支持多次释放

semaphore API 个数多,资源占用较多,使用灵活,可以尝试获取,可以多次释放,

5.completion 如何加入工程

标准版 RT-Thread 中的 completion 源码在 "\\rt-thread\\components\\drivers\\src\\completion.c"在你要使用的文件中#include completion.h直接就可以使用。

Nano 版 RT-Thread 直接拷贝completion.c 和 completion.h 添加到工程就可以使用。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分