RT-Thread隐藏的宝藏之completion

[RTT] RT-Thread线程调度机制、线程切换时机分析 目录1. 问题2. 验证3. 代码分析3. 总结 1. 问题 最初接触RTT时,对于线程切换时机的相关概念主要来自以下几个方面: RTT在创建线程时,需要输入线程的时间片参数,时间片的单位为OS Tick。 线程休眠函数rt_thread_delay()、设置软件定时器、以及一些如信号量、邮箱等可以设置timeout的线程间通讯和同步方式,设置的时间参数都是以OS Tick为最小单位。 RTT文档也写出:操作系统中最小的时间单位是时钟节拍 (OS Tick)。 由此,我便将其理解为:OS Tick也是 阅读详情
  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);
  1. 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();
  1. completion 与信号量的对比

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

  2. completion 如何加入工程

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

原文链接:https://club.rt-thread.org/ask/article/2500.html

RT-Thread completion机制解析:嵌入式线程同步的轻量级解决方案 嵌入式实时操作系统中,线程同步是确保多任务正确协作的核心机制。常见的同步原语如信号量和互斥量主要用于资源管理和临界区保护,但在处理“一次性完成事件”时存在语义模糊和误用风险。completion完成量)作为一种专为等待单一操作完成而设计的同步机制,通过内置状态标志和等待队列,实现了更清晰、更安全的同步语义。其原理基于状态检查与广播唤醒,在线程等待条件满足时立即返回,避免了信号量计数管理的复杂性。这一机制在驱动开发、硬件初始化、模块加载等场景中具有重要价值,能有效防止因信号量误操作导致的同步错误。本文结合 阅读详情

相关推荐

RT-Thread完成量:轻量级线程同步原语的设计与实战

嵌入式实时操作系统开发中,线程同步是确保多任务协调运行的基础技术。其核心原理是通过特定的机制,让一个或多个线程在特定条件满足前暂停执行,待条件达成后再被唤醒继续工作,从而保证数据一致性和执行顺序。这种同步机制的技术价值在于能够有效管理共享资源,避免竞态条件,提升系统可靠性和可预测性。在应用场景上,线程同步广泛用于设备驱动开发、任务间精准握手、生产者-消费者模型等需要严格时序控制的场合。本文聚焦于RT-Thread实时操作系统中的完成量completion),这是一个专为“等待-完成”一对一同步模式设计的

weixin_30954817的博客 343

RT-Thread 隐藏宝藏completion

1. completion 是什么 completion 直接翻译过来是完成,所以我更愿意称 rt_completion完成量。在 RT-Thread 的文档中心 中讲线程间通讯(IPC)时,只介绍了,信号量, 互斥量, 事件集,其实 rt_completion 可以认为是轻量级的二值信号量。 2. completion 怎么使用 completion 的使用非常简单 定义一个完成量 struct rt_completion completion; 初始化完成量 rt_completio

whj123999的博客 1149

RTT学习笔记10- 设备IPC 完成量-ringbufffer-workwueue

设备IPC 完成量-ringbufffer-workwueue

Car12 761

rtthread-ipc之completion

这是一个较为简单的线程同步通信机制,当然截至写稿之前我也不懂,但是从代码来看,还是比较简单。 一 首先查看completion.h文件 #ifndef COMPLETION_H_ #define COMPLETION_H_ #include /** * Completion */ struct rt_completion { rt_uint32_t flag; /* suspended lis...

Kk_01110001B的博客 1573

RT-Thread Device IPC Completion

completion 可以称之为完成量,是一种轻量级的线程间(IPC)同步机制,举一个生活中的例子来理解下,公交车上的售票员是一个线程 1,公交车司机是一个线程 2,只有当公交车司机停车后,售票员才能把车门打开。即售票员 (线程 1) 等待司机(线程 2)停车(完成了某件事)后,当售票员(线程 1)才能开门(做某件事)。其中 flag,表征当前完成量对象的状态,用下面的两个宏表示,即当 flag 值为 RT_COMPLETED 时,表征当前完成量对象已完成了某一个工作,可以继续下一个工作;

华为奋斗者精神 928

RT-Thread completion嵌入式多线程同步的隐藏宝藏

嵌入式多线程编程中,线程同步是确保数据一致性和系统稳定性的核心机制。其原理在于通过操作系统提供的同步原语,协调多个线程对共享资源的访问顺序,避免竞态条件和数据损坏。从技术价值看,高效的同步机制能显著降低CPU占用率,提升系统整体吞吐量,尤其在资源受限的嵌入式环境中至关重要。常见的应用场景包括设备初始化等待、生产者-消费者数据传递、以及异步操作(如DMA传输)的同步化处理。本文聚焦于RT-Thread操作系统中的completion完成量)组件,它作为一种轻量级、语义清晰的同步工具,专为“等待单一事件完成

weixin_30596165的博客 295

深入理解 `rt_completion` —— 一次性同步机制的正确使用姿势

