public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH][2.5] fix preempt-issues with smp_call_function()
@ 2003-02-25 18:08 Thomas Schlichter
  2003-02-26  9:27 ` Andrew Morton
  2003-02-26 10:37 ` Dave Jones
  0 siblings, 2 replies; 14+ messages in thread
From: Thomas Schlichter @ 2003-02-25 18:08 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Dave Jones, Hugh Dickins, Andrew Morton, Linux Kernel


[-- Attachment #1.1: body text --]
[-- Type: text/plain, Size: 429 bytes --]

Hello,

here is a patch to solve all (I hope I missed none) possible problems that 
could occur on SMP machines running a preemptible kernel when 
smp_call_function() calls a function which should be also executed on the 
current processor.

This patch is based on the one Dave Jones sent to the LKML last friday and 
applies to the linux kernel version 2.5.63.

Thank you for any response...

    Thomas Schlichter

[-- Attachment #1.2: preempt_fix.patch --]
[-- Type: text/x-diff, Size: 26527 bytes --]

diff -urP linux-2.5.63/arch/alpha/kernel/process.c linux-2.5.63_patched/arch/alpha/kernel/process.c
--- linux-2.5.63/arch/alpha/kernel/process.c	Mon Feb 24 20:05:42 2003
+++ linux-2.5.63_patched/arch/alpha/kernel/process.c	Mon Feb 24 23:02:43 2003
@@ -155,10 +155,7 @@
 	struct halt_info args;
 	args.mode = mode;
 	args.restart_cmd = restart_cmd;
-#ifdef CONFIG_SMP
-	smp_call_function(common_shutdown_1, &args, 1, 0);
-#endif
-	common_shutdown_1(&args);
+	on_each_cpu(common_shutdown_1, &args, 1, 0);
 }
 
 void
diff -urP linux-2.5.63/arch/alpha/kernel/smp.c linux-2.5.63_patched/arch/alpha/kernel/smp.c
--- linux-2.5.63/arch/alpha/kernel/smp.c	Mon Feb 24 20:05:14 2003
+++ linux-2.5.63_patched/arch/alpha/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -899,10 +899,8 @@
 smp_imb(void)
 {
 	/* Must wait other processors to flush their icache before continue. */
-	if (smp_call_function(ipi_imb, NULL, 1, 1))
+	if (on_each_cpu(ipi_imb, NULL, 1, 1))
 		printk(KERN_CRIT "smp_imb: timed out\n");
-
-	imb();
 }
 
 static void
@@ -916,11 +914,9 @@
 {
 	/* Although we don't have any data to pass, we do want to
 	   synchronize with the other processors.  */
-	if (smp_call_function(ipi_flush_tlb_all, NULL, 1, 1)) {
+	if (on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1)) {
 		printk(KERN_CRIT "flush_tlb_all: timed out\n");
 	}
-
-	tbia();
 }
 
 #define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
@@ -938,6 +934,8 @@
 void
 flush_tlb_mm(struct mm_struct *mm)
 {
+	preempt_disable();
+
 	if (mm == current->active_mm) {
 		flush_tlb_current(mm);
 		if (atomic_read(&mm->mm_users) <= 1) {
@@ -948,6 +946,7 @@
 				if (mm->context[cpu])
 					mm->context[cpu] = 0;
 			}
+			preempt_enable();
 			return;
 		}
 	}
@@ -955,6 +954,8 @@
 	if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
 		printk(KERN_CRIT "flush_tlb_mm: timed out\n");
 	}
+
+	preempt_enable();
 }
 
 struct flush_tlb_page_struct {
@@ -981,6 +982,8 @@
 	struct flush_tlb_page_struct data;
 	struct mm_struct *mm = vma->vm_mm;
 
+	preempt_disable();
+
 	if (mm == current->active_mm) {
 		flush_tlb_current_page(mm, vma, addr);
 		if (atomic_read(&mm->mm_users) <= 1) {
@@ -991,6 +994,7 @@
 				if (mm->context[cpu])
 					mm->context[cpu] = 0;
 			}
+			preempt_enable();
 			return;
 		}
 	}
@@ -1002,6 +1006,8 @@
 	if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) {
 		printk(KERN_CRIT "flush_tlb_page: timed out\n");
 	}
+
+	preempt_enable();
 }
 
 void
@@ -1030,6 +1036,8 @@
 	if ((vma->vm_flags & VM_EXEC) == 0)
 		return;
 
+	preempt_disable();
+
 	if (mm == current->active_mm) {
 		__load_new_mm_context(mm);
 		if (atomic_read(&mm->mm_users) <= 1) {
@@ -1040,6 +1048,7 @@
 				if (mm->context[cpu])
 					mm->context[cpu] = 0;
 			}
+			preempt_enable();
 			return;
 		}
 	}
