【CPU篇 01】上下文切换context switch

本文详细介绍了Linux系统中的上下文切换,包括自愿上下文切换(CSWCH)和非自愿上下文切换(NVCSWCH)的概念及区别。上下文切换涉及切换MM和CPU寄存器状态,通过`context_switch`函数实现,其中`switch_mm`和`switch_to`分别负责页表和寄存器的切换。过多的上下文切换可能导致系统性能下降,需要根据CSWCH和NVCSWCH的情况定位问题。文章还探讨了基础的指令、症状和不同情况下的上下文切换,如进程、线程、中断和系统调用,并提供了相关资料。
摘要由CSDN通过智能技术生成

文章结构

  • 概念
  • 指令
  • 症状
  • 资料

目录

  1. 上下文切换
    1. Linux context_switch注释
    2. context_switch的两种子状态:CSWCH和NVCSWCH
  2. 基础知识
    1. 指令
    2. 症状
    3. context_switch细分情况
      1. 进程
      2. 线程
      3. 中断
      4. 系统调用
    4. 资料

 

一、上下文切换

context switch:主要是切换mm(switch_mm函数)和cpu register state(switch_to函数,包括寄存器和堆栈)。

Linux context_switch函数的源码注释:context_switch - switch to the new MM and the new thread's register state.

  1. 源码地址:https://elixir.bootlin.com/linux/latest/source/kernel/sched/core.c#L3324
/*
 * context_switch - switch to the new MM and the new thread's register state.
 */
static __always_inline struct rq *
context_switch(struct rq *rq, struct task_struct *prev,
	       struct task_struct *next, struct rq_flags *rf)
{
	prepare_task_switch(rq, prev, next);

	/*
	 * For paravirt, this is coupled with an exit in switch_to to
	 * combine the page table reload and the switch backend into
	 * one hypercall.
	 */
	arch_start_context_switch(prev);

	/*
	 * kernel -> kernel   lazy + transfer active
	 *   user -> kernel   lazy + mmgrab() active
	 *
	 * kernel ->   user   switch + mmdrop() active
	 *   user ->   user   switch
	 */
	if (!next->mm) {                                // to kernel
		enter_lazy_tlb(prev->active_mm, next);

		next->active_mm = prev->active_mm;
		if (prev->mm)                           // from user
			mmgrab(prev->active_mm);
		else
			prev->active_mm = NULL;
	} else {                                        // to user
		membarrier_switch_mm(rq, prev->active_mm, next->mm);
		/*
		 * sys_membarrier() requires an smp_mb() between setting
		 * rq->curr / membarrier_switch_mm() and returning to userspace.
		 *
		 * The below provides this either through switch_mm(), or in
		 * case 'prev->active_mm == next->mm' through
		 * finish_task_switch()'s mmdrop().
		 */
		switch_mm_irqs_off(prev->active_mm, next->mm, next);

		if (!prev->mm) {                        // from kernel
			/* will mmdrop() in finish_task_switch(). */
			rq->prev_mm = prev->active_mm;
			prev->active_mm = NULL;
		}
	}

	rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);

	prepare_lock_switch(rq, next, rf);

	/* Here we just switch the register state and the stack. */
	switch_to(prev, next, prev);
	barrier();

	return finish_task_switch(prev);
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值