svn commit: r242905 - in projects/calloutng/sys: amd64/amd64 dev/acpica i386/i386 ia64/ia64 kern pc98/pc98 powerpc/powerpc sys

Alexander Motin mav at FreeBSD.org
Mon Nov 12 07:25:48 UTC 2012


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 <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/kdb.h>
 #include <sys/ktr.h>
@@ -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;


More information about the svn-src-projects mailing list