@@ -1047,6 +1056,8 @@
 	if (smp_call_function(ipi_flush_icache_page, mm, 1, 1)) {
 		printk(KERN_CRIT "flush_icache_page: timed out\n");
 	}
+
+	preempt_enable();
 }
 \f
 #ifdef CONFIG_DEBUG_SPINLOCK
diff -urP linux-2.5.63/arch/i386/kernel/io_apic.c linux-2.5.63_patched/arch/i386/kernel/io_apic.c
--- linux-2.5.63/arch/i386/kernel/io_apic.c	Mon Feb 24 20:05:15 2003
+++ linux-2.5.63_patched/arch/i386/kernel/io_apic.c	Mon Feb 24 23:02:43 2003
@@ -1376,8 +1376,7 @@
 
 void print_all_local_APICs (void)
 {
-	smp_call_function(print_local_APIC, NULL, 1, 1);
-	print_local_APIC(NULL);
+	on_each_cpu(print_local_APIC, NULL, 1, 1);
 }
 
 void /*__init*/ print_PIC(void)
@@ -1843,8 +1842,7 @@
 	 */ 
 	printk(KERN_INFO "activating NMI Watchdog ...");
 
-	smp_call_function(enable_NMI_through_LVT0, NULL, 1, 1);
-	enable_NMI_through_LVT0(NULL);
+	on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
 
 	printk(" done.\n");
 }
