当前位置: 首页 > news >正文

Linux psi_task_change任务状态切换PSI计算

Linux psi_task_change任务状态切换PSI计算

psi_task_change是PSI(Pressure Stall Information)子系统的核心函数,负责在任务状态发生切换时更新per-CPU的stall追踪状态。任务状态的变化直接决定了cgroup当前是否处于IO、内存或CPU资源压力的stall状态,以及stall的严重程度(some vs full)。

函数核心逻辑

psi_task_change接收当前任务、新旧任务状态flags以及是否睡眠等参数,根据这些信息判断stall状态是否发生变化,并更新per-CPU的统计累积时间。

```c
void psi_task_change(struct task_struct *task, int clear, int set)
{
struct psi_group *group;
int cpu = task_cpu(task);
struct psi_group_cpu *groupc;
u64 now;
int state_mask;

if (!task->pid)
return;

group = task_psi_group(task);
if (!group)
return;

now = cpu_clock(cpu);
groupc = per_cpu_ptr(group->pcpu, cpu);

raw_spin_lock(&groupc->lock);

/*
* 计算新状态掩码,先清除旧flags再设置新flags,
* 排除TASK_NONIDLE等非PSI状态位
*/
state_mask = (groupc->state_mask & ~clear) | set;
state_mask &= PSI_TASK_STATE_MASK;

if (state_mask != groupc->state_mask) {
u64 delta;

/*
* 计算从上次状态改变到现在的stall持续时间,
* 累加到对应状态的times数组中
*/
delta = now - groupc->state_start;
if (delta > 0) {
int s;

for (s = 0; s < NR_PSI_STATES; s++) {
if (groupc->state_mask & (1 << s))
groupc->times[s][groupc->state_mask] += delta;
}
}

groupc->state_mask = state_mask;
groupc->state_start = now;

/*
* 如果新状态包含非空闲标志,需要设置
* nonidle_start时间戳,用于非idle时间跟踪
*/
if (state_mask & TASK_NONIDLE) {
if (!groupc->nonidle_start)
groupc->nonidle_start = now;
} else {
if (groupc->nonidle_start) {
delta = now - groupc->nonidle_start;
groupc->nonidle_time += delta;
groupc->nonidle_start = 0;
}
}
}

raw_spin_unlock(&groupc->lock);

/*
* 如果状态变化涉及可运行状态(running/runnable)的切换,
* 需要通知调度器更新psi_sched统计
*/
if (task->psi_flags & TSK_RUNNING) {
if (!(set & TSK_RUNNING)) {
psi_sched_account(task, true);
}
}
}
```

PSI状态的分类体系

PSI定义了三种资源类型(IO、Memory、CPU)和两种stall严重程度(Some、Full)。Some表示至少有一个任务处于stall状态但非全部,Full表示所有非idle任务都处于stall状态。

```c
enum psi_states {
PSI_IO_SOME,
PSI_IO_FULL,
PSI_MEM_SOME,
PSI_MEM_FULL,
PSI_CPU_SOME,
PSI_CPU_FULL,
NR_PSI_STATES,
};
```

psi_task_switch调度器入口

调度器在进程切换时调用psi_task_switch,该函数包装了psi_task_change并提供额外的上下文信息,是调度器与PSI子系统的主要接口。

```c
void psi_task_switch(struct task_struct *prev, struct task_struct *next,
bool sleep)
{
struct psi_group *group, *prev_group;

if (!static_branch_likely(&psi_disabled))
return;

if (prev->pid) {
prev_group = task_psi_group(prev);
if (prev->state == TASK_RUNNING) {
psi_task_change(prev, TSK_RUNNING, 0);
} else if (sleep) {
/*
* 任务进入睡眠状态,设置TSK_SLEEP标志,
* 此时该任务不再贡献活跃度
*/
psi_task_change(prev, TSK_RUNNING, TSK_SLEEP);
if (prev->in_iowait)
psi_task_change(prev, 0, TSK_IOWAIT);
}
}

if (next->pid) {
group = task_psi_group(next);
if (next->state == TASK_RUNNING) {
psi_task_change(next, 0, TSK_RUNNING);
}
}

/*
* 如果任务迁移到不同cgroup,需要同步
* per-CPU的psi_group_cpu统计
*/
if (prev_group != group && prev->pid && next->pid)
psi_group_change_sync(prev, prev_group, next, group, cpu);
}
```

