首页 > 其他分享 >【WALT】WALT入口 update_task_ravg() 代码详解

【WALT】WALT入口 update_task_ravg() 代码详解

时间:2023-07-01 23:55:37浏览次数:55  
标签:task rq update WALT 任务 demand

目录

【WALT】WALT入口 update_task_ravg() 代码详解

代码版本:Linux4.9 android-msm-crosshatch-4.9-android12

代码展示

void update_task_ravg(struct task_struct *p, struct rq *rq, int event,
						u64 wallclock, u64 irqtime)	{
	u64 old_window_start;
	
	// ⑴ 判断是否进入 WALT 算法
	if (!rq->window_start || sched_disable_window_stats ||
	    p->ravg.mark_start == wallclock)
		return;

	lockdep_assert_held(&rq->lock);

	// ⑵ 获取 WALT 算法中上一个窗口的开始时间
	old_window_start = update_window_start(rq, wallclock, event);

	// ⑶ 如果任务刚初始化结束,不进入 WALT 算法,进入 `done`
	if (!p->ravg.mark_start) {
		update_task_cpu_cycles(p, cpu_of(rq), wallclock);
		goto done;
	}

	// ⑷ 更新任务及 CPU 的 cycles
	update_task_rq_cpu_cycles(p, rq, event, wallclock, irqtime);
	// ⑸ 更新任务及 CPU 的 demand 及 pred_demand
	update_task_demand(p, rq, event, wallclock);
	// ⑹ 更新 CPU 的 busy time
	update_cpu_busy_time(p, rq, event, wallclock, irqtime);
	// ⑺ 更新任务的 pred_demand
	update_task_pred_demand(rq, p, event);

	// ⑻ 如果任务正在退出,进入 `done`
	if (exiting_task(p))
		goto done;

	// 两个系统自带的 tracepoint
	trace_sched_update_task_ravg(p, rq, event, wallclock, irqtime,
				rq->cc.cycles, rq->cc.time, &rq->grp_time);
	trace_sched_update_task_ravg_mini(p, rq, event, wallclock, irqtime,
				rq->cc.cycles, rq->cc.time, &rq->grp_time);

done:
	p->ravg.mark_start = wallclock;
	run_walt_irq_work(old_window_start, rq);
}

代码逻辑

WALT 算法以任务为主,当任务被唤醒、任务开始执行、任务停止执行、任务退出、窗口滚动、频率变化、任务迁移、经过一个调度tick、在中断结束时会调用update_task_ravg()

其中,窗口是 WALT 算法中的一个特殊的设定,将在 update_task_demand()update_cpu_busy_time() 中详细解释。

⑴ 判断是否进入 WALT 算法

在进入 WALT 算法后首先会判断当前任务所在的运行队列(runqueue)是否进行初始化,以及是否禁用 CPU 的窗口统计:if(!rq->window_start || sched_disable_window_stats...)。如果没有初始化,就不会记录窗口的开始时间,任务负载就无法进行计算。有几点需要注意:

  1. 该处是指 rq,而非 cfs->rq 或 rt->rq,即该处不区分实时任务或普通任务;
  2. 任务/CPU 窗口(sched_ravg_window)是自定义的,不同版本代码或不同设备中设置的窗口大小是不一样的,调整的位置也不尽相同。

然后会判断窗口开始时间是否更新:if(...p->ravg.mark_start == wallclock)。如果运行队列没有初始化,或禁用了 CPU 的窗口统计,或窗口开始时间没有更新,就会直接结束 WALT 算法。

⑵ 获取 WALT 算法中上一个窗口的开始时间

然后通过函数update_window_start()获取上一个窗口的开始时间,存在变量old_window_start中。

点击此处查看 update_window_start() 代码详解。

⑶ 如果任务刚初始化结束

如果任务刚初始化结束:if(!p->ravg.mark_start),还没有标记过任务的开始时间,就先通过函数 update_task_cpu_cycles() 更新一下该任务的 cycles 值(p->cpu_cycles),然后进入 done

点击此处查看 update_task_cpu_cycles() 代码详解。

⑷ 更新任务及 CPU 的 cycles

update_task_cpu_cycles() 相似,但比其多更新了 CPU 的 cycles 值(rq->cc.cycles)。

点击此处查看 update_task_rq_cpu_cycles() 代码详解。

⑸ 更新任务及 CPU 的 demand 及 pred_demand

在任务满足条件后,在不同情况下根据任务的开始时间、窗口的开始时间以及当前时间来计算任务在当前及之前M个窗口中的运行时间。在窗口结束时将运行时间进行归一化,并统计进任务的历史窗口中(sum_history[RAVG_HIST_SIZE])。

WALT 算法根据历史窗口中的值计算任务的 demand,根据桶算法计算任务的 pred_demand,并将 demand 与 pred_demand 统计进任务所在 CPU 的 rq(runqueue)中。

注意:以上说的 demand 与 pred_demand 都是预测值。

点击此处查看 update_task_demand() 代码详解。

⑹ 更新 CPU 的 busy time

