Name: Check Calls to smp_processor_id() Author: Rusty Russell Status: Experimental D: This patch inserts checks in smp_processor_id(), which doesn't have much D: meaning when preemption is active. It also includes various fixes for D: the problems it finds. diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/arch/i386/lib/delay.c working-2.6.0-smp_processor_id/arch/i386/lib/delay.c --- linux-2.6.0/arch/i386/lib/delay.c 2003-09-22 10:23:08.000000000 +1000 +++ working-2.6.0-smp_processor_id/arch/i386/lib/delay.c 2003-12-23 23:20:30.000000000 +1100 @@ -31,10 +31,12 @@ void __delay(unsigned long loops) inline void __const_udelay(unsigned long xloops) { int d0; + preempt_disable(); __asm__("mull %0" :"=d" (xloops), "=&a" (d0) :"1" (xloops),"0" (current_cpu_data.loops_per_jiffy)); __delay(xloops * HZ); + preempt_enable(); } void __udelay(unsigned long usecs) diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/include/asm-i386/smp.h working-2.6.0-smp_processor_id/include/asm-i386/smp.h --- linux-2.6.0/include/asm-i386/smp.h 2003-09-22 10:28:12.000000000 +1000 +++ working-2.6.0-smp_processor_id/include/asm-i386/smp.h 2003-12-23 18:44:10.000000000 +1100 @@ -50,7 +50,7 @@ extern void zap_low_mappings (void); * from the initial startup. We map APIC_BASE very early in page_setup(), * so this is correct in the x86 case. */ -#define smp_processor_id() (current_thread_info()->cpu) +#define __get_cpu() (current_thread_info()->cpu) extern cpumask_t cpu_callout_map; diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/include/linux/smp.h working-2.6.0-smp_processor_id/include/linux/smp.h --- linux-2.6.0/include/linux/smp.h 2003-09-22 10:27:37.000000000 +1000 +++ working-2.6.0-smp_processor_id/include/linux/smp.h 2003-12-23 18:52:24.000000000 +1100 @@ -90,6 +90,13 @@ extern int smp_threads_ready; */ void smp_prepare_boot_cpu(void); +#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP +/* Far too hard to inline this: #include hell. */ +extern unsigned int smp_processor_id(void); +#else +#define smp_processor_id() __get_cpu() +#endif /* CONFIG_DEBUG_SPINLOCK_SLEEP */ + #else /* !SMP */ /* diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/kernel/module.c working-2.6.0-smp_processor_id/kernel/module.c --- linux-2.6.0/kernel/module.c 2003-11-24 15:42:33.000000000 +1100 +++ working-2.6.0-smp_processor_id/kernel/module.c 2003-12-24 18:22:13.000000000 +1100 @@ -386,8 +386,8 @@ static void module_unload_init(struct mo INIT_LIST_HEAD(&mod->modules_which_use_me); for (i = 0; i < NR_CPUS; i++) local_set(&mod->ref[i].count, 0); - /* Hold reference count during initialization. */ - local_set(&mod->ref[smp_processor_id()].count, 1); + /* Hold reference count during initialization: who cares which one. */ + local_set(&mod->ref[__get_cpu()].count, 1); /* Backwards compatibility macros put refcount during init. */ mod->waiter = current; } diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/kernel/sched.c working-2.6.0-smp_processor_id/kernel/sched.c --- linux-2.6.0/kernel/sched.c 2003-12-18 15:53:33.000000000 +1100 +++ working-2.6.0-smp_processor_id/kernel/sched.c 2003-12-24 18:21:58.000000000 +1100 @@ -2322,7 +2322,13 @@ EXPORT_SYMBOL(yield); */ void io_schedule(void) { - struct runqueue *rq = this_rq(); + /* This usage is actually OK if we get preempted, but suppress + * warning --RR */ + struct runqueue *rq; + + preempt_disable(); + rq = this_rq(); + preempt_enable(); atomic_inc(&rq->nr_iowait); schedule(); @@ -2867,6 +2873,26 @@ void __might_sleep(char *file, int line) #endif } EXPORT_SYMBOL(__might_sleep); + +unsigned int smp_processor_id(void) +{ + static int last; + + if (system_running) { + preempt_disable(); + if (preempt_count() == 1 + && !irqs_disabled() + && cpus_weight(current->cpus_allowed) != 1 + && current != this_rq()->idle) { + WARN_ON(jiffies > last + HZ); + last = jiffies; + } + preempt_enable(); + } + + return __get_cpu(); +} +EXPORT_SYMBOL(smp_processor_id); #endif diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.6.0/kernel/softirq.c working-2.6.0-smp_processor_id/kernel/softirq.c --- linux-2.6.0/kernel/softirq.c 2003-10-09 18:03:02.000000000 +1000 +++ working-2.6.0-smp_processor_id/kernel/softirq.c 2003-12-24 18:13:35.000000000 +1100 @@ -117,11 +117,11 @@ EXPORT_SYMBOL(do_softirq); void local_bh_enable(void) { - __local_bh_enable(); - WARN_ON(irqs_disabled()); if (unlikely(!in_interrupt() && local_softirq_pending())) invoke_softirq(); + __local_bh_enable(); + WARN_ON(irqs_disabled()); preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable);