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