1. completion 是什么
completion 直接翻译过来是完成,所以我们可以称 rt_completion 为 完成量。在 RT-Thread 的文档中心 中讲线程间同步时,介绍了 信号量, 互斥量, 事件集 。 rt_completion 是一个 轻量级的二值信号量。
2. completion 怎么使用
completion 的使用非常简单
定义一个完成量
1struct rt_completion completion;
初始化完成量
1rt_completion_init(&completion);
等待完成量
1rt_completion_wait(&completion);
释放完成量
《br /》rt_completion_done(&completion);《br /》
3. completion 的实现
completion 的 API 非常少,可以通过简单的代码去分析
初始化完成量
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}
干了两件事:
设置 flag 为 RT_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 {
12
13 }
14 else
15 {
16 /* reset thread error number */
17 thread-》error = RT_EOK;
18
19 /* suspend thread */
20 rt_thread_suspend(thread);
21 /* add to suspended list */
22 rt_list_insert_before(&(completion-》suspended_list),
23 &(thread-》tlist));
24
25 /* current context checking */
26 RT_DEBUG_NOT_IN_INTERRUPT;
27
28 /* 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);
39
40 /* do schedule */
41 rt_schedule();
42
43 /* thread is waked up */
44 result = thread-》error;
45
46 level = rt_hw_interrupt_disable();
47 }
48 }
49 /* clean completed flag */
50 completion-》flag = RT_UNCOMPLETED;
51
52 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;
10
11 /* get thread entry */
12 thread = rt_list_entry(completion-》suspended_list.next,
13 struct rt_thread,
14 tlist);
15
16 /* resume it */
17 rt_thread_resume(thread);
18 rt_hw_interrupt_enable(level);
19
20 /* perform a schedule */
21 rt_schedule();
22 }
23 }
主要做了以下工作:
关中断: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 源码在 “ t-threadcomponentsdriverssrccompletion.c”在你要使用的文件中#include completion.h直接就可以使用。
Nano 版 RT-Thread 直接拷贝completion.c 和 completion.h 添加到工程就可以使用
编辑:lyn
全部0条评论
快来发表一下你的评论吧 !