在任务满足条件后,在不同情况下根据任务的开始时间、窗口的开始时间以及当前时间来计算任务在当前及上一个窗口中的运行时间,将不同窗口内的运行时间进行归一化,并根据任务的状态统计进任务的 curr_windowprev_window 中,以及任务所在 rq 的 curr_runnable_sumprev_runnable_sum 中。

在窗口翻滚的时候更新任务的 window 值 以及 rq 的 runnable_sum 的值。

注意:以上说的 window 以及 runnable_sum 都是真实值。

点击此处查看 update_cpu_busy_time() 代码详解。

⑺ 更新任务的 pred_demand

如果符合条件的任务在当前窗口中预测出来的 demand 值小于 curr_window,则再次使用桶算法计算 pred_demand。

点击此处查看 update_task_pred_demand() 代码详解。

⑻ 如果任务正在退出

#define EXITING_TASK_MARKER	0xdeaddead

static inline int exiting_task(struct task_struct *p)
{
	return (p->ravg.sum_history[0] == EXITING_TASK_MARKER);
}

当任务最近一个窗口的值为 0xdeaddead 时,意味着任务正在退出,进入 done

done 结束部分:

  1. 更新一下任务的开始时间:p->ravg.mark_start = wallclock
  2. 通过函数 irq_work_queue() 处理没有 tick 的情况,循环调用 update_task_ravg()

标签:task,rq,update,WALT,任务,demand
From: https://www.cnblogs.com/cyrusandy/p/17520192.html

相关文章

  • 【WALT】update_window_start() 代码详解
    目录【WALT】update_window_start()代码详解代码展示代码逻辑【WALT】update_window_start()代码详解代码版本:Linux4.9android-msm-crosshatch-4.9-android12代码展示staticu64update_window_start(structrq*rq,u64wallclock,intevent){ s64delta; intnr_window......
  • celery笔记九之task运行结果查看
    本文首发于公众号:Hunter后端原文链接:celery笔记九之task运行结果查看这一篇笔记介绍一下celery的task运行之后结果的查看。前面我们使用的配置是这样的:#settings.pyCELERY_RESULT_BACKEND="redis://localhost/1"是将task的运行结果保存在redis的第二个数据......
  • c# Thread.Sleep 与 Task.Delay 在多线程中的影响
    一般在函数执行的时候,如果需要让一个任务等待一会儿在执行,大部分都是采用的Thread.Sleep()语句。但如果该函数要复用,同时要给函数一个参数,并让该函数被线程调用后并发执行。当采用如下调用方式的时候,就会出现什么情况呢?就会出现线程阻塞,你会发现只有task1执行,也即只有一个线程......
  • Windows Server 2022 中文版、英文版下载 (updated Jun 2023)
    WindowsServer2022中文版、英文版下载(updatedJun2023)WindowsServer2022正式版,2023年6月更新请访问原文链接:https://sysin.org/blog/windows-server-2022/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org早期直观体验版本21H2,根据名称预计今年秋季......
  • Windows 10, version 22H2 (updated Jun 2023) 中文版、英文版下载
    Windows10,version22H2(updatedJun2023)中文版、英文版下载Windows1022H2企业版arm64x64请访问原文链接:https://sysin.org/blog/windows-10/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgWindows10更新历史记录Windows10,version22H2,alledit......
  • Windows 11 22H2 中文版、英文版 (x64、ARM64) 下载 (updated Jun 2023)
    Windows1122H2中文版、英文版(x64、ARM64)下载(updatedJun2023)Windows11,version22H2,2023年6月更新请访问原文链接:https://sysin.org/blog/windows-11/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org全新推出Windows11全新Windows体验,让您与热......
  • Freertos学习05-Task状态打印
    一、前言TaskList()是FreeRTOS中的一个函数,它可以列出所有当前正在运行的任务。这个函数可以用于调试和监视系统中的任务。它返回一个指向任务列表的指针,其中包含每个任务的名称、状态、优先级和堆栈使用情况等信息。二、函数介绍该函数的输入参数为数据缓存区的地址,可......
  • Freertos学习03-Task状态
    一、前言FreeRTOS是一个流行的实时操作系统,它支持多任务处理。在FreeRTOS中,任务有不同的状态,这些状态反映了任务在系统中的行为。二、状态特点任务可以存在于以下状态中:运行当任务实际执行时,它被称为处于运行状态。任务当前正在使用处理器。如果运行RTOS的处理器只......
  • 线程上运行 task
    我没能实现始终在一个线程上运行task 前文我们总结了在使用常驻任务实现常驻线程时,应该注意的事项。但是我们最终没有提到如何在处理对于带有异步代码的办法。本篇将接受笔者对于该内容的总结。如何识别当前代码跑在什么线程上一切开始之前,我们先来使用一种简单的方式来识......
  • Freertos学习03-Task优先级
    一、前言FreeRTOS是一个流行的实时操作系统,它允许用户创建多个任务并在它们之间共享处理器时间。在FreeRTOS中,任务的优先级别是非常重要的,因为它决定了任务在系统中的执行顺序。二、任务优先级特点FreeRTOS中的任务优先级别是一个整数,范围从0到configMAX_PRIORITIES-1,其......