Linux 6.0.19自定义RSDL调度器resched_curr延迟调度问题求助
解决Linux 6.0.19 RSDL调度器配额耗尽后的调度延迟问题
核心问题分析
从日志和代码来看,延迟的根本原因是:
- 任务配额耗尽后,仅调用
resched_curr(rq)设置调度标志,但未将任务从**可运行队列(active)**中移除,导致调度器的pick_next_task_rsdl仍会重复选中该配额耗尽的任务。 - 每次时钟tick触发
task_tick_rsdl时,再次触发resched_curr,但调度器始终没有找到合适的下一个任务,直到后续某个tick才完成切换。
具体修复步骤
1. 修正配额耗尽后的任务队列处理
在task_tick_rsdl中,当检测到配额耗尽时,先将当前任务移出active队列(或标记为过期),再触发调度:
static void task_tick_rsdl(struct rq *rq, struct task_struct *curr, int queued) { struct sched_rsdl_entity *rsdl; struct rsdl_rq *rsdl_rq; int *queue_quota; trace_printk("task_tick_rsdl\n"); rsdl = &curr->rsdl; rsdl_rq = &rq->rsdl_rq; queue_quota = rsdl_rq->active->quota + rsdl_rq->curr_prio; update_curr(rsdl_rq); if (rsdl->quota && *queue_quota) { rsdl->quota--; *queue_quota = *queue_quota - 1; } printk("p = %d ; tq = %lld ; qq = %d; cur_prio = %d\n", curr->pid, rsdl->quota, *queue_quota, rsdl_rq->curr_prio); if (!(rsdl->quota > 0 && *queue_quota > 0)) { // 将当前任务从active队列移除,移至expire队列(根据RSDL双队列设计) dequeue_task_rsdl(rq, curr, DEQUEUE_SLEEP); // 若active队列空,切换active/expire队列并重置配额(按需实现) if (list_empty(&rsdl_rq->active->tasks)) { swap(rsdl_rq->active, rsdl_rq->expire); reset_queue_quota(rsdl_rq->active); // 需自行实现队列配额重置逻辑 } // 触发调度 resched_curr(rq); printk("need resched\n"); } }
2. 修复pick_next_task_rsdl的任务选择逻辑
确保调度器不会选中配额耗尽的任务,在选择下一个任务时增加配额检查:
struct task_struct *pick_next_task_rsdl(struct rq *rq) { struct rsdl_rq *rsdl_rq = &rq->rsdl_rq; struct sched_rsdl_entity *rsdl; struct task_struct *p; // 遍历active队列,筛选有有效配额的任务 list_for_each_entry(p, &rsdl_rq->active->tasks, rsdl.run_list) { rsdl = &p->rsdl; int *queue_quota = rsdl_rq->active->quota + rsdl_rq->curr_prio; if (rsdl->quota > 0 && *queue_quota > 0) { rq->curr_prio = rsdl->prio; // 更新当前队列优先级(按需调整) return p; } // 移除配额耗尽的任务到expire队列 dequeue_task_rsdl(rq, p, DEQUEUE_SLEEP); enqueue_task_rsdl(rq, p, ENQUEUE_WAKEUP); } // 切换空的active队列到expire队列 if (list_empty(&rsdl_rq->active->tasks)) { swap(rsdl_rq->active, rsdl_rq->expire); reset_queue_quota(rsdl_rq->active); } // 重新获取第一个有效任务 return list_first_entry_or_null(&rsdl_rq->active->tasks, struct task_struct, rsdl.run_list); }
3. 强制触发调度(可选)
若仍存在延迟,可在调用resched_curr后,根据上下文主动触发调度:
if (!(rsdl->quota > 0 && *queue_quota > 0)) { // ... 队列处理逻辑 ... resched_curr(rq); // 进程上下文且允许抢占时,立即触发调度 if (!in_interrupt() && !preempt_count()) { preempt_schedule(); } // 中断上下文时,发送调度IPI强制触发 else if (in_interrupt()) { sched_send_ipi_current(); } printk("need resched\n"); }
验证要点
- 检查日志,确认配额耗尽的任务不会再被
pick_next_task_rsdl选中。 - 确认
dequeue_task_rsdl和enqueue_task_rsdl正确维护队列结构,避免任务丢失或重复入队。
内容的提问来源于stack exchange,提问作者Abhishek Ghosh
相关产品推荐
相关产品推荐

