引言
因为rcore
并非设计为一个rtos
,而是在我们需要的时候我们需要在设计的时候考虑到线程切换的时候的延时问题.
回顾上一部分的使用环形队列进行调度的方式,我们会发现我们寻找下一个Ready
的任务的时间是不均匀的.
并且我们的任务是没有优先级的,可以认为是平权的,因此,为了:
- 快速且时间均匀地找到下一个应该被调度的线程.
- 为不同任务之间实现优先级.
我添加了这个extend
部分,实现了一些rtos
的特性.
仅有32位优先级的抢占式调度
有点类似于哈希表的拉链法里的拉链数据结构了
在结构体里存一个带有优先级的变量u32
,每个位对应一个链表.用一个u32
来管理,为1,说明当前存在待调度的线程.
每次在线程ready
的时候把线程插入对应的队列里,并且把线程优先级|
到这个u32
.同理,删除这个线程的时候,也需要&~
线程优先级.
为什么要选择优先级数值越小优先级越高?
为了快速找出目前需要调度的队列,这种算法是存在的.
找目前优先级最高的需要调度的线程,其实就是找u32
最低位为1的数字.
使用位图寻找
空间换时间
首先我们先看上图中被虚线划开的第一部分,也就是前8
位.
前八位可以有两种观点看待:
- 看作是数值.
- 看作是一个
flag&mask
的每个位代表一个状态的结构.
上述两个信息第一个可以从直接读取来获取,第二个则可以通过位操作来获取,都是很快的.
但是为1的第一位这个信息我们是不知道的,因此我们需要为0~255
(0x00~0xff
)所有的值都匹配一个对应的首个1
的位置.
最终得到这样的一个位图(但是保存为一位数组,相当于逐行储存):
0是单独处理的.
在8
位的情况下,每个对应的是对应数值的一个为1
的bit
的位置(但是是从0开始计算的).原因是前8
位就使之+1
,那么9~16
位就可以+17
,以此类推.
为什么以前
8
位为例?
8
位是最小的可操作的变量单位- 更大的位数的都可以转变为一个前八位的问题.通过
&0xff
检查前8
位是否为空.
优先级拓展
这里反过来想,每次使用位图处理优先级的时候,都是1Byte
为单位处理的.
那么如果需要拓展优先级,则很容易得出结论:原方法是使用一个u32
作为4
个Byte
的容器,如果需要拓展优先级,则使用u8
的数组就可以很容易类比实现.