RT-Thread 系统中,是一种轻量级的线程同步机制,用于线程之间的一次性完成通知。很多开发者在刚接触它时,会误以为它与信号量rt_sem类似,可以重复使用、积累事件,这种误解往往导致程序出现“莫名其妙的死等”或“事件丢失”的问题。本文将结合一个形象的**“步枪上弹→瞄准射击”的类比,彻底讲清楚的使用场景、限制与正确姿势**。在我们的项目中,有同事曾尝试这样使用// 等待外设响应// 处理响应而另一个线程可能在某些情况下先于wait()调用了done()

enginexpert的博客 1324

Device IPC-2

pipe基于设备框架,基于ringbuffer实现?

qq_37932504的博客 1664

LDD3之并发和竞态-completion(完成量)的学习和验证

原文:http://blog.csdn.net/kangear/article/details/34898267 LDD3之并发和竞态-completion(完成量)的学习和验证 首先说下测试环境: Linux2.6.32.2 Mini2440开发板 一开始难以理解书上的书面语言,这里《linux中同步例子(完成量completion)》举了一个公交车上司机和乘客

alianqiugui的博客 674

complete完成量

通过完成量实现内核驱动开发工作,完成量底层分装了等待队列内容,实现了驱动多进程之间消息互通。实际在裸机驱动开发过程中,如果一个中断信号过来,我们通过将一个标识位置为来实现。

生活需要深度 758

Kernel module编程(十三):信号量、互斥锁、读写信号量和完成量

  本文也即《Linux Device Drivers》,LDD3的第五章Concurrency and Race Conditions的读书笔记之二,但我们不限于此内容。信号量(Semaphore)信号量和互斥锁  Kernel提供不同的原语来处理不同的情况,最常用的是采用信号量的方式。如果不能获得资源将进入sleep状态,等待资源释放,也即block的方式。通过

愷风(Wei)的专栏 8584

Linux设备驱动开发 - 内核线程和内核同步完成量completion示例

Linux设备驱动开发 - 内核线程和内核同步完成量completion示例

fulinux的博客 722

linux内核同步之信号量、顺序锁、RCU、完成量、关闭中断

一、信号量 1.信号量的概念 信号量也是一种锁,当信号量不可用时,尝试获取信号量的任务将挂起直到它拿到了信号量。由于尝试获取信号量的任务可能挂起,因而中断服务程序以及可延迟函数不能使用信号量。 对于信号量来说需要注意: 只有对信号量计数值的操作是原子的信号量的自旋锁只用于保护信号量的等待队列信号量是比较特殊的,其up操作不是必须由down操作的调用者发起。如果把信号量也看作

浩海拾贝 6543

Linux内核同步方法之完成量

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引入库 代码

lh0616的博客 1004

Rtthread学习笔记(二十二)RT-Thread内核-线程间同步

一、信号量 查看官方例程程序RT-线程间同步 1、信号量的使用场合 信号量是一种非常灵活的同步方式,可以运用在多种场合中。形成锁、同步、资源计数等关系,也能方便的用于线程与线程、中断与线程间的同步中。 (1)线程同步 线程同步是信号量最简单的一类应用。例如,使用信号量进行两个线程之间的同步,信号量的值初始化成 0,表示具备 0 个信号量资源实例;而尝试获得该信号量的线程,将直接在这个信号量上进行等待。 当持有信号量的线程完成它处理的工作时,释放这个信号量,可以把等待在这个信号量上的线程唤醒,让它执行下一部分

Davidysw的博客 1395

147 completion机制基本概念

文章目录一、总结完成量和(信号量&互斥量)的差异二、completion结构体三、初始化completion1、init_completion() 宏2、__init_completion()函数三、静态定义并初始化1、DECLARE_COMPLETIONCOMPLETION_INITIALIZER宏四、completion休眠1、wait_for_completion()函数2、wait_for_completion_timeout()函数3、wait_for_completion_interr

engineer0的博客 1671

内核的并发和竞态(信号量、completion、自旋锁)

1、并发和并行 (1)并行:在同一时刻有多个线程一起运行; (2)并发:在同一时刻只有一个线程在运行,但是在一个时间段内有多个线程运行; 总结:并发是宏观的并行。因为CPU运行特别快,虽然CPU不断在切换运行的线程,但是对于人来说,根本感知不到CPU的切换过程,就好像荧光灯在不停的闪烁, 但是频率只要够快,人们就感觉不到在闪烁。 2、并发产生的原因 (1)正在运行的多个用户进程以无法预知的方式访问驱动程序代码 (2)外部设备的中断异步的发生,导致正在运行的进程或者驱动代码被中断 (3)linux的软件

weixin_42031299的博客 792

互斥与同步之完成量

参考资料 《深入Linux设备驱动程序内核机制》 参考资料《Linux Device Driver 3rd Edition》 参考资料《Linux设备驱动开发详解4.0内核》 参考资料《Documentation\scheduler\completion.txt》 1. 完成量概述 1.1 完成量与等待队列的关系 完成量completion是基于等待队列实现的内核同步机制 1.2 什么是完成量 完成量用于一个执行单元等待另一个执行单元执行完成某事,该机制用来在多个执行路径之间作同步使

liaojunwu的博客 565
上一篇: 【再见,2020】这一年我与RT-Thread的故事征集
下一篇: 【20210122期AI简报】保姆级深度学习环境配置指南、寒武纪首颗AI训练芯片亮相...
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值