CosyOS-II “中断挂起服务缓存” 为何必须先入先出?
本帖最后由 CosyOS 于 2023-10-24 01:13 编辑“中断挂起服务”是 CosyOS 实现“零中断延迟”这一目标的关键技术之一,今天论证一下:
CosyOS-II 中的“中断挂起服务缓存”为何必须先入先出?
传统RTOS在中断中调用服务时,通常是先要关中断,而后执行服务,然后再开中断,以保证服务的“执行流”不会被打断。
CosyOS 为了实现零中断延迟,采用了中断挂起服务的方案。
所谓中断挂起服务,是指在中断中调用的服务不在本地直接执行,而是把服务的相关信息存入局部的结构体中,再把
结构体指针存入中断挂起服务缓存,再触发PendSV,而后在PendSV中执行。PendSV是最低优先级中断,位于 CosyOS
实时运行模型 中的服务层,所有服务(中断本地服务除外)均在本层执行,从而保证服务的“操作流”不会被打断。
通常在中断中既有用户自己的代码又有服务调用,而中断又是高优先级抢占的,所以当多个中断并发时,服务的调用顺序
不一定是中断的发生顺序或响应顺序,具有一定的随机性。从这个角度来说,
CosyOS 的中断挂起服务,没有必要先入先出,顺序可以随意打乱,只要最后能够一个不落的执行完成所有服务即可。
事实真的是这样吗?让我们来看下面这种情况。
当多个中断并发时,由于PendSV优先级最低,导致PendSV迟迟未能进入(服务未执行)。此时,某个中断已经二次或多次进入,
而每次进入时调用的服务又都是反操作。
例如某个中断第一次进入时调用的服务是iSuspendTask(task_a),第二次进入时调用的服务是iResumeTask(task_a):
(1)如果是传统RTOS,当然是先执行iSuspendTask(task_a),后执行iResumeTask(task_a),最终结果是task_a被恢复运行,符合用户的预期。
(2)换做是CosyOS,如果中断挂起服务缓存是先入先出FIFO,则先执行iSuspendTask(task_a),后执行iResumeTask(task_a),符合用户的预期。
如果是后入先出LIFO,则最终结果是task_a被挂起,与用户的初衷相违背。
通过以上分析可知,
对于零中断延迟的RTOS(CosyOS)来说,中断挂起服务缓存必须先入先出FIFO,才会完全符合用户的预期,否则可能会导致错误的结果。
CosyOS-I 在这方面是有缺陷的,Arm为LIFO,51/251为按序查询。
CosyOS-II 已实现所有内核(Arm、51/251)中断挂起服务缓存均为先入先出FIFO,从此再无遗憾。
CosyOS-II 源码中,“中断挂起服务缓存”在 mcucfg文件 中定义,并命名为 “mPendSV_FIFO”。
另外再补充说明一点,中断挂起服务缓存要想实现先入先出FIFO,并非是一件容易的事情,原因是整个“入”和“出”的过程(操作流),
必须是原子操作,不能被打断。那 CosyOS-II 又是如何实现这一过程的呢?有兴趣的朋友可自行阅读源码,一探究竟。
页:
[1]