中断子系统8_软中断入口处理

简介:
//	irq统计信息
1.1 typedef struct {
	unsigned int __softirq_pending;//softirq标志位,32种softirq
	unsigned long idle_timestamp;
	unsigned int __nmi_count;	//nmi中断发生次数
	unsigned int apic_timer_irqs;	/* arch dependent */
} ____cacheline_aligned irq_cpustat_t;

//	检查softirq标志是否被置位
1.2 #define local_softirq_pending() \
	__IRQ_STAT(smp_processor_id(), __softirq_pending)

//	per-cpu irq统计信息
1.3 #define __IRQ_STAT(cpu, member)	(irq_stat[cpu].member)



//	软中断入口函数
//	调用路径 __do_IRQ->irq_exit->do_softirq
//	函数主要任务:
//		1.确保没有hardirq,softirq运行情况,否则直接退出
//		2.关中断,检查是否有raise的softirq
//			2.1 执行软中断处理函数
//		3.恢复中断状态
//	注:
//		1.软中断执行过程中,开中断,关软中断,禁止内核抢占
//		2.do_softirq会在中断、softirqd两条路径上被调用,同时只有一个在执行
2.1 asmlinkage void do_softirq(void)
{
	__u32 pending;
	unsigned long flags;

	//如果当前有hardirq,softirq在运行中,直接退出
	if (in_interrupt())
		return;
	//关中断下检查softirq标志
	local_irq_save(flags);
	pending = local_softirq_pending();
	//执行softirq处理函数
	if (pending)
		__do_softirq();
	//恢复之前的中断状态
	local_irq_restore(flags);
}


//	执行软中断处理函数
//	调用路径 __do_IRQ->irq_exit->do_softirq->__do_softirq
//	函数主要任务:
//		1.获取raise的softirq比特位
//		2.禁止本cpu的softirq
//		3.清除softirq标志位
//		4.开中断		
//		5.遍历softirq_vec,执行被raise的softirq_action的处理函数
//		6.关中断
//		7.检查softirq标志位
//			7.1 如果有raise的softirq,并且没有超过最大的遍历次数,重复步骤3
//			7.2 否则,唤醒softirq核心进程处理softirq
//		8.开启本cpu的softirq
2.2 asmlinkage void __do_softirq(void)
{
	struct softirq_action *h;
	__u32 pending;
	//最大遍历次数10次
	int max_restart = MAX_SOFTIRQ_RESTART;
	int cpu;
	//本cpu被raise的softirq
	pending = local_softirq_pending();
	//禁止本cpu softirq
	local_bh_disable();
	cpu = smp_processor_id();
restart:
	//softirq标志位清空
	local_softirq_pending() = 0;
	//开中断
	local_irq_enable();

	h = softirq_vec;

	do {
		if (pending & 1) {
			h->action(h);
			rcu_bh_qsctr_inc(cpu);
		}
		h++;
		pending >>= 1;
	} while (pending);

	local_irq_disable();

	pending = local_softirq_pending();
	if (pending && --max_restart)
		goto restart;
	//超过最大的调用次数,唤醒softirq核心进程
	if (pending)
		wakeup_softirqd();
	//开启软中断
	__local_bh_enable();
}

//	禁止本cpu softirq
2.2 #define local_bh_disable() \
		do { add_preempt_count(SOFTIRQ_OFFSET); barrier(); } while (0)


//	唤醒softirq进程
//	函数主要任务:
//		1.获取本cpu的softirq进程
//		2.如果进程未执行,唤醒其
//	注:
//		关中断,关软中断状态下唤醒softirq进程
3.1 static inline void wakeup_softirqd(void)
{
	//per cpu进程
	struct task_struct *tsk = __get_cpu_var(ksoftirqd);
	//softirq进程非就绪状态
	if (tsk && tsk->state != TASK_RUNNING)
	{
		wake_up_process(tsk);//唤醒进程
	}
}

//	softirq核心进程function
//	函数主要任务:
//		1.检查softirq标志
//		2.禁止内核抢占
//		3.通过do_softirq执行软中断处理函数
//		4.开启内核抢占
//	注:
//		1.软中断执行过程中,开中断,关软中断,禁止内核抢占
//		2.do_softirq会在中断、softirqd两条路径上被调用,同时只有一个在执行
3.2 static int ksoftirqd(void * __bind_cpu)
{
	//设置静态优先级
	set_user_nice(current, 19);
	//当前进程不允许被frozen
	current->flags |= PF_NOFREEZE;
	//可中断睡眠
	set_current_state(TASK_INTERRUPTIBLE);
	while (!kthread_should_stop()) {
		//没有raised的softirq,调度
		if (!local_softirq_pending())
		{
			schedule();
		}	
		//进程被唤醒
		__set_current_state(TASK_RUNNING);
		//检查softirq标志
		while (local_softirq_pending()) {
			//禁止内核抢占
			preempt_disable();
			//与中断路径执行相同的处理函数,二者同时只有一个在执行
			do_softirq();
			//开启内核抢占
			preempt_enable();
			//检查是否need reschedule
			cond_resched();
		}

		set_current_state(TASK_INTERRUPTIBLE);
	}
	//设置进程为运行状态,然后退出
	//此进程不再会被wakeup_softirqd唤醒执行
	__set_current_state(TASK_RUNNING);
	return 0;
}

