前言
多任务系统,线程和中断是两个竞争关系的各自独立的实体。很多 api 是禁止在中断中调用的。
和线程运行息息相关的函数,要求必须在任务调度运行起来以后才能使用。
以及,一些 api 被设计出来是用来在某线程操作另外一个线程,是不可以某线程针对自己使用的。
今天就说说哪些 api 禁止在中断中调用、哪些必须在任务调度器运行以后才能使用、哪些不能线程用在自己身上。
禁止在中断调用的 api 列表
所有被禁止在中断中调用的函数都有个相似的特征 —— 它可能是阻塞的,导致中断无法短时间内返回;或者它想调用可能发生阻塞的 api 。
任何引用了他们的函数也被带跑了,不能在中断中使用。
RT_DEBUG_NOT_IN_INTERRUPT 调试宏定义
rt-thread 定义了一个宏,当我们开启调试的时候,它可以帮我检查当前函数是否被中断调用了。其实现如下:
#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 ISRn", __FUNCTION__);
RT_ASSERT(0)
}
rt_hw_interrupt_enable(level);
}
while (0)
当你在源码里看见某个函数体中有一行
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 也有用样的使用不当,放到某个判断内部,而不是函数开头就引用。
那么我还有个疑问:这是 idle 线程的内部调用的局部函数,会被中断调用了?!谁有权限在中断里引用它?!rt_defunct_execute 函数应该从上面的列表里删除掉,这个笔者已经在 github 上 pr 修改过了
必须在线程上下文调用的 api 列表