svn commit: r344332 - head/sys/x86/x86
Bruce Evans
bde at FreeBSD.org
Wed Feb 20 02:40:39 UTC 2019
Author: bde
Date: Wed Feb 20 02:40:38 2019
New Revision: 344332
URL: https://svnweb.freebsd.org/changeset/base/344332
Log:
Fix hangs in r341810 waiting for AP startup.
idle_td is dereferenced without thread-locking it to make its contents is
invariant, and was accessed without telling the compiler that its contents
is invariant. Some compilers optimized accesses to the supposedly invariant
contents by moving the critical checks for changes outside of the loop that
waits for changes. Fix this using atomic ops.
This bug only showed up for the following configuration: a Turion2
system, amd64 kernels, compiled by gcc, and SCHED_4BSD. clang fails
to do the optimization with all CFLAGS that I tried, because it doesn't
fully optimize the '__asm __volatile' for cpu_spinwait() although this
asm has no memory clobber. gcc only does the optimization with most
CFLAGS. I mostly used -Os with all compilers. i386 works because gcc
-m32 -Os only moves 1 or the 2 accesses outside of the loop.
Non-Turion2 systems and SCHED_ULE worked due to different timing (when
all APs start before the BP checks them outside of the loop).
Reviewed by: kib
Modified:
head/sys/x86/x86/mp_x86.c
Modified: head/sys/x86/x86/mp_x86.c
==============================================================================
--- head/sys/x86/x86/mp_x86.c Wed Feb 20 02:14:41 2019 (r344331)
+++ head/sys/x86/x86/mp_x86.c Wed Feb 20 02:40:38 2019 (r344332)
@@ -1088,8 +1088,8 @@ smp_after_idle_runnable(void *arg __unused)
for (cpu = 1; cpu < mp_ncpus; cpu++) {
idle_td = pcpu_find(cpu)->pc_idlethread;
- while (idle_td->td_lastcpu == NOCPU &&
- idle_td->td_oncpu == NOCPU)
+ while (atomic_load_int(&idle_td->td_lastcpu) == NOCPU &&
+ atomic_load_int(&idle_td->td_oncpu) == NOCPU)
cpu_spinwait();
kmem_free((vm_offset_t)bootstacks[cpu], kstack_pages *
PAGE_SIZE);
More information about the svn-src-all
mailing list