//	softirq数组
//		irq_cpustat_t->__softirq_pending只有32bit,因此共有32种软中断
4.1 static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;

//	softirq描述符
4.2 struct softirq_action
{
	void	(*action)(struct softirq_action *);
	void	*data;
};

//	静态编译的软中断类型
4.3 enum
{
	HI_SOFTIRQ=0,
	TIMER_SOFTIRQ,
	NET_TX_SOFTIRQ,
	NET_RX_SOFTIRQ,
	SCSI_SOFTIRQ,
	TASKLET_SOFTIRQ
};

//	raise softirq
//	注:
//		调用者负责调用前禁止中断
5.1 inline fastcall void raise_softirq_irqoff(unsigned int nr)
{
	//设置对应的bit位
	__raise_softirq_irqoff(nr);
	//当前不在中断上下文中,唤醒softirq进程
	if (!in_interrupt())
		wakeup_softirqd();
}
//	raise softirq
//	注:
//		本函数会负责关闭中断
5.2 void fastcall raise_softirq(unsigned int nr)
{
	unsigned long flags;
	//关中断
	local_irq_save(flags);
	raise_softirq_irqoff(nr);
	local_irq_restore(flags);
}
//	注册softirq
5.3 void open_softirq(int nr, void (*action)(struct softirq_action*), void *data)
{
	softirq_vec[nr].data = data;
	softirq_vec[nr].action = action;
}

目录
相关文章
|
传感器 监控 Shell
|
8月前
|
存储 Linux 网络安全
如何从CentOS7升级到8?CentOS8最新安装教程
从CentOS 7升级到8只需三步:清理系统、更换软件包及存储库、安装新内核与发布版本。首先确保系统最新并清理冗余包,接着替换基础系统包为CentOS 8版本,最后通过DNF工具完成内核更新与系统同步。整个过程需在终端执行,建议升级前备份VPS快照以防数据丢失。此方法可避免重装系统导致的数据清除问题,实现平滑升级。
1421 6
|
1月前
|
存储 缓存 自然语言处理
64_模型部署:推理优化策略
随着人工智能技术的飞速发展,大型语言模型(LLM)在自然语言处理、多模态理解等领域展现出惊人的能力。然而,将这些模型从实验室环境部署到实际生产系统中,面临着诸多挑战。根据2025年最新研究数据,大模型部署的主要挑战包括:
|
8月前
|
自然语言处理 JavaScript 前端开发
《深度剖析:开发鸿蒙原生应用,为何ArkTS是最优之选》
ArkTS 是鸿蒙原生应用开发的核心语言,基于 TypeScript 深度扩展,具备强大的静态检查和类型系统,有效提升代码稳定性。其声明式语法简洁高效,助力快速构建复杂用户界面;多维度状态管理机制灵活掌控应用状态,支持全局与跨设备数据同步。此外,ArkTS 与 ArkUI 深度集成,优化分布式场景下的多设备协同开发体验,并通过完善工具链降低开发门槛。随着持续演进,ArkTS 将进一步推动鸿蒙生态繁荣,为开发者带来更高效的解决方案。
319 0
|
Linux 开发工具 Android开发
python之实现apk
python之实现apk
|
人工智能 架构师 容灾
函数计算 FC:首发 GPU 极速模式,更弹性、更降本
2024 云栖大会上,函数计算 FC 为 AI 加码,首发 GPU 极速模式,让 GPU 可以更弹性、更便宜。
575 14
|
运维 Kubernetes 数据处理
阿里云Argo X K8s玩转工作流引擎,实现大规模并行计算
Kubernetes已经成为事实的云原生操作系统,成为业务上云、容器化的标准。从过去无状态应用、企业核心应用,到现在AI时代的数据处理、AI训练、科学仿真等,越来越多的离线任务跑在K8s上。
|
网络协议 Linux 网络架构
linux:ping不通www.baidu.com
linux:ping不通www.baidu.com
5112 0
|
Unix 信息无障碍 数据安全/隐私保护
粘滞键是什么意思有什么作用(粘滞键的设置和取消关闭)
粘滞键是什么意思有什么作用(粘滞键的设置和取消关闭)
2657 0
|
机器学习/深度学习 人工智能 BI
深度学习入门基础CNN系列——卷积计算
卷积是数学分析中的一种积分变换的方法,在图像处理中采用的是卷积的离散形式。这里需要说明的是,在卷积神经网络中,卷积层的实现方式实际上是数学中定义的**互相关 (cross-correlation)运算**,与数学分析中的卷积定义有所不同,这里跟其他框架和卷积神经网络的教程保持一致,都使用互相关运算作为卷积的定义,具体的计算过程如 **图** 所示。
深度学习入门基础CNN系列——卷积计算