diff -urP linux-2.5.63/arch/i386/kernel/ldt.c linux-2.5.63_patched/arch/i386/kernel/ldt.c
--- linux-2.5.63/arch/i386/kernel/ldt.c	Mon Feb 24 20:05:38 2003
+++ linux-2.5.63_patched/arch/i386/kernel/ldt.c	Mon Feb 24 23:02:43 2003
@@ -55,13 +55,13 @@
 	wmb();
 
 	if (reload) {
+		preempt_disable();
 		load_LDT(pc);
 #ifdef CONFIG_SMP
-		preempt_disable();
 		if (current->mm->cpu_vm_mask != (1 << smp_processor_id()))
 			smp_call_function(flush_ldt, 0, 1, 1);
-		preempt_enable();
 #endif
+		preempt_enable();
 	}
 	if (oldsize) {
 		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
diff -urP linux-2.5.63/arch/i386/kernel/microcode.c linux-2.5.63_patched/arch/i386/kernel/microcode.c
--- linux-2.5.63/arch/i386/kernel/microcode.c	Mon Feb 24 20:05:12 2003
+++ linux-2.5.63_patched/arch/i386/kernel/microcode.c	Mon Feb 24 23:02:32 2003
@@ -183,11 +183,10 @@
 	int i, error = 0, err;
 	struct microcode *m;
 
-	if (smp_call_function(do_update_one, NULL, 1, 1) != 0) {
+	if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
 		printk(KERN_ERR "microcode: IPI timeout, giving up\n");
 		return -EIO;
 	}
-	do_update_one(NULL);
 
 	for (i=0; i<NR_CPUS; i++) {
 		err = update_req[i].err;
diff -urP linux-2.5.63/arch/i386/kernel/smp.c linux-2.5.63_patched/arch/i386/kernel/smp.c
--- linux-2.5.63/arch/i386/kernel/smp.c	Mon Feb 24 20:05:06 2003
+++ linux-2.5.63_patched/arch/i386/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -436,7 +436,7 @@
 	preempt_enable();
 }
 
-static inline void do_flush_tlb_all_local(void)
+static void do_flush_tlb_all(void* info)
 {
 	unsigned long cpu = smp_processor_id();
 
@@ -445,18 +445,9 @@
 		leave_mm(cpu);
 }
 
-static void flush_tlb_all_ipi(void* info)
-{
-	do_flush_tlb_all_local();
-}
-
 void flush_tlb_all(void)
 {
-	preempt_disable();
-	smp_call_function (flush_tlb_all_ipi,0,1,1);
-
-	do_flush_tlb_all_local();
-	preempt_enable();
+	on_each_cpu(do_flush_tlb_all, 0, 1, 1);
 }
 
 /*
diff -urP linux-2.5.63/arch/i386/kernel/sysenter.c linux-2.5.63_patched/arch/i386/kernel/sysenter.c
--- linux-2.5.63/arch/i386/kernel/sysenter.c	Mon Feb 24 20:06:02 2003
+++ linux-2.5.63_patched/arch/i386/kernel/sysenter.c	Mon Feb 24 23:02:43 2003
@@ -95,8 +95,7 @@
 		return 0;
 
 	memcpy((void *) page, sysent, sizeof(sysent));
-	enable_sep_cpu(NULL);
-	smp_call_function(enable_sep_cpu, NULL, 1, 1);
+	on_each_cpu(enable_sep_cpu, NULL, 1, 1);
 	return 0;
 }
 
diff -urP linux-2.5.63/arch/i386/mach-voyager/voyager_smp.c linux-2.5.63_patched/arch/i386/mach-voyager/voyager_smp.c
--- linux-2.5.63/arch/i386/mach-voyager/voyager_smp.c	Mon Feb 24 20:05:16 2003
+++ linux-2.5.63_patched/arch/i386/mach-voyager/voyager_smp.c	Mon Feb 24 23:02:43 2003
@@ -1209,8 +1209,8 @@
 		smp_call_function_interrupt();
 }
 
-static inline void
-do_flush_tlb_all_local(void)
+static void
+do_flush_tlb_all(void* info)
 {
 	unsigned long cpu = smp_processor_id();
 
@@ -1220,19 +1220,11 @@
 }
 
 
-static void
-flush_tlb_all_function(void* info)
-{
-	do_flush_tlb_all_local();
-}
-
 /* flush the TLB of every active CPU in the system */
 void
 flush_tlb_all(void)
 {
-	smp_call_function (flush_tlb_all_function, 0, 1, 1);
-
-	do_flush_tlb_all_local();
+	on_each_cpu(do_flush_tlb_all, 0, 1, 1);
 }
 
 /* used to set up the trampoline for other CPUs when the memory manager
diff -urP linux-2.5.63/arch/i386/mm/pageattr.c linux-2.5.63_patched/arch/i386/mm/pageattr.c
--- linux-2.5.63/arch/i386/mm/pageattr.c	Mon Feb 24 20:05:29 2003
+++ linux-2.5.63_patched/arch/i386/mm/pageattr.c	Mon Feb 24 23:02:43 2003
@@ -130,11 +130,8 @@
 } 
 
 static inline void flush_map(void)
-{	
-#ifdef CONFIG_SMP 
-	smp_call_function(flush_kernel_map, NULL, 1, 1);
-#endif	
-	flush_kernel_map(NULL);
+{
+	on_each_cpu(flush_kernel_map, NULL, 1, 1);
 }
 
 struct deferred_page { 
diff -urP linux-2.5.63/arch/i386/oprofile/nmi_int.c linux-2.5.63_patched/arch/i386/oprofile/nmi_int.c
--- linux-2.5.63/arch/i386/oprofile/nmi_int.c	Mon Feb 24 20:05:44 2003
+++ linux-2.5.63_patched/arch/i386/oprofile/nmi_int.c	Mon Feb 24 23:02:43 2003
@@ -95,8 +95,7 @@
 	 * without actually triggering any NMIs as this will
 	 * break the core code horrifically.
 	 */
-	smp_call_function(nmi_cpu_setup, NULL, 0, 1);
-	nmi_cpu_setup(0);
+	on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
 	set_nmi_callback(nmi_callback);
 	oprofile_pmdev = set_nmi_pm_callback(oprofile_pm_callback);
 	return 0;
@@ -148,8 +147,7 @@
 {
 	unset_nmi_pm_callback(oprofile_pmdev);
 	unset_nmi_callback();
-	smp_call_function(nmi_cpu_shutdown, NULL, 0, 1);
-	nmi_cpu_shutdown(0);
+	on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
 }
 
  
@@ -162,8 +160,7 @@
 
 static int nmi_start(void)
 {
-	smp_call_function(nmi_cpu_start, NULL, 0, 1);
-	nmi_cpu_start(0);
+	on_each_cpu(nmi_cpu_start, NULL, 0, 1);
 	return 0;
 }
  
@@ -177,8 +174,7 @@
  
 static void nmi_stop(void)
 {
-	smp_call_function(nmi_cpu_stop, NULL, 0, 1);
-	nmi_cpu_stop(0);
+	on_each_cpu(nmi_cpu_stop, NULL, 0, 1);
 }
 
 
diff -urP linux-2.5.63/arch/ia64/kernel/smp.c linux-2.5.63_patched/arch/ia64/kernel/smp.c
--- linux-2.5.63/arch/ia64/kernel/smp.c	Mon Feb 24 20:06:01 2003
+++ linux-2.5.63_patched/arch/ia64/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -206,18 +206,18 @@
 void
 smp_flush_tlb_all (void)
 {
-	smp_call_function((void (*)(void *))local_flush_tlb_all, 0, 1, 1);
-	local_flush_tlb_all();
+	on_each_cpu((void (*)(void *))local_flush_tlb_all, 0, 1, 1);
 }
 
 void
 smp_flush_tlb_mm (struct mm_struct *mm)
 {
-	local_finish_flush_tlb_mm(mm);
-
 	/* this happens for the common case of a single-threaded fork():  */
 	if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
+	{
+		local_finish_flush_tlb_mm(mm);
 		return;
+	}
 
 	/*
 	 * We could optimize this further by using mm->cpu_vm_mask to track which CPUs
@@ -226,7 +226,7 @@
 	 * anyhow, and once a CPU is interrupted, the cost of local_flush_tlb_all() is
 	 * rather trivial.
 	 */
-	smp_call_function((void (*)(void *))local_finish_flush_tlb_mm, mm, 1, 1);
+	on_each_cpu((void (*)(void *))local_finish_flush_tlb_mm, mm, 1, 1);
 }
 
 /*
diff -urP linux-2.5.63/arch/mips64/kernel/smp.c linux-2.5.63_patched/arch/mips64/kernel/smp.c
--- linux-2.5.63/arch/mips64/kernel/smp.c	Mon Feb 24 20:05:38 2003
+++ linux-2.5.63_patched/arch/mips64/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -195,8 +195,7 @@
 
 void flush_tlb_all(void)
 {
-	smp_call_function(flush_tlb_all_ipi, 0, 1, 1);
-	_flush_tlb_all();
+	on_each_cpu(flush_tlb_all_ipi, 0, 1, 1);
 }
 
 static void flush_tlb_mm_ipi(void *mm)
@@ -219,6 +218,8 @@
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
+	preempt_disable();
+
 	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
 		smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1);
 	} else {
@@ -228,6 +229,8 @@
 				CPU_CONTEXT(i, mm) = 0;
 	}
 	_flush_tlb_mm(mm);
+
+	preempt_enable();
 }
 
 struct flush_tlb_data {
@@ -246,6 +249,8 @@
 
 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
 {
+	preempt_disable();
+
 	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
 		struct flush_tlb_data fd;
 
@@ -260,6 +265,8 @@
 				CPU_CONTEXT(i, mm) = 0;
 	}
 	_flush_tlb_range(mm, start, end);
+
+	preempt_enable();
 }
 
 static void flush_tlb_page_ipi(void *info)
@@ -271,6 +278,8 @@
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
+	preempt_disable();
+
 	if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) {
 		struct flush_tlb_data fd;
 
@@ -284,5 +293,7 @@
 				CPU_CONTEXT(i, vma->vm_mm) = 0;
 	}
 	_flush_tlb_page(vma, page);
+
+	preempt_enable();
 }
 
diff -urP linux-2.5.63/arch/parisc/kernel/cache.c linux-2.5.63_patched/arch/parisc/kernel/cache.c
--- linux-2.5.63/arch/parisc/kernel/cache.c	Mon Feb 24 20:05:29 2003
+++ linux-2.5.63_patched/arch/parisc/kernel/cache.c	Mon Feb 24 23:02:43 2003
@@ -39,8 +39,7 @@
 void
 flush_data_cache(void)
 {
-	smp_call_function((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
-	flush_data_cache_local();
+	on_each_cpu((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
 }
 #endif
 
diff -urP linux-2.5.63/arch/parisc/kernel/irq.c linux-2.5.63_patched/arch/parisc/kernel/irq.c
--- linux-2.5.63/arch/parisc/kernel/irq.c	Mon Feb 24 20:05:16 2003
+++ linux-2.5.63_patched/arch/parisc/kernel/irq.c	Mon Feb 24 23:02:43 2003
@@ -61,20 +61,17 @@
 
 static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;  /* protect IRQ regions */
 
-#ifdef CONFIG_SMP
 static void cpu_set_eiem(void *info)
 {
 	set_eiem((unsigned long) info);
 }
-#endif
 
 static inline void disable_cpu_irq(void *unused, int irq)
 {
 	unsigned long eirr_bit = EIEM_MASK(irq);
 
 	cpu_eiem &= ~eirr_bit;
-	set_eiem(cpu_eiem);
-        smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
+        on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
 }
 
 static void enable_cpu_irq(void *unused, int irq)
@@ -83,8 +80,7 @@
 
 	mtctl(eirr_bit, 23);	/* clear EIRR bit before unmasking */
 	cpu_eiem |= eirr_bit;
-        smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
-	set_eiem(cpu_eiem);
+        on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
 }
 
 /* mask and disable are the same at the CPU level
@@ -100,8 +96,7 @@
 	** handle *any* unmasked pending interrupts.
 	** ie We don't need to check for pending interrupts here.
 	*/
