首页 > 其他分享 >中断上下文

中断上下文

时间:2024-04-19 15:03:41浏览次数:21  
标签:count 中断 计数 上下文 bits define

中断上下文

前言

中断处理过程中会禁止抢占,如果中断处理函数不能尽快执行完成就会影响系统的实时性,为此内核将中断的处理过程分为上半部(Top Half)和下半部(Bottom Half),将耗时操作推迟到下半部异步执行。

  • 中断上半部:在上半部中执行一些能够快速完成的动作,比如响应外设请求。
  • 中断下半部:在下半部中执行一些耗时的动作,比如网络协议栈解析

因此在内核中CPU就有可能处于三种上下文:

  • 硬中断上下文:CPU在执行中断上半部时处于硬中断上下文,在较新的内核中断设计中,硬中断上下文会禁用中断,因此不会产生中断嵌套,只有等待当前中断上半部执行结束后才能响应下一个中断。
  • 软中断上下文:CPU在执行中断下半部时处于软中断上下文,在软中断上下文中可以被中断抢占,但是在CPU上软中断不允许嵌套,如果在执行中断下半部时发生中断,在处理完新的中断上半部之后不会进入新的软中断上下文。
  • 进程上下文:CPU在执行进程代码时处于进程上下文

内核使用了一个per-pcu的变量preempt_count来区分这些上下文,同时管理中断嵌套、抢占行为。

preempt_count

preempt_count是一个32 bits的整数,32 bits被划分为如下五个部分:

  • bits[0,8): preempt disable count抢占禁用计数占8 bits,执行preempt_disable()会对抢占禁用计数加一,preempt_disable()preempt_enable()必须要成对使用。当抢占禁用计数不为0时禁用抢占,此时不会发生调度,内核可以支持255层的抢占禁用嵌套。
  • bit 8: softirq count软中断计数,当softirq count不为0时表示软中断正在执行,由于不会出现软中断嵌套因此只需要一个bit表示。
  • bits[9,16): bottom half disable count中断下半部禁用计数,进程有时会有同步需要,此时不允许被软中断抢占,local_bh_disable()将计数加一,local_bh_disable()local_bh_enable()需要成对使用。可以支持127层中断下半部禁用嵌套。
  • bits[16,20): hardirq count硬中断计数占用4 bits,当硬中断计数不为0时表示硬中断正在执行,之前提到过内核不会出现硬中断嵌套,理论上只用一个bit就足够了,但是为了兼容一些有古董驱动(极少数情况),这些驱动可能在中断处理过程中打开中断,发生中断嵌套。内核能够支持最多15层硬中断嵌套,用于处理这些过时驱动。
  • bits[20,24): NMI count不可屏蔽中断计数占用4 bits。处理NMI中断时需要将硬中断计数和NMI中断计数都加一。
  • bits[24,31): 未使用
  • bit 31: PREEMPT_NEED_RESCHED用于表明内核有更高优先级的任务需要被调度,当抢占禁用计数不为0时才会设置,但是我看这个bit在调度中并没有发挥实际作用,内核中有对这个bit设置和清楚,但是在调度决策过程中并没有读取这个bit值。
/*
 *         PREEMPT_MASK:	0x000000ff
 *         SOFTIRQ_MASK:	0x0000ff00
 *         HARDIRQ_MASK:	0x000f0000
 *             NMI_MASK:	0x00f00000
 * PREEMPT_NEED_RESCHED:	0x80000000
 */

// bits number
#define PREEMPT_BITS	8
#define SOFTIRQ_BITS	8
#define HARDIRQ_BITS	4
#define NMI_BITS	4

// field shift
#define PREEMPT_SHIFT	0
#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
#define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
#define NMI_SHIFT	(HARDIRQ_SHIFT + HARDIRQ_BITS)

// field mask
#define __IRQ_MASK(x)	((1UL << (x))-1)
#define PREEMPT_MASK	(__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
#define SOFTIRQ_MASK	(__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
#define HARDIRQ_MASK	(__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define NMI_MASK	(__IRQ_MASK(NMI_BITS)     << NMI_SHIFT)

// field offset
#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
#define NMI_OFFSET	(1UL << NMI_SHIFT)

// irq count
#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK \
				 | NMI_MASK))

/* 
 * in_irq()       - We're in (hard) IRQ context
 * in_softirq()   - We have BH disabled, or are processing softirqs
 * in_interrupt() - We're in NMI,IRQ,SoftIRQ context or have BH disabled
 * in_serving_softirq() - We're in softirq context
 * in_nmi()       - We're in NMI context
 * in_task()	  - We're in task context
 */
