[PATCH] apm.c, 2.4.20, set_cpus_allowed for CPU 0 on SMP
[email protected] (Jim Carter) Mon, 8 Dec 2003 22:27:02 -0800 (PST)
| Newsgroups | org.kernel.vger.linux-laptop |
|---|---|
| Message-ID | <[email protected]> |
Using hyperthreading, and wanting to power off the CPU, when loading the apm.o module I intermittently got the BUG() in function apm() of ./arch/i386/kernel/apm.c where it tries to migrate to CPU 0 and fails. Shouldn't it call set_cpus_allowed() (in ./kernel/sched.c) instead of just setting current->cpus_allowed and calling schedule()? I didn't see where schedule() notices that the task is on the wrong CPU, though I could have missed it. The attached patch makes this call, and it's unconditional, so that if the thread starts out on CPU 0 but some ghost later tries to put it on another CPU, it will stay on CPU 0. Ten successive boot and "halt -p" pairs were successful in initializing the module (of course for power-off only, due to SMP) and turning off the power. Before the patch I would have expected several failures -- seems like less than half, but enough to really mess up remote administration. Comments in the code say that some APM BIOSes need to be called by CPU 0 only. There is no evidence that my BIOS does or does not require this. Administrative details: The patch is relative to 2.4.20 from SuSE Linux 8.2, which is what the testing was done on. The relevant code is identical in pristine 2.4.23 sources. Hardware is a Dell Dimension 4600 with a Pentium-4 processor (2.4 GHz, hyperthreading). Kernel is configured with SMP. James F. Carter Voice 310 825 2897 FAX 310 206 6673 UCLA-Mathnet; 6115 MSA; 405 Hilgard Ave.; Los Angeles, CA, USA 90095-1555 Email: [email protected] http://www.math.ucla.edu/~jimc (q.v. for PGP key) --- linux-2.4.20.SuSE/arch/i386/kernel/apm.c.orig 2003-03-17 07:51:20.000000000 -0800 +++ linux-2.4.20.SuSE/arch/i386/kernel/apm.c 2003-12-08 17:13:39.000000000 -0800 @@ -1716,13 +1716,12 @@ * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D. * Some bioses don't like being called from CPU != 0. * Method suggested by Ingo Molnar. + * Done unconditionally in case a ghost from the Dark Side makes the + * kernel thread migrate to another CPU later. */ - if (cpu_number_map(smp_processor_id()) != 0) { - current->cpus_allowed = 1; - schedule(); - if (unlikely(cpu_number_map(smp_processor_id()) != 0)) - BUG(); - } + set_cpus_allowed(current, 1); /*Bitmask allows only CPU 0*/ + if (unlikely(cpu_number_map(smp_processor_id()) != 0)) + BUG(); #endif if (apm_info.connection_version == 0) {