From owner-svn-src-projects@FreeBSD.ORG Mon Nov 12 07:25:48 2012 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 2B706B6F; Mon, 12 Nov 2012 07:25:48 +0000 (UTC) (envelope-from mav@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 061538FC13; Mon, 12 Nov 2012 07:25:48 +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 qAC7Plut075449; Mon, 12 Nov 2012 07:25:47 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qAC7PlMe075439; Mon, 12 Nov 2012 07:25:47 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201211120725.qAC7PlMe075439@svn.freebsd.org> From: Alexander Motin Date: Mon, 12 Nov 2012 07:25:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r242905 - in projects/calloutng/sys: amd64/amd64 dev/acpica i386/i386 ia64/ia64 kern pc98/pc98 powerpc/powerpc sys X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Nov 2012 07:25:48 -0000 Author: mav Date: Mon Nov 12 07:25:47 2012 New Revision: 242905 URL: http://svnweb.freebsd.org/changeset/base/242905 Log: When CPU becomes idle, cpu_idleclock() calculates time till the next timer event to reprogram the hardware timer. Return that time in microseconds to the caller and pass it to acpi_cpu_idle(), where it can be used as one more factor (quite precise one) to estimate further sleep time and choose optimal sleep state. With this change, depending on hardware, synthetic tests show up to double improvement in callout precision when deeper sleep states are in use. Also fix minor build issues on UP systems. Modified: projects/calloutng/sys/amd64/amd64/machdep.c projects/calloutng/sys/dev/acpica/acpi_cpu.c projects/calloutng/sys/i386/i386/machdep.c projects/calloutng/sys/ia64/ia64/machdep.c projects/calloutng/sys/kern/kern_clocksource.c projects/calloutng/sys/kern/kern_timeout.c projects/calloutng/sys/pc98/pc98/machdep.c projects/calloutng/sys/powerpc/powerpc/cpu.c projects/calloutng/sys/sys/proc.h projects/calloutng/sys/sys/systm.h Modified: projects/calloutng/sys/amd64/amd64/machdep.c ============================================================================== --- projects/calloutng/sys/amd64/amd64/machdep.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/amd64/amd64/machdep.c Mon Nov 12 07:25:47 2012 (r242905) @@ -658,7 +658,7 @@ cpu_halt(void) halt(); } -void (*cpu_idle_hook)(void) = NULL; /* ACPI idle hook. */ +void (*cpu_idle_hook)(int) = NULL; /* ACPI idle hook. */ static int cpu_ident_amdc1e = 0; /* AMD C1E supported. */ static int idle_mwait = 1; /* Use MONITOR/MWAIT for short idle. */ TUNABLE_INT("machdep.idle_mwait", &idle_mwait); @@ -670,7 +670,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwai #define STATE_SLEEPING 0x2 static void -cpu_idle_acpi(int busy) +cpu_idle_acpi(int us) { int *state; @@ -682,14 +682,14 @@ cpu_idle_acpi(int busy) if (sched_runnable()) enable_intr(); else if (cpu_idle_hook) - cpu_idle_hook(); + cpu_idle_hook(us); else __asm __volatile("sti; hlt"); *state = STATE_RUNNING; } static void -cpu_idle_hlt(int busy) +cpu_idle_hlt(int us) { int *state; @@ -730,7 +730,7 @@ cpu_idle_hlt(int busy) #define MWAIT_C4 0x30 static void -cpu_idle_mwait(int busy) +cpu_idle_mwait(int us) { int *state; @@ -753,7 +753,7 @@ cpu_idle_mwait(int busy) } static void -cpu_idle_spin(int busy) +cpu_idle_spin(int us) { int *state; int i; @@ -808,6 +808,7 @@ void cpu_idle(int busy) { uint64_t msr; + int us = -1; CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", busy, curcpu); @@ -825,7 +826,7 @@ cpu_idle(int busy) /* If we have time - switch timers into idle mode. */ if (!busy) { critical_enter(); - cpu_idleclock(); + us = cpu_idleclock(); } /* Apply AMD APIC timer C1E workaround. */ @@ -836,7 +837,7 @@ cpu_idle(int busy) } /* Call main idle method. */ - cpu_idle_fn(busy); + cpu_idle_fn(us); /* Switch timers mack into active mode. */ if (!busy) { Modified: projects/calloutng/sys/dev/acpica/acpi_cpu.c ============================================================================== --- projects/calloutng/sys/dev/acpica/acpi_cpu.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/dev/acpica/acpi_cpu.c Mon Nov 12 07:25:47 2012 (r242905) @@ -169,7 +169,7 @@ static int acpi_cpu_cx_cst(struct acpi_c static void acpi_cpu_startup(void *arg); static void acpi_cpu_startup_cx(struct acpi_cpu_softc *sc); static void acpi_cpu_cx_list(struct acpi_cpu_softc *sc); -static void acpi_cpu_idle(void); +static void acpi_cpu_idle(int us); static void acpi_cpu_notify(ACPI_HANDLE h, UINT32 notify, void *context); static int acpi_cpu_quirks(void); static int acpi_cpu_usage_sysctl(SYSCTL_HANDLER_ARGS); @@ -918,7 +918,7 @@ acpi_cpu_startup_cx(struct acpi_cpu_soft * interrupts are re-enabled. */ static void -acpi_cpu_idle() +acpi_cpu_idle(int us) { struct acpi_cpu_softc *sc; struct acpi_cx *cx_next; @@ -944,13 +944,14 @@ acpi_cpu_idle() } /* Find the lowest state that has small enough latency. */ + us = min(us, sc->cpu_prev_sleep); cx_next_idx = 0; if (cpu_disable_deep_sleep) i = min(sc->cpu_cx_lowest, sc->cpu_non_c3); else i = sc->cpu_cx_lowest; for (; i >= 0; i--) { - if (sc->cpu_cx_states[i].trans_lat * 3 <= sc->cpu_prev_sleep) { + if (sc->cpu_cx_states[i].trans_lat * 3 <= us) { cx_next_idx = i; break; } Modified: projects/calloutng/sys/i386/i386/machdep.c ============================================================================== --- projects/calloutng/sys/i386/i386/machdep.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/i386/i386/machdep.c Mon Nov 12 07:25:47 2012 (r242905) @@ -1220,7 +1220,7 @@ cpu_halt(void) int scheduler_running; static void -cpu_idle_hlt(int busy) +cpu_idle_hlt(int us) { scheduler_running = 1; @@ -1241,7 +1241,7 @@ cpu_halt(void) #endif -void (*cpu_idle_hook)(void) = NULL; /* ACPI idle hook. */ +void (*cpu_idle_hook)(int) = NULL; /* ACPI idle hook. */ static int cpu_ident_amdc1e = 0; /* AMD C1E supported. */ static int idle_mwait = 1; /* Use MONITOR/MWAIT for short idle. */ TUNABLE_INT("machdep.idle_mwait", &idle_mwait); @@ -1253,7 +1253,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwai #define STATE_SLEEPING 0x2 static void -cpu_idle_acpi(int busy) +cpu_idle_acpi(int us) { int *state; @@ -1265,7 +1265,7 @@ cpu_idle_acpi(int busy) if (sched_runnable()) enable_intr(); else if (cpu_idle_hook) - cpu_idle_hook(); + cpu_idle_hook(us); else __asm __volatile("sti; hlt"); *state = STATE_RUNNING; @@ -1273,7 +1273,7 @@ cpu_idle_acpi(int busy) #ifndef XEN static void -cpu_idle_hlt(int busy) +cpu_idle_hlt(int us) { int *state; @@ -1315,7 +1315,7 @@ cpu_idle_hlt(int busy) #define MWAIT_C4 0x30 static void -cpu_idle_mwait(int busy) +cpu_idle_mwait(int us) { int *state; @@ -1338,7 +1338,7 @@ cpu_idle_mwait(int busy) } static void -cpu_idle_spin(int busy) +cpu_idle_spin(int us) { int *state; int i; @@ -1399,6 +1399,7 @@ cpu_idle(int busy) #ifndef XEN uint64_t msr; #endif + int us = -1; CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", busy, curcpu); @@ -1418,7 +1419,7 @@ cpu_idle(int busy) /* If we have time - switch timers into idle mode. */ if (!busy) { critical_enter(); - cpu_idleclock(); + us = cpu_idleclock(); } #ifndef XEN @@ -1431,7 +1432,7 @@ cpu_idle(int busy) #endif /* Call main idle method. */ - cpu_idle_fn(busy); + cpu_idle_fn(us); /* Switch timers mack into active mode. */ if (!busy) { Modified: projects/calloutng/sys/ia64/ia64/machdep.c ============================================================================== --- projects/calloutng/sys/ia64/ia64/machdep.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/ia64/ia64/machdep.c Mon Nov 12 07:25:47 2012 (r242905) @@ -155,7 +155,7 @@ extern vm_offset_t ksym_start, ksym_end; struct msgbuf *msgbufp = NULL; /* Other subsystems (e.g., ACPI) can hook this later. */ -void (*cpu_idle_hook)(void) = NULL; +void (*cpu_idle_hook)(int) = NULL; struct kva_md_info kmi; @@ -392,10 +392,11 @@ void cpu_idle(int busy) { register_t ie; + int us = -1; if (!busy) { critical_enter(); - cpu_idleclock(); + us = cpu_idleclock(); } ie = intr_disable(); @@ -404,7 +405,7 @@ cpu_idle(int busy) if (sched_runnable()) ia64_enable_intr(); else if (cpu_idle_hook != NULL) { - (*cpu_idle_hook)(); + (*cpu_idle_hook)(us); /* The hook must enable interrupts! */ } else { ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0); Modified: projects/calloutng/sys/kern/kern_clocksource.c ============================================================================== --- projects/calloutng/sys/kern/kern_clocksource.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/kern/kern_clocksource.c Mon Nov 12 07:25:47 2012 (r242905) @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -771,7 +772,7 @@ cpu_stopprofclock(void) /* * Switch to idle mode (all ticks handled). */ -void +int cpu_idleclock(void) { struct bintime now, t; @@ -783,7 +784,7 @@ cpu_idleclock(void) || curcpu == CPU_FIRST() #endif ) - return; + return (-1); state = DPCPU_PTR(timerstate); if (periodic) now = state->now; @@ -799,6 +800,9 @@ cpu_idleclock(void) if (!periodic) loadtimer(&now, 0); ET_HW_UNLOCK(state); + bintime_sub(&t, &now); + return (t.sec > (INT_MAX >> 20) ? INT_MAX : + ((t.sec < 0) ? 0 : ((t.sec << 20) + (t.frac >> 44)))); } /* @@ -913,7 +917,9 @@ cpu_new_callout(int cpu, struct bintime /* Otherwise make other CPU to reprogram it. */ state->handle = 1; ET_HW_UNLOCK(state); +#ifdef SMP ipi_cpu(cpu, IPI_HARDCLOCK); +#endif } /* Modified: projects/calloutng/sys/kern/kern_timeout.c ============================================================================== --- projects/calloutng/sys/kern/kern_timeout.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/kern/kern_timeout.c Mon Nov 12 07:25:47 2012 (r242905) @@ -632,12 +632,12 @@ softclock_call_cc(struct callout *c, str void *c_arg; struct lock_class *class; struct lock_object *c_lock; - int c_flags, flags, sharedlock; + int c_flags, sharedlock; #ifdef SMP struct callout_cpu *new_cc; void (*new_func)(void *); void *new_arg; - int new_cpu; + int flags, new_cpu; struct bintime new_time; #endif #ifdef DIAGNOSTIC Modified: projects/calloutng/sys/pc98/pc98/machdep.c ============================================================================== --- projects/calloutng/sys/pc98/pc98/machdep.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/pc98/pc98/machdep.c Mon Nov 12 07:25:47 2012 (r242905) @@ -1144,7 +1144,7 @@ SYSCTL_INT(_machdep, OID_AUTO, idle_mwai #define STATE_SLEEPING 0x2 static void -cpu_idle_hlt(int busy) +cpu_idle_hlt(int us) { int *state; @@ -1185,7 +1185,7 @@ cpu_idle_hlt(int busy) #define MWAIT_C4 0x30 static void -cpu_idle_mwait(int busy) +cpu_idle_mwait(int us) { int *state; @@ -1208,7 +1208,7 @@ cpu_idle_mwait(int busy) } static void -cpu_idle_spin(int busy) +cpu_idle_spin(int us) { int *state; int i; @@ -1233,6 +1233,7 @@ void (*cpu_idle_fn)(int) = cpu_idle_hlt; void cpu_idle(int busy) { + int us = -1; CTR2(KTR_SPARE2, "cpu_idle(%d) at %d", busy, curcpu); @@ -1250,11 +1251,11 @@ cpu_idle(int busy) /* If we have time - switch timers into idle mode. */ if (!busy) { critical_enter(); - cpu_idleclock(); + us = cpu_idleclock(); } /* Call main idle method. */ - cpu_idle_fn(busy); + cpu_idle_fn(us); /* Switch timers mack into active mode. */ if (!busy) { Modified: projects/calloutng/sys/powerpc/powerpc/cpu.c ============================================================================== --- projects/calloutng/sys/powerpc/powerpc/cpu.c Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/powerpc/powerpc/cpu.c Mon Nov 12 07:25:47 2012 (r242905) @@ -79,9 +79,9 @@ static void cpu_970_setup(int cpuid, uin static void cpu_booke_setup(int cpuid, uint16_t vers); int powerpc_pow_enabled; -void (*cpu_idle_hook)(void) = NULL; -static void cpu_idle_60x(void); -static void cpu_idle_booke(void); +void (*cpu_idle_hook)(int) = NULL; +static void cpu_idle_60x(int); +static void cpu_idle_booke(int); struct cputab { const char *name; @@ -516,6 +516,7 @@ cpu_feature_bit(SYSCTL_HANDLER_ARGS) void cpu_idle(int busy) { + int us = -1; #ifdef INVARIANTS if ((mfmsr() & PSL_EE) != PSL_EE) { @@ -531,9 +532,9 @@ cpu_idle(int busy) if (cpu_idle_hook != NULL) { if (!busy) { critical_enter(); - cpu_idleclock(); + us = cpu_idleclock(); } - cpu_idle_hook(); + cpu_idle_hook(us); if (!busy) { cpu_activeclock(); critical_exit(); @@ -551,7 +552,7 @@ cpu_idle_wakeup(int cpu) } static void -cpu_idle_60x(void) +cpu_idle_60x(int us) { register_t msr; uint16_t vers; @@ -586,7 +587,7 @@ cpu_idle_60x(void) } static void -cpu_idle_booke(void) +cpu_idle_booke(int us) { register_t msr; Modified: projects/calloutng/sys/sys/proc.h ============================================================================== --- projects/calloutng/sys/sys/proc.h Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/sys/proc.h Mon Nov 12 07:25:47 2012 (r242905) @@ -907,7 +907,7 @@ void tidhash_add(struct thread *); void tidhash_remove(struct thread *); void cpu_idle(int); int cpu_idle_wakeup(int); -extern void (*cpu_idle_hook)(void); /* Hook to machdep CPU idler. */ +extern void (*cpu_idle_hook)(int); /* Hook to machdep CPU idler. */ void cpu_switch(struct thread *, struct thread *, struct mtx *); void cpu_throw(struct thread *, struct thread *) __dead2; void unsleep(struct thread *); Modified: projects/calloutng/sys/sys/systm.h ============================================================================== --- projects/calloutng/sys/sys/systm.h Mon Nov 12 06:15:54 2012 (r242904) +++ projects/calloutng/sys/sys/systm.h Mon Nov 12 07:25:47 2012 (r242905) @@ -262,7 +262,7 @@ void startprofclock(struct proc *); void stopprofclock(struct proc *); void cpu_startprofclock(void); void cpu_stopprofclock(void); -void cpu_idleclock(void); +int cpu_idleclock(void); void cpu_activeclock(void); extern int cpu_can_deep_sleep; extern int cpu_disable_deep_sleep;