rt-thread心法系列(一)那些你必须知道的几类 api

网友投稿 499 2022-10-23

rt-thread心法系列(一)那些你必须知道的几类 api

前言

禁止在中断调用的 api 列表

内存堆操作类

rt_system_heap_initrt_mallocrt_reallocrt_free

内存池类

内核对象类

rt_object_allocatert_object_find

idle 线程

rt_defunct_execute

ipc 同步和消息机制类

rt_sem_creatert_sem_deletert_mutex_creatert_mutex_trytakert_mutex_deletert_event_creatert_event_deletert_mb_creatert_mb_deletert_mq_creatert_mq_delete

完成量

队列类

rt_wqueue_waitrt_data_queue_pushrt_data_queue_pop

延时

注:源码中摘录,并无理论考证,更无实际验证

所有被禁止在中断中调用的函数都有个相似的特征 —— 它可能是阻塞的,导致中断无法短时间内返回;或者它想调用可能发生阻塞的 api 。 任何引用了他们的函数也被带跑了,不能在中断中使用。

RT_DEBUG_NOT_IN_INTERRUPT 调试宏定义

#define RT_DEBUG_NOT_IN_INTERRUPT \do \{ \ rt_base_t level; \ level = rt_hw_interrupt_disable(); \ if (rt_interrupt_get_nest() != 0) \ { \ rt_kprintf("Function[%s] shall not be used in ISR\n", __FUNCTION__); \ RT_ASSERT(0) \ } \ rt_hw_interrupt_enable(level); \} \while (0)

当你在源码里看见某个函数体中有一行

引用 RT_DEBUG_NOT_IN_INTERRUPT 调试宏的几点问题

1. rt-thread 中有多处引用了这个宏,上面函数列表里绝大部分有; 2. 有一些没有,比如 memheap.c 文件中的 `rt_memheap_alloc` `rt_memheap_realloc` 等操作。 3. 仔细查看引用了 `RT_DEBUG_NOT_IN_INTERRUPT` 的所有函数,有部分使用宏的地方真让人揪心,以 `rt_defunct_execute` 函数为例:

static void rt_defunct_execute(void) { // Loop until there is no dead thread. // So one call to rt_defunct_execute // will do all the cleanups. */ while (1) { register rt_base_t level; rt_thread_t thread; void (*cleanup)(struct rt_thread *tid);#ifdef RT_USING_MODULE struct rt_dlmodule *module = RT_NULL;#endif RT_DEBUG_NOT_IN_INTERRUPT; // <<--

为什么放 while 里?不是 while 之前?不应该放到函数开头醒目的地方吗?有人反驳了啊,放哪儿不一样,放哪也是一行代码的事儿!RT_DEBUG_IN_THREAD_CONTEXT 也有用样的使用不当,放到某个判断内部,而不是函数开头就引用。 4. 那么我还有个疑问:这是 idle 线程的内部调用的局部函数,会被中断调用了?!谁有权限在中断里引用它?!**`rt_defunct_execute` 函数应该从上面的列表里删除掉**,这个笔者已经在 github 上 pr 修改过了

必须在线程上下文调用的 api 列表

信号

rt_signal_wait

ipc 同步和消息机制

rt_sem_takert_mutex_takert_mutex_releasert_event_recvrt_mb_send_waitrt_mb_recvrt_mq_send_waitrt_mq_recv

线程操作类

rt_thread_detachrt_thread_deletert_thread_yieldrt_thread_delayrt_thread_delay_untilrt_thread_mdelayrt_thread_suspendrt_thread_resume

其它

rt_tick_getrt_enter_criticalrt_exit_critical

RT_DEBUG_IN_THREAD_CONTEXT 调试宏定义

首先,贴出来它的定义

#define RT_DEBUG_IN_THREAD_CONTEXT \ RT_DEBUG_NOT_IN_INTERRUPT; \do \{ \ rt_base_t level; \ level = rt_hw_interrupt_disable(); \ if (rt_thread_self() == RT_NULL) \ { \ rt_kprintf("Function[%s] shall not be used before scheduler start\n", \ __FUNCTION__); \ RT_ASSERT(0) \ } \ rt_hw_interrupt_enable(level); \} \while (0)#else#define RT_DEBUG_NOT_IN_INTERRUPT#define RT_DEBUG_IN_THREAD_CONTEXT#endif

注:此定义代码略有改动。

在线程上下文调用的函数有两个特征: 1. 不能在中断中调用。 2. 不能在任务调度器启动前调用,必须线程启动后,被线程入口函数调用。

因此,函数体中添加了此宏引用的函数,也不能在中断响应过程中被调用。

鉴于此,本篇开头的***“禁止在中断调用的 api 列表” 需要进行扩充,添加上 “必须在线程上下文调用的 api 列表” 中的所有 api***。

不能用在线程自己身上的 api

首先,这类 api 有个特征,那就是形参有个 rt_thread_t 类型参数。

rt_thread_detachrt_thread_delete

这俩不多说,一个针对静态线程对象,一个针对动态线程对象。作用均是退出线程、清理线程。当前线程退出可以直接从 while 循环里跳出来,从线程入口函数 return 就可以。

`rt_thread_startup` 当一个线程正在运行的时候,它自己再 startup 自己是不是就很诡异了。

`rt_thread_resume` 线程挂起由得自己,唤醒就由不得自己了。

特别的,目前 rt-thread 只支持当前线程自己主动 suspend ,然后等待中断或者其它线程 resume 它。而且,仅限于定时、线程间同步和通信机制里使用。不支持 A 线程 suspend B 线程,然后某个时机再 resume B。不支持 `rt_thread_suspend` `rt_thread_resume` 直接调用。 虽然 `rt_thread_detach` `rt_thread_delete` 用来退出线程,但是,不了解线程运行机制,千万别随意使用这俩函数退出其它线程。如果有需要,使用消息机制让现在自己跳出线程入口函数的 while 循环,自己从线程入口函数返回,这样更安全可靠。

结束

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:JdbcTemplate操作数据库的具体方法
下一篇:K8S核心技术PV和PVC状态的变化#yyds干货盘点#
相关文章

 发表评论

暂时没有评论,来抢沙发吧~