sysctl equivalent to "idle=poll"

From: Ian Pilcher
Date: Fri Jan 02 2004 - 01:25:07 EST


This patch against 2.4.23 adds an x86 sysctl,
/proc/sys/kernel/idle_poll, which allows idle behavior to be toggled
between polling and using HLT instructions.

Since this is the first time I've ever messed with kernel code, I'd
appreciate it if those more knowledgeable can give it a quick glance and
let me know if I've made any particularly obvious errors. For example,
should I be doing something to ensure that the value of pm_idle_poll is
actually read from memory in default_idle? (sysctl.c doesn't like it if
I just make pm_idle_poll volatile.)

Thanks!
--
========================================================================
Ian Pilcher i.pilcher@xxxxxxxxxxx
========================================================================
diff -ur linux-2.4.23-orig/arch/i386/kernel/process.c linux-2.4.23/arch/i386/kernel/process.c
--- linux-2.4.23-orig/arch/i386/kernel/process.c 2004-01-01 22:11:19.000000000 -0600
+++ linux-2.4.23/arch/i386/kernel/process.c 2004-01-01 22:31:57.000000000 -0600
@@ -62,6 +62,12 @@
void (*pm_idle)(void);

/*
+ * Use polling instead of HLT instructions? (Has no effect if pm_idle is over-
+ * ridden by APM, ACPI, etc.)
+ */
+int pm_idle_poll = 0;
+
+/*
* Power off function, if any
*/
void (*pm_power_off)(void);
@@ -77,10 +83,9 @@
}

/*
- * We use this if we don't have any better
- * idle routine..
+ * Idle using HLT instructions; saves power & keeps cpu's cool.
*/
-void default_idle(void)
+static void hlt_idle(void)
{
if (current_cpu_data.hlt_works_ok && !hlt_counter) {
__cli();
@@ -118,6 +123,18 @@
}

/*
+ * Default idle routine; can be overridden by APM, ACPI, etc. (See cpu_idle &
+ * pm_idle.)
+ */
+void default_idle(void)
+{
+ if (pm_idle_poll)
+ poll_idle();
+ else
+ hlt_idle();
+}
+
+/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
* low exit latency (ie sit in a loop waiting for
@@ -145,7 +162,7 @@
{
if (!strncmp(str, "poll", 4)) {
printk("using polling idle threads.\n");
- pm_idle = poll_idle;
+ pm_idle_poll = 1;
}

return 1;
diff -ur linux-2.4.23-orig/include/linux/pm.h linux-2.4.23/include/linux/pm.h
--- linux-2.4.23-orig/include/linux/pm.h 2004-01-01 22:11:01.000000000 -0600
+++ linux-2.4.23/include/linux/pm.h 2004-01-01 22:31:18.000000000 -0600
@@ -185,6 +185,10 @@

#endif /* CONFIG_PM */

+#ifdef CONFIG_X86
+extern int pm_idle_poll;
+#endif
+
extern void (*pm_idle)(void);
extern void (*pm_power_off)(void);

diff -ur linux-2.4.23-orig/include/linux/sysctl.h linux-2.4.23/include/linux/sysctl.h
--- linux-2.4.23-orig/include/linux/sysctl.h 2004-01-01 22:11:01.000000000 -0600
+++ linux-2.4.23/include/linux/sysctl.h 2004-01-01 22:19:07.000000000 -0600
@@ -128,6 +128,7 @@
KERN_PPC_L3CR=57, /* l3cr register on PPC */
KERN_EXCEPTION_TRACE=58, /* boolean: exception trace */
KERN_CORE_SETUID=59, /* int: set to allow core dumps of setuid apps */
+ KERN_IDLE_POLL=60, /* boolean: use polling for idle threads? */
};


diff -ur linux-2.4.23-orig/kernel/sysctl.c linux-2.4.23/kernel/sysctl.c
--- linux-2.4.23-orig/kernel/sysctl.c 2004-01-01 22:11:01.000000000 -0600
+++ linux-2.4.23/kernel/sysctl.c 2004-01-01 22:20:01.000000000 -0600
@@ -31,6 +31,7 @@
#include <linux/sysrq.h>
#include <linux/highuid.h>
#include <linux/swap.h>
+#include <linux/pm.h>

#include <asm/uaccess.h>

@@ -275,6 +276,10 @@
{KERN_EXCEPTION_TRACE,"exception-trace",
&exception_trace,sizeof(int),0644,NULL,&proc_dointvec},
#endif
+#ifdef CONFIG_X86
+ {KERN_IDLE_POLL,"idle_poll",
+ &pm_idle_poll,sizeof(int),0644,NULL,&proc_dointvec},
+#endif
{0}
};