rCore第五章实验练习

stride调度算法实现

简述

  • TaskControlBlockInner中加入 stridepriority两个字段,这里我选择的类型是usize
  • 接下来将 TaskManager中的任务队列更换为BinaryHeap类型 (官方文档)。
  • 为了能进行比较,还需要为TaskControlBlock实现Ord trait (官方文档)
  • 最后,修改 task/processor.rs 中的run_tasks()函数,使其在调度任务时,计算pass并增加对应task的stride

实现

// os/src/task/task.rs
use core::cmp::Ordering;

impl Ord for TaskControlBlock {
    fn cmp(&self, other: &Self) -> Ordering {
        let self_stride = self.inner_exclusive_access().get_stride() as isize;
        let other_stride = other.inner_exclusive_access().get_stride() as isize;
        // Min heap need reverse sub
        let cmp_res = other_stride.wrapping_sub(self_stride);

        // use isize to process stride overflow
        if cmp_res < 0 {
            Ordering::Less
        } else if cmp_res > 0 {
            Ordering::Greater
        } else {
            Ordering::Equal
        }
    }
}

impl PartialOrd for TaskControlBlock {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Eq for TaskControlBlock {}

impl PartialEq for TaskControlBlock {
    fn eq(&self, other: &Self) -> bool {
        let self_stride = self.inner_exclusive_access().get_stride();
        let other_stride = other.inner_exclusive_access().get_stride();

        self_stride == other_stride
    }
}

这里需要注意两点:

  1. 考虑到stride溢出问题(需要一定计组知识),需要将无符号数转为有符号数后再进行判断,详细分析见 uCore stride算法

这里将实验书中u8的例子解释下 , i8取值范围为 [ − 128 , 127 ] \left [-128, 127 \right ] [128,127]
u8 → \to i8
125(0x7D) → \to 125 (0x7D)
255 (0xFF) → \to -1 (0xFF 补码表示) (0x81 原码表示)
于是125 - 255 → \to 125 - (-1) = 126 > 0
所以 (125 < 255) == false

129 (0x81) → \to -127 ((0x81 补码表示) (0xFF 原码表示)
255 (0xFF) → \to -1 (0xFF 补码表示) (0x81 原码表示)
于是129 - 255 → \to -127 - (-1) = -126 < 0
所以 (129 < 255) == true

再用下面这张图解释一下,u8i8的转换就是这样一个映射关系
无符号数 [ 0 , 127 ] \left [0, 127 \right ] [0,127] 对应有符号数 [ 0 , 127 ] \left [0, 127 \right ] [0,127]
无符号数 [ 128 , 255 ] \left [128, 255 \right ] [128,255] 对应有符号数 [ − 128 , − 1 ] \left [-128, -1 \right ] [128,1]

当两个stride分别处于不同颜色区域时,在蓝色部分的数就是发生溢出的,真实stride比处在橙色部分要大;通过有符号数的转换,两个数大小关系恢复到真实值(即u8蓝色溢出要比橙色大)
在这里插入图片描述

  1. 由于BinaryHeap默认为大根堆,cmp函数需要用 other 减去 self来实现小根堆。使用wrapping_sub也是为了防止溢出

pub const BIG_STRIDE: usize = usize::MAX >> 1;

// os/src/task/processor.rs
pub fn run_tasks() {
    loop {
        let mut processor = PROCESSOR.exclusive_access();
        if let Some(task) = fetch_task() {
            let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
            // access coming task TCB exclusively
            let mut task_inner = task.inner_exclusive_access();
            let next_task_cx_ptr = &task_inner.task_cx as *const TaskContext;
            task_inner.task_status = TaskStatus::Running;
            
            let pass = BIG_STRIDE / task_inner.get_priority();
            let task_stride = task_inner.get_stride();
            task_inner.stride = task_stride.wrapping_add(pass);
            drop(task_inner);
            // release coming task TCB manually
            processor.current = Some(task);
            // release processor manually
            drop(processor);
            unsafe {
                __switch(idle_task_cx_ptr, next_task_cx_ptr);
            }
        }
    }
}

由于要求priority >= 2,所以pass = BIG_STRIDE / priority <= usize::MAX / 2 ,所以将BIG_STRIDE设置为该值


实验结果

在这里插入图片描述
Max raito / Min raito = 2_387_666 / 2_315_200 = 1.03 < 1.5 通过测试

总结

实验主要难点在于stride溢出问题,我解释了下u8的例子并用一张图说明了无符号数到有符号数的转换,希望有助于大家理解

  • 13
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值