-        smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
-	set_eiem(cpu_eiem);
+        on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
 }
 
 /*
diff -urP linux-2.5.63/arch/parisc/kernel/smp.c linux-2.5.63_patched/arch/parisc/kernel/smp.c
--- linux-2.5.63/arch/parisc/kernel/smp.c	Mon Feb 24 20:06:01 2003
+++ linux-2.5.63_patched/arch/parisc/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -401,7 +401,7 @@
 __setup("maxcpus=", maxcpus);
 
 /*
- * Flush all other CPU's tlb and then mine.  Do this with smp_call_function()
+ * Flush all other CPU's tlb and then mine.  Do this with on_each_cpu()
  * as we want to ensure all TLB's flushed before proceeding.
  */
 
@@ -410,8 +410,7 @@
 void
 smp_flush_tlb_all(void)
 {
-	smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
-	flush_tlb_all_local();
+	on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
 }
 
 
diff -urP linux-2.5.63/arch/parisc/mm/init.c linux-2.5.63_patched/arch/parisc/mm/init.c
--- linux-2.5.63/arch/parisc/mm/init.c	Mon Feb 24 20:05:32 2003
+++ linux-2.5.63_patched/arch/parisc/mm/init.c	Mon Feb 24 23:02:43 2003
@@ -974,8 +974,7 @@
 	    do_recycle++;
 	}
 	spin_unlock(&sid_lock);