memstall与iowait的处理

当任务因缺页等待IO时,内核标记PF_MEMSTALL标志。psi_memstall_enter和psi_memstall_leave通过psi_task_change切换TSK_MEMSTALL状态,使PSI能够追踪内存stall导致的任务等待。

```c
void psi_memstall_enter(unsigned long *flags)
{
struct task_struct *task = current;

if (!static_branch_likely(&psi_disabled))
return;

*flags = task->flags & PF_MEMSTALL;
task->flags |= PF_MEMSTALL;

if (!(*flags & PF_MEMSTALL))
psi_task_change(task, 0, TSK_MEMSTALL);
}

void psi_memstall_leave(unsigned long *flags)
{
struct task_struct *task = current;

if (!static_branch_likely(&psi_disabled))
return;

if (*flags & PF_MEMSTALL)
return;

task->flags &= ~PF_MEMSTALL;
psi_task_change(task, TSK_MEMSTALL, 0);
}
```

通过psi_task_change的精细状态追踪,PSI能够准确区分不同资源类型的stall,并为系统管理员提供精确的拥塞度量,这是cgroup v2资源隔离能力的关键组成部分。

http://www.gsyq.cn/news/1573081.html

相关文章:

  • 南京视频号代运营服务机构综合实力排行 - 起跑123
  • 2026 郑州管道疏通 + 水电综合避坑汇!马桶 / 下水道 / 暗漏真实测评榜单 - 星际AI
  • DeepSeek V4 Pro降价背后的混部池技术真相
  • 医学影像AI新突破:SGMRI-VQA如何实现动态MRI的时空推理与视觉问答
  • 双层平面腔磁子-极化子激发研究与应用
  • 2026年6月最新宝珀中国官方售后客服服务热线电话地址网点 - 亨得利官方服务中心
  • AI Agent如何从一行while循环进化出五十万行自治代码
  • CircleCI + Argo CD 实现 Kubernetes GitOps 生产级交付
  • Hermes Agent RL训练流水线:让AI助手学会聪明调用工具
  • 电动车托运怎么最省钱?3招搞定 - 快递物流资讯
  • 面向国内开发者的AI服务协同工作流平台
  • 终极植物大战僵尸修改器指南:如何快速掌握PVZ Toolkit的完整功能
  • 2026年河南企业AI搜索推广怎么选?深蓝新媒与主流GEO服务商深度横评 - 优质企业观察收录
  • MC9RS08LA8 LCD驱动开发实战:从环境搭建到调试避坑
  • 南京正规视频号代运营服务机构综合排行梳理 - 起跑123
  • 5分钟快速上手IPXWrapper:让经典游戏在现代Windows上重获联机功能
  • 2026 青岛装修公司口碑盘点:靠谱家装品牌实力参考 - 装修新知
  • 2026年10款靠谱论文降AIGC工具亲测:规范定稿实战对比实用指南
  • 2026重庆钻石回收TOP7实测榜单|本地靠谱钻饰变现商家测评 - 名奢变现站
  • DeepSeek-R1在llama.cpp中的GPU加速真相与生产级调优
  • 终极指南:5分钟免费解锁英雄联盟国服全皮肤体验
  • Seedance 2.0不是独立产品,而是即梦平台的AI视频引擎
  • LangChain / LangGraph、MCP、Harness Engineer 与 Claude Code 的对应关系 - 若
  • FitGirl游戏启动器:3个技巧让你轻松管理游戏收藏
  • Mac NTFS读写终极指南:免费开源解决方案Nigate完整使用教程
  • 2026年天津西青区汽车购车与维保一站式服务深度选购指南 - 年度推荐企业名录
  • 2026广州企业搬迁优选指南|办公室/工厂/商铺搬迁,政企认可服务商汇总,适配写字楼工厂门店搬迁 - GrowthUME
  • 企业级Wi-Fi认证排障:EAP-TTLS与MSCHAPv2实战指南
  • 用Python+Droplet+cron自建Claude API中转系统
  • Nexus Mods App终极指南:轻松管理游戏模组的智能解决方案