mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	softirq: Use hotplug thread infrastructure
[ paulmck: Call rcu_note_context_switch() with interrupts enabled. ] Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Namhyung Kim <namhyung@kernel.org> Link: http://lkml.kernel.org/r/20120716103948.456416747@linutronix.de Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
		
							parent
							
								
									3180d89b47
								
							
						
					
					
						commit
						3e339b5dae
					
				
					 1 changed files with 27 additions and 84 deletions
				
			
		
							
								
								
									
										101
									
								
								kernel/softirq.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								kernel/softirq.c
									
									
									
									
									
								
							|  | @ -23,6 +23,7 @@ | |||
| #include <linux/rcupdate.h> | ||||
| #include <linux/ftrace.h> | ||||
| #include <linux/smp.h> | ||||
| #include <linux/smpboot.h> | ||||
| #include <linux/tick.h> | ||||
| 
 | ||||
| #define CREATE_TRACE_POINTS | ||||
|  | @ -742,49 +743,22 @@ void __init softirq_init(void) | |||
| 	open_softirq(HI_SOFTIRQ, tasklet_hi_action); | ||||
| } | ||||
| 
 | ||||
| static int run_ksoftirqd(void * __bind_cpu) | ||||
| static int ksoftirqd_should_run(unsigned int cpu) | ||||
| { | ||||
| 	set_current_state(TASK_INTERRUPTIBLE); | ||||
| 	return local_softirq_pending(); | ||||
| } | ||||
| 
 | ||||
| 	while (!kthread_should_stop()) { | ||||
| 		preempt_disable(); | ||||
| 		if (!local_softirq_pending()) { | ||||
| 			schedule_preempt_disabled(); | ||||
| 		} | ||||
| 
 | ||||
| 		__set_current_state(TASK_RUNNING); | ||||
| 
 | ||||
| 		while (local_softirq_pending()) { | ||||
| 			/* Preempt disable stops cpu going offline.
 | ||||
| 			   If already offline, we'll be on wrong CPU: | ||||
| 			   don't process */ | ||||
| 			if (cpu_is_offline((long)__bind_cpu)) | ||||
| 				goto wait_to_die; | ||||
| static void run_ksoftirqd(unsigned int cpu) | ||||
| { | ||||
| 	local_irq_disable(); | ||||
| 			if (local_softirq_pending()) | ||||
| 	if (local_softirq_pending()) { | ||||
| 		__do_softirq(); | ||||
| 		rcu_note_context_switch(cpu); | ||||
| 		local_irq_enable(); | ||||
| 			sched_preempt_enable_no_resched(); | ||||
| 		cond_resched(); | ||||
| 			preempt_disable(); | ||||
| 			rcu_note_context_switch((long)__bind_cpu); | ||||
| 		return; | ||||
| 	} | ||||
| 		preempt_enable(); | ||||
| 		set_current_state(TASK_INTERRUPTIBLE); | ||||
| 	} | ||||
| 	__set_current_state(TASK_RUNNING); | ||||
| 	return 0; | ||||
| 
 | ||||
| wait_to_die: | ||||
| 	preempt_enable(); | ||||
| 	/* Wait for kthread_stop */ | ||||
| 	set_current_state(TASK_INTERRUPTIBLE); | ||||
| 	while (!kthread_should_stop()) { | ||||
| 		schedule(); | ||||
| 		set_current_state(TASK_INTERRUPTIBLE); | ||||
| 	} | ||||
| 	__set_current_state(TASK_RUNNING); | ||||
| 	return 0; | ||||
| 	local_irq_enable(); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_HOTPLUG_CPU | ||||
|  | @ -850,48 +824,12 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, | |||
| 				  unsigned long action, | ||||
| 				  void *hcpu) | ||||
| { | ||||
| 	int hotcpu = (unsigned long)hcpu; | ||||
| 	struct task_struct *p; | ||||
| 
 | ||||
| 	switch (action) { | ||||
| 	case CPU_UP_PREPARE: | ||||
| 	case CPU_UP_PREPARE_FROZEN: | ||||
| 		p = kthread_create_on_node(run_ksoftirqd, | ||||
| 					   hcpu, | ||||
| 					   cpu_to_node(hotcpu), | ||||
| 					   "ksoftirqd/%d", hotcpu); | ||||
| 		if (IS_ERR(p)) { | ||||
| 			printk("ksoftirqd for %i failed\n", hotcpu); | ||||
| 			return notifier_from_errno(PTR_ERR(p)); | ||||
| 		} | ||||
| 		kthread_bind(p, hotcpu); | ||||
|   		per_cpu(ksoftirqd, hotcpu) = p; | ||||
|  		break; | ||||
| 	case CPU_ONLINE: | ||||
| 	case CPU_ONLINE_FROZEN: | ||||
| 		wake_up_process(per_cpu(ksoftirqd, hotcpu)); | ||||
| 		break; | ||||
| #ifdef CONFIG_HOTPLUG_CPU | ||||
| 	case CPU_UP_CANCELED: | ||||
| 	case CPU_UP_CANCELED_FROZEN: | ||||
| 		if (!per_cpu(ksoftirqd, hotcpu)) | ||||
| 			break; | ||||
| 		/* Unbind so it can run.  Fall thru. */ | ||||
| 		kthread_bind(per_cpu(ksoftirqd, hotcpu), | ||||
| 			     cpumask_any(cpu_online_mask)); | ||||
| 	case CPU_DEAD: | ||||
| 	case CPU_DEAD_FROZEN: { | ||||
| 		static const struct sched_param param = { | ||||
| 			.sched_priority = MAX_RT_PRIO-1 | ||||
| 		}; | ||||
| 
 | ||||
| 		p = per_cpu(ksoftirqd, hotcpu); | ||||
| 		per_cpu(ksoftirqd, hotcpu) = NULL; | ||||
| 		sched_setscheduler_nocheck(p, SCHED_FIFO, ¶m); | ||||
| 		kthread_stop(p); | ||||
| 		takeover_tasklets(hotcpu); | ||||
| 	case CPU_DEAD_FROZEN: | ||||
| 		takeover_tasklets((unsigned long)hcpu); | ||||
| 		break; | ||||
| 	} | ||||
| #endif /* CONFIG_HOTPLUG_CPU */ | ||||
| 	} | ||||
| 	return NOTIFY_OK; | ||||
|  | @ -901,14 +839,19 @@ static struct notifier_block __cpuinitdata cpu_nfb = { | |||
| 	.notifier_call = cpu_callback | ||||
| }; | ||||
| 
 | ||||
| static struct smp_hotplug_thread softirq_threads = { | ||||
| 	.store			= &ksoftirqd, | ||||
| 	.thread_should_run	= ksoftirqd_should_run, | ||||
| 	.thread_fn		= run_ksoftirqd, | ||||
| 	.thread_comm		= "ksoftirqd/%u", | ||||
| }; | ||||
| 
 | ||||
| static __init int spawn_ksoftirqd(void) | ||||
| { | ||||
| 	void *cpu = (void *)(long)smp_processor_id(); | ||||
| 	int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu); | ||||
| 
 | ||||
| 	BUG_ON(err != NOTIFY_OK); | ||||
| 	cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); | ||||
| 	register_cpu_notifier(&cpu_nfb); | ||||
| 
 | ||||
| 	BUG_ON(smpboot_register_percpu_thread(&softirq_threads)); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| early_initcall(spawn_ksoftirqd); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Thomas Gleixner
						Thomas Gleixner