-	smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
-	flush_tlb_all_local();
+	on_each_cpu((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
 	if (do_recycle) {
 	    spin_lock(&sid_lock);
 	    recycle_sids(recycle_ndirty,recycle_dirty_array);
diff -urP linux-2.5.63/arch/ppc/kernel/temp.c linux-2.5.63_patched/arch/ppc/kernel/temp.c
--- linux-2.5.63/arch/ppc/kernel/temp.c	Mon Feb 24 20:05:33 2003
+++ linux-2.5.63_patched/arch/ppc/kernel/temp.c	Mon Feb 24 23:02:43 2003
@@ -194,10 +194,7 @@
 
 	/* schedule ourselves to be run again */
 	mod_timer(&tau_timer, jiffies + shrink_timer) ;
-#ifdef CONFIG_SMP
-	smp_call_function(tau_timeout, NULL, 1, 0);
-#endif
-	tau_timeout(NULL);
+	on_each_cpu(tau_timeout, NULL, 1, 0);
 }
 
 /*
@@ -239,10 +236,7 @@
 	tau_timer.expires = jiffies + shrink_timer;
 	add_timer(&tau_timer);
 	
-#ifdef CONFIG_SMP
-	smp_call_function(TAU_init_smp, NULL, 1, 0);
-#endif
-	TAU_init_smp(NULL);
+	on_each_cpu(TAU_init_smp, NULL, 1, 0);
 	
 	printk("Thermal assist unit ");
 #ifdef CONFIG_TAU_INT
diff -urP linux-2.5.63/arch/s390/kernel/smp.c linux-2.5.63_patched/arch/s390/kernel/smp.c
--- linux-2.5.63/arch/s390/kernel/smp.c	Mon Feb 24 20:05:05 2003
+++ linux-2.5.63_patched/arch/s390/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -228,8 +228,7 @@
 void machine_restart_smp(char * __unused) 
 {
 	cpu_restart_map = cpu_online_map;
-        smp_call_function(do_machine_restart, NULL, 0, 0);
-	do_machine_restart(NULL);
+        on_each_cpu(do_machine_restart, NULL, 0, 0);
 }
 
 static void do_machine_halt(void * __unused)
@@ -247,8 +246,7 @@
 
 void machine_halt_smp(void)
 {
-        smp_call_function(do_machine_halt, NULL, 0, 0);
-	do_machine_halt(NULL);
+        on_each_cpu(do_machine_halt, NULL, 0, 0);
 }
 
 static void do_machine_power_off(void * __unused)
@@ -266,8 +264,7 @@
 
 void machine_power_off_smp(void)
 {
-        smp_call_function(do_machine_power_off, NULL, 0, 0);
-	do_machine_power_off(NULL);
+        on_each_cpu(do_machine_power_off, NULL, 0, 0);
 }
 
 /*
@@ -339,8 +336,7 @@
 
 void smp_ptlb_all(void)
 {
-        smp_call_function(smp_ptlb_callback, NULL, 0, 1);
-	local_flush_tlb();
+        on_each_cpu(smp_ptlb_callback, NULL, 0, 1);
 }
 
 /*
@@ -400,8 +396,7 @@
 	parms.end_ctl = cr;
 	parms.orvals[cr] = 1 << bit;
 	parms.andvals[cr] = 0xFFFFFFFF;
-	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_set_bit(cr, bit);
+	on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
@@ -414,8 +409,7 @@
 	parms.end_ctl = cr;
 	parms.orvals[cr] = 0x00000000;
 	parms.andvals[cr] = ~(1 << bit);
-	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_clear_bit(cr, bit);
+	on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
diff -urP linux-2.5.63/arch/s390x/kernel/smp.c linux-2.5.63_patched/arch/s390x/kernel/smp.c
--- linux-2.5.63/arch/s390x/kernel/smp.c	Mon Feb 24 20:05:32 2003
+++ linux-2.5.63_patched/arch/s390x/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -227,8 +227,7 @@
 void machine_restart_smp(char * __unused) 
 {
 	cpu_restart_map = cpu_online_map;
-        smp_call_function(do_machine_restart, NULL, 0, 0);
-	do_machine_restart(NULL);
+        on_each_cpu(do_machine_restart, NULL, 0, 0);
 }
 
 static void do_machine_halt(void * __unused)
@@ -246,8 +245,7 @@
 
 void machine_halt_smp(void)
 {
-        smp_call_function(do_machine_halt, NULL, 0, 0);
-	do_machine_halt(NULL);
+        on_each_cpu(do_machine_halt, NULL, 0, 0);
 }
 
 static void do_machine_power_off(void * __unused)
@@ -265,8 +263,7 @@
 
 void machine_power_off_smp(void)
 {
-        smp_call_function(do_machine_power_off, NULL, 0, 0);
-	do_machine_power_off(NULL);
+        on_each_cpu(do_machine_power_off, NULL, 0, 0);
 }
 
 /*
@@ -383,8 +380,7 @@
 	parms.end_ctl = cr;
 	parms.orvals[cr] = 1 << bit;
 	parms.andvals[cr] = -1L;
-	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_set_bit(cr, bit);
+	on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 /*
@@ -397,8 +393,7 @@
 	parms.end_ctl = cr;
 	parms.orvals[cr] = 0;
 	parms.andvals[cr] = ~(1L << bit);
-	smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
-        __ctl_clear_bit(cr, bit);
+	on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
 }
 
 
diff -urP linux-2.5.63/arch/x86_64/kernel/bluesmoke.c linux-2.5.63_patched/arch/x86_64/kernel/bluesmoke.c
--- linux-2.5.63/arch/x86_64/kernel/bluesmoke.c	Mon Feb 24 20:05:43 2003
+++ linux-2.5.63_patched/arch/x86_64/kernel/bluesmoke.c	Mon Feb 24 23:02:43 2003
@@ -111,11 +111,7 @@
 {
 	u32 low, high;
 	int i;
-	unsigned int *cpu = info;
 
-	BUG_ON (*cpu != smp_processor_id());
-
-	preempt_disable();
 	for (i=0; i<banks; i++) {
 		rdmsr(MSR_IA32_MC0_STATUS+i*4, low, high);
 
@@ -130,20 +126,12 @@
 			wmb();
 		}
 	}
-	preempt_enable();
 }
 
 
 static void mce_timerfunc (unsigned long data)
 {
-	unsigned int i;
-
-	for (i=0; i<smp_num_cpus; i++) {
-		if (i == smp_processor_id())
-			mce_checkregs(&i);
-		else
-			smp_call_function (mce_checkregs, &i, 1, 1);
-	}
+	on_each_cpu (mce_checkregs, NULL, 1, 1);
 
 	/* Refresh the timer. */
 	mce_timer.expires = jiffies + MCE_RATE;
diff -urP linux-2.5.63/arch/x86_64/kernel/io_apic.c linux-2.5.63_patched/arch/x86_64/kernel/io_apic.c
--- linux-2.5.63/arch/x86_64/kernel/io_apic.c	Mon Feb 24 20:05:32 2003
+++ linux-2.5.63_patched/arch/x86_64/kernel/io_apic.c	Mon Feb 24 23:02:43 2003
@@ -928,8 +928,7 @@
 
 void print_all_local_APICs (void)
 {
-	smp_call_function(print_local_APIC, NULL, 1, 1);
-	print_local_APIC(NULL);
+	on_each_cpu(print_local_APIC, NULL, 1, 1);
 }
 
 void /*__init*/ print_PIC(void)
diff -urP linux-2.5.63/arch/x86_64/kernel/ldt.c linux-2.5.63_patched/arch/x86_64/kernel/ldt.c
--- linux-2.5.63/arch/x86_64/kernel/ldt.c	Mon Feb 24 20:05:44 2003
+++ linux-2.5.63_patched/arch/x86_64/kernel/ldt.c	Mon Feb 24 23:02:43 2003
@@ -60,13 +60,13 @@
 	pc->size = mincount;
 	wmb();
 	if (reload) {
+		preempt_disable();
 		load_LDT(pc);
 #ifdef CONFIG_SMP
-		preempt_disable();
 		if (current->mm->cpu_vm_mask != (1<<smp_processor_id()))
 			smp_call_function(flush_ldt, 0, 1, 1);
-		preempt_enable();
 #endif
+		preempt_enable();
 	}
 	if (oldsize) {
 		if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
diff -urP linux-2.5.63/arch/x86_64/kernel/smp.c linux-2.5.63_patched/arch/x86_64/kernel/smp.c
--- linux-2.5.63/arch/x86_64/kernel/smp.c	Mon Feb 24 20:05:13 2003
+++ linux-2.5.63_patched/arch/x86_64/kernel/smp.c	Mon Feb 24 23:02:43 2003
@@ -328,7 +328,7 @@
 	preempt_enable();
 }
 
-static inline void do_flush_tlb_all_local(void)
+static void do_flush_tlb_all(void* info)
 {
 	unsigned long cpu = smp_processor_id();
 
@@ -337,18 +337,9 @@
 		leave_mm(cpu);
 }
 
-static void flush_tlb_all_ipi(void* info)
-{
-	do_flush_tlb_all_local();
-}
-
 void flush_tlb_all(void)
 {
-	preempt_disable();
-	smp_call_function (flush_tlb_all_ipi,0,1,1);
-
-	do_flush_tlb_all_local();
-	preempt_enable();
+	on_each_cpu(do_flush_tlb_all, 0, 1, 1);
 }
 
 void smp_kdb_stop(void)
diff -urP linux-2.5.63/arch/x86_64/mm/pageattr.c linux-2.5.63_patched/arch/x86_64/mm/pageattr.c
--- linux-2.5.63/arch/x86_64/mm/pageattr.c	Mon Feb 24 20:05:32 2003
+++ linux-2.5.63_patched/arch/x86_64/mm/pageattr.c	Mon Feb 24 23:02:43 2003
@@ -123,12 +123,7 @@
 
 static inline void flush_map(unsigned long address)
 {	
-	preempt_disable();
-#ifdef CONFIG_SMP 
-	smp_call_function(flush_kernel_map, (void *)address, 1, 1);
-#endif	
-	flush_kernel_map((void *)address);
-	preempt_enable();
+	on_each_cpu(flush_kernel_map, (void *)address, 1, 1);
 }
 
 struct deferred_page { 
diff -urP linux-2.5.63/drivers/char/agp/agp.h linux-2.5.63_patched/drivers/char/agp/agp.h
--- linux-2.5.63/drivers/char/agp/agp.h	Mon Feb 24 20:05:29 2003
+++ linux-2.5.63_patched/drivers/char/agp/agp.h	Mon Feb 24 23:02:43 2003
@@ -42,9 +42,8 @@
 
 static void __attribute__((unused)) global_cache_flush(void)
 {
-	if (smp_call_function(ipi_handler, NULL, 1, 1) != 0)
+	if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0)
 		panic(PFX "timed out waiting for the other CPUs!\n");
-	flush_agp_cache();
 }
 #else
 static inline void global_cache_flush(void)
diff -urP linux-2.5.63/drivers/s390/char/sclp.c linux-2.5.63_patched/drivers/s390/char/sclp.c
--- linux-2.5.63/drivers/s390/char/sclp.c	Mon Feb 24 20:05:35 2003
+++ linux-2.5.63_patched/drivers/s390/char/sclp.c	Mon Feb 24 23:02:43 2003
@@ -481,8 +481,7 @@
 do_machine_quiesce(void)
 {
 	cpu_quiesce_map = cpu_online_map;
-	smp_call_function(do_load_quiesce_psw, NULL, 0, 0);
-	do_load_quiesce_psw(NULL);
+	on_each_cpu(do_load_quiesce_psw, NULL, 0, 0);
 }
 #else
 static void
diff -urP linux-2.5.63/fs/buffer.c linux-2.5.63_patched/fs/buffer.c
--- linux-2.5.63/fs/buffer.c	Mon Feb 24 20:05:34 2003
+++ linux-2.5.63_patched/fs/buffer.c	Mon Feb 24 23:02:43 2003
@@ -1403,10 +1403,7 @@
 	
 static void invalidate_bh_lrus(void)
 {
-	preempt_disable();
-	invalidate_bh_lru(NULL);
-	smp_call_function(invalidate_bh_lru, NULL, 1, 1);
-	preempt_enable();
+	on_each_cpu(invalidate_bh_lru, NULL, 1, 1);
 }
 
 void set_bh_page(struct buffer_head *bh,
diff -urP linux-2.5.63/include/asm-parisc/cacheflush.h linux-2.5.63_patched/include/asm-parisc/cacheflush.h
--- linux-2.5.63/include/asm-parisc/cacheflush.h	Mon Feb 24 20:05:47 2003
+++ linux-2.5.63_patched/include/asm-parisc/cacheflush.h	Mon Feb 24 23:02:43 2003
@@ -25,16 +25,10 @@
 
 extern void flush_cache_all_local(void);
 
-#ifdef CONFIG_SMP
 static inline void flush_cache_all(void)
 {
-	smp_call_function((void (*)(void *))flush_cache_all_local, NULL, 1, 1);
-	flush_cache_all_local();
+	on_each_cpu((void (*)(void *))flush_cache_all_local, NULL, 1, 1);
 }
-#else
-#define flush_cache_all flush_cache_all_local
-#endif
-
 
 /* The following value needs to be tuned and probably scaled with the
  * cache size.
diff -urP linux-2.5.63/include/linux/smp.h linux-2.5.63_patched/include/linux/smp.h
--- linux-2.5.63/include/linux/smp.h	Mon Feb 24 20:05:33 2003
+++ linux-2.5.63_patched/include/linux/smp.h	Mon Feb 24 23:02:44 2003
@@ -10,9 +10,10 @@
 
 #ifdef CONFIG_SMP
 
+#include <linux/preempt.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
-#include <linux/threads.h>
+#include <linux/thread_info.h>
 #include <asm/smp.h>
 #include <asm/bug.h>
 
@@ -54,6 +55,25 @@
 			      int retry, int wait);
 
 /*
+ * Call a function on all processors
+ */
+static inline int on_each_cpu(void (*func) (void *info), void *info,
+			      int retry, int wait)
+{
+	int ret = 0;
+
+	preempt_disable();
+
+	if(num_online_cpus() > 1)
+		ret = smp_call_function(func, info, retry, wait);
+	func(info);
+
+	preempt_enable();
+
+	return ret;
+}
+
+/*
  * True once the per process idle is forked
  */
 extern int smp_threads_ready;
@@ -96,6 +116,7 @@
 #define hard_smp_processor_id()			0
 #define smp_threads_ready			1
 #define smp_call_function(func,info,retry,wait)	({ 0; })
+#define on_each_cpu(func,info,retry,wait)	({ func(info); 0; })
 static inline void smp_send_reschedule(int cpu) { }
 static inline void smp_send_reschedule_all(void) { }
 #define cpu_online_map				1
diff -urP linux-2.5.63/mm/slab.c linux-2.5.63_patched/mm/slab.c
--- linux-2.5.63/mm/slab.c	Mon Feb 24 20:05:39 2003
+++ linux-2.5.63_patched/mm/slab.c	Mon Feb 24 23:02:44 2003
@@ -1116,12 +1116,16 @@
 static void smp_call_function_all_cpus(void (*func) (void *arg), void *arg)
 {
 	check_irq_on();
+	preempt_disable();
+
 	local_irq_disable();
 	func(arg);
 	local_irq_enable();
 
 	if (smp_call_function(func, arg, 1, 1))
 		BUG();
+
+	preempt_enable();
 }
 
 static void free_block (kmem_cache_t* cachep, void** objpp, int len);

[-- Attachment #2: signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread
* Re: [PATCH][2.5] replace flush_map() in arch/i386/mm/pageattr.c w ith flush_tlb_all()
@ 2003-02-21 14:20 Dave Jones
  2003-02-21 17:36 ` Dave Jones
  0 siblings, 1 reply; 14+ messages in thread
From: Dave Jones @ 2003-02-21 14:20 UTC (permalink / raw)
  To: Thomas Schlichter; +Cc: Hugh Dickins, Andrew Morton, Linux Kernel

On Fri, Feb 21, 2003 at 01:42:12PM +0100, Thomas Schlichter wrote:

 > > No.  All that does is make sure that the cpu you start out on is
 > > flushed, once or twice, and the cpu you end up on may be missed.
 > > Use preempt_disable and preempt_enable.
 > 
 > Oh, you are right! I think I am totally stupid this morning...!
 > Now finally I hope this is the correct patch...

That would appear to do what you want, but its an ugly construct to
be repeating everywhere that wants to call a function on all CPUs.
It would probably clean things up a lot if we had a function to do..

static inline void on_each_cpu(void *func)
{      
#ifdef CONFIG_SMP
	preempt_disable();
	smp_call_function(func, NULL, 1, 1);
	func(NULL);
	preempt_enable();
#else
	func(NULL);
#endif
}

Bluesmoke and agpgart could both use this to cleanup some mess,
and no doubt there are others

Comments?

		Dave

-- 
| Dave Jones.        http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2003-02-26 18:59 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-02-25 18:08 [PATCH][2.5] fix preempt-issues with smp_call_function() Thomas Schlichter
2003-02-26  9:27 ` Andrew Morton
2003-02-26 10:37 ` Dave Jones
2003-02-26  9:54   ` Andrew Morton
2003-02-26 10:14     ` Thomas Schlichter
2003-02-26 11:19     ` Dave Jones
2003-02-26 10:28       ` Andrew Morton
2003-02-26 10:52         ` Thomas Schlichter
2003-02-26 11:28         ` Dave Jones
2003-02-26 13:39         ` Alan Cox
2003-02-26 18:47           ` Andrew Morton
2003-02-26 20:11             ` Alan Cox
2003-02-26 16:00         ` Martin J. Bligh
  -- strict thread matches above, loose matches on Subject: below --
2003-02-21 14:20 [PATCH][2.5] replace flush_map() in arch/i386/mm/pageattr.c w ith flush_tlb_all() Dave Jones
2003-02-21 17:36 ` Dave Jones
2003-02-22  3:23   ` [PATCH][2.5] fix preempt-issues with smp_call_function() Thomas Schlichter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox