zoukankan      html  css  js  c++  java
  • 中断子系统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;
    }


  • 相关阅读:
    Java实现 LeetCode 784 字母大小写全排列(DFS)
    Java实现 LeetCode 784 字母大小写全排列(DFS)
    Java实现 LeetCode 783 二叉搜索树节点最小距离(遍历)
    Java实现 LeetCode 783 二叉搜索树节点最小距离(遍历)
    Java实现 LeetCode 783 二叉搜索树节点最小距离(遍历)
    Java实现 LeetCode 781 森林中的兔子(分析题)
    一种机制,与js类似
    图片热区
    我对 aspnetpager和repeater以及查询条件的封装
    我对webform的整改。
  • 原文地址:https://www.cnblogs.com/riasky/p/3429350.html
Copyright © 2011-2022 走看看