#define in_irq()		(hardirq_count())
#define in_softirq()		(softirq_count())
#define in_interrupt()		(irq_count())
#define in_serving_softirq()	(softirq_count() & SOFTIRQ_OFFSET)
#define in_nmi()		(preempt_count() & NMI_MASK)
#define in_task()		(!(preempt_count() & \
				   (NMI_MASK | HARDIRQ_MASK | SOFTIRQ_OFFSET)))

通过preempt_count可以判断当前所处的上下文。需要注意软中断上下文有两个检查函数:

  • in_softirq()bits[8,16)进行判断是否是软中断上下文,因此宏观上中断下半部禁用也可以被认为是软中断上下文。
  • in_serving_softirq()判断当前是否处于中断下半部执行过程中,可以取softirq count这个bit位进行确认。

标签:count,中断,计数,上下文,bits,define
From: https://www.cnblogs.com/wodemia/p/18145886

相关文章

  • 软中断
    softirq软中断(softirq)是内核虚拟出的一种异步中断,通过raise_softirq()来触发,可以将一些不紧急的任务推迟执行。在软中断中可以处理中断下半部,比如网卡数据收发的软中断NET_TX_SOFTIRQ和NET_RX_SOFTIRQ,还可以处理一些需要异步执行的场景,比如定时器软中断TIMER_SOFTIRQ。softirq这......
  • 汇编语言简易教程(14):中断与恢复
    汇编语言简易教程(14):中断与恢复从一般意义上讲,中断是工作流的暂停或保持。例如,如果您正在打电话,门铃响了,则电话通话将处于暂停状态,门将应答。销售人员被送走后,电话交谈恢复(对话中断的地方)在计算机编程中,中断也是当前正在执行的过程的暂停或保持。通常,当前进程会中断,以便可......
  • •请花大概几天左右的时间,快速阅读完整本教材,列出你不懂的或者感兴趣的3-5个问题(或者
    课程作业探索软件工程技术与应用:五个有待思考的问题软件工程,作为技术世界的重要支柱,不仅仅是关于编码和系统的构建。它深深植根于解决复杂问题的艺术和科学之中,其影响范围远远超出了代码本身。随着技术的飞速进步和社会需求的不断变化,软件工程面临着一系列新的挑战和机遇。以下......
  • STM32外部中断小记
    一、EXTI配置步骤//1.配置RCC时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO时钟,AFIO:GPIO复用/重映射功能//2.配置EXTIGPIO端口及工作模式(输入模式)//3.配置EXTI中断线、模式(上升沿、下降沿......
  • playwright-上下文管理器-xpath定位-页面切换
    fromplaywright.sync_apiimportsync_playwright#封装一个方法用于切换浏览器窗口页面defswitch_to_page(context,url):forpageincontext.pages:ifurl==page.url:#如果传进来的url等于列表中urlpage.bring_to_front()#对页面进行暂停......
  • 第7章 中断系统
    第7章中断系统一、中断概述中断技术是在微机中广泛使用的一种资源共享技术。中断中断是指当CPU在正常执行程序时,由于外部或内部事件强迫CPU停止当前执行的程序,转去为事件服务(中断服务),服务完毕,又能自动返回到被中断的程序中继续执行。中断功能实现CPU与外设的速度匹......
  • Golang context (上下文)是什么
    Golangcontext(上下文)是什么?原创 几颗酥 几颗酥 2024-03-1111:24 广西 1人听过介绍Context 是golang中十分重要的接口,用于定义 goroutine 中的上下文信息,context 常用于以下几种情况:数据传递:在多个 goroutine 中传递数据超时管理:通过配置超时时间,可以......
  • FOC算法中为啥用PWM触发ADC中断
    在FOC(FieldOrientedControl,场向量控制)算法中,为什么要使用PWM(PulseWidthModulation,脉宽调制)触发ADC(Analog-to-DigitalConverter,模数转换器)中断呢?在FOC中,PWM被用来控制电机的相电流,以实现精确的控制。通过改变PWM信号的占空比,可以调节电机的转速和转矩。而为了实现精确的控......
  • 计算机怎么实现中断
    中断类型外部中断可屏蔽中断可屏蔽中断是通过INTR引脚进入CPU的,外部设备如硬盘、网卡等发出的中断都是可屏蔽中断可屏蔽的意思是此外部设备发出的的中断,CPU可以不理会,因为它不会导致系统宕机,所有可以通过eflags寄存器的IF位将所有这些外部设备的中断屏蔽不可屏蔽中断......
  • FreeRTOS中断管理以及实验
    FreeRTOS中断管理以及实验继续记录学习FreeRTOS的博客,参照正点原子FreeRTOS的视频。ARMCortex-M使用了8位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器,STM32寄存器中并且这个寄存器只使用[7:4],所以具体表达优先级的位数如下图所示:STM32的中断优先......