From owner-svn-src-all@FreeBSD.ORG Fri Nov 23 15:44:05 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id EF211123; Fri, 23 Nov 2012 15:44:04 +0000 (UTC) (envelope-from nyan@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id D48E78FC08; Fri, 23 Nov 2012 15:44:04 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qANFi4vc043206; Fri, 23 Nov 2012 15:44:04 GMT (envelope-from nyan@svn.freebsd.org) Received: (from nyan@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qANFi4cH043205; Fri, 23 Nov 2012 15:44:04 GMT (envelope-from nyan@svn.freebsd.org) Message-Id: <201211231544.qANFi4cH043205@svn.freebsd.org> From: Takahashi Yoshihiro Date: Fri, 23 Nov 2012 15:44:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r243461 - stable/8/sys/pc98/pc98 X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Nov 2012 15:44:05 -0000 Author: nyan Date: Fri Nov 23 15:44:04 2012 New Revision: 243461 URL: http://svnweb.freebsd.org/changeset/base/243461 Log: MFC: r225977, r242867, r242868, r242869 MFi386: r225936 Add some improvements in the idle table callbacks: - Replace instances of manual assembly instruction "hlt" call with halt() function calling. - In cpu_idle_mwait() avoid races in check to sched_runnable() using the same pattern used in cpu_idle_hlt() with the 'hlt' instruction. - Add comments explaining the logic behind the pattern used in cpu_idle_hlt() and other idle callbacks. MFi386: r211924 Register an interrupt vector for DTrace return probes. Fix some KASSERTs. They are missing changes from r208833, r227394 and r227442. Reduce diffs against i386. Modified: stable/8/sys/pc98/pc98/machdep.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/pc98/ (props changed) Modified: stable/8/sys/pc98/pc98/machdep.c ============================================================================== --- stable/8/sys/pc98/pc98/machdep.c Fri Nov 23 15:42:25 2012 (r243460) +++ stable/8/sys/pc98/pc98/machdep.c Fri Nov 23 15:44:04 2012 (r243461) @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include "opt_maxmem.h" #include "opt_npx.h" #include "opt_perfmon.h" +#include "opt_kdtrace.h" #include #include @@ -1122,7 +1123,7 @@ void cpu_halt(void) { for (;;) - __asm__ ("hlt"); + halt(); } static int idle_mwait = 1; /* Use MONITOR/MWAIT for short idle. */ @@ -1141,9 +1142,22 @@ cpu_idle_hlt(int busy) state = (int *)PCPU_PTR(monitorbuf); *state = STATE_SLEEPING; + /* - * We must absolutely guarentee that hlt is the next instruction - * after sti or we introduce a timing window. + * Since we may be in a critical section from cpu_idle(), if + * an interrupt fires during that critical section we may have + * a pending preemption. If the CPU halts, then that thread + * may not execute until a later interrupt awakens the CPU. + * To handle this race, check for a runnable thread after + * disabling interrupts and immediately return if one is + * found. Also, we must absolutely guarentee that hlt is + * the next instruction after sti. This ensures that any + * interrupt that fires after the call to disable_intr() will + * immediately awaken the CPU from hlt. Finally, please note + * that on x86 this works fine because of interrupts enabled only + * after the instruction following sti takes place, while IF is set + * to 1 immediately, allowing hlt instruction to acknowledge the + * interrupt. */ disable_intr(); if (sched_runnable()) @@ -1169,11 +1183,19 @@ cpu_idle_mwait(int busy) state = (int *)PCPU_PTR(monitorbuf); *state = STATE_MWAIT; - if (!sched_runnable()) { - cpu_monitor(state, 0, 0); - if (*state == STATE_MWAIT) - cpu_mwait(0, MWAIT_C1); + + /* See comments in cpu_idle_hlt(). */ + disable_intr(); + if (sched_runnable()) { + enable_intr(); + *state = STATE_RUNNING; + return; } + cpu_monitor(state, 0, 0); + if (*state == STATE_MWAIT) + __asm __volatile("sti; mwait" : : "a" (MWAIT_C1), "c" (0)); + else + enable_intr(); *state = STATE_RUNNING; } @@ -1185,6 +1207,12 @@ cpu_idle_spin(int busy) state = (int *)PCPU_PTR(monitorbuf); *state = STATE_RUNNING; + + /* + * The sched_runnable() call is racy but as long as there is + * a loop missing it one time will have just a little impact if any + * (and it is much better than missing the check at all). + */ for (i = 0; i < 1000; i++) { if (sched_runnable()) return; @@ -1198,7 +1226,7 @@ void cpu_idle(int busy) { -#ifdef SMP +#if defined(SMP) if (mp_grab_cpu_hlt()) return; #endif @@ -1708,7 +1736,11 @@ extern inthand_t IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), - IDTVEC(xmm), IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall); + IDTVEC(xmm), +#ifdef KDTRACE_HOOKS + IDTVEC(dtrace_ret), +#endif + IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall); #ifdef DDB /* @@ -2088,6 +2120,8 @@ do_next: for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE) pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] + off); + + PT_UPDATES_FLUSH(); } void @@ -2227,6 +2261,10 @@ init386(first) GSEL(GCODE_SEL, SEL_KPL)); setidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); +#ifdef KDTRACE_HOOKS + setidt(IDT_DTRACE_RET, &IDTVEC(dtrace_ret), SDT_SYS386TGT, SEL_UPL, + GSEL(GCODE_SEL, SEL_KPL)); +#endif r_idt.rd_limit = sizeof(idt0) - 1; r_idt.rd_base = (int) idt; @@ -2563,7 +2601,8 @@ int fill_fpregs(struct thread *td, struct fpreg *fpregs) { - KASSERT(td == curthread || TD_IS_SUSPENDED(td), + KASSERT(td == curthread || TD_IS_SUSPENDED(td) || + P_SHOULDSTOP(td->td_proc), ("not suspended thread %p", td)); #ifdef DEV_NPX npxgetregs(td); @@ -2732,6 +2771,7 @@ static void fpstate_drop(struct thread *td) { + KASSERT(PCB_USER_FPU(td->td_pcb), ("fpstate_drop: kernel-owned fpu")); critical_enter(); #ifdef DEV_NPX if (PCPU_GET(fpcurthread) == td)