Re: 2.6.14-rt13

From: Steven Rostedt
Date: Fri Nov 18 2005 - 21:39:38 EST


On Fri, 2005-11-18 at 14:41 -0800, Fernando Lopez-Lezcano wrote:
> On Fri, 2005-11-18 at 23:07 +0100, Ingo Molnar wrote:
> > * Fernando Lopez-Lezcano <nando@xxxxxxxxxxxxxxxxxx> wrote:
> >
> > > Arghhh, at least I take this as a confirmation that the TSCs do drift
> > > and there is no workaround. It currently makes the -rt/Jack
> > > combination not very useful, at least in my tests.
> > >
> > > Is there a way to resync the TSCs?
> >
> > no reasonable way. Does idle=poll make any difference?
>
> I don't know yet, and I may never know :-) I've been running it for a
> while and so far works but that's what I thought yesterday of -rt13. It
> is not practical for normal use, it just heats the cpu unnecessarily and
> there's no way to control it other than a reboot.

Not anymore!

OK, I used this as an exercise to learn how kobject and sysfs work (I've
been putting this off for too long). So if this isn't exactly proper,
let me know :-)

Ingo, This could be a temporary patch until we come up with a better
solution. This adds /sys/kernel/idle/idle_poll, which if idle=poll is
_not_ set, it still lets you switch the machine to idle=poll on the fly,
as well as turn it off. If you have idle=poll, this doesn't even show
up.

So for example (I'm currently running it):

# cat /sys/kernel/idle/idle_poll
off
# echo 1 > /sys/kernel/idle/idle_poll
# cat /sys/kernel/idle/idle_poll on
# echo 0 > /sys/kernel/idle/idle_poll
# cat /sys/kernel/idle/idle_poll off

# echo on > /sys/kernel/idle/idle_poll
and
# echo off > /sys/kernel/idle/idle_poll
also work.

So like I said. This could be used for just those that need to have
idle=poll for running benchmarks but don't want to reboot when they are
done.

-- Steve

PS. I haven't tested to see if the idle actually changes, but it looks
pretty obvious in the code in cpu_idle:

idle = pm_idle;
if (!idle)
idle = default_idle;
if (cpu_is_offline(smp_processor_id()))
play_dead();
stop_critical_timing();
propagate_preempt_locks_value();
idle();



Index: linux-2.6.14-rt13/arch/x86_64/kernel/process.c
===================================================================
--- linux-2.6.14-rt13.orig/arch/x86_64/kernel/process.c 2005-11-15 11:12:37.000000000 -0500
+++ linux-2.6.14-rt13/arch/x86_64/kernel/process.c 2005-11-18 21:12:53.000000000 -0500
@@ -822,3 +822,104 @@
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+#ifdef CONFIG_SYSFS
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/spinlock.h>
+
+#define KERNEL_ATTR_RW(_name) \
+static struct subsys_attribute _name##_attr = \
+ __ATTR(_name, 0644, _name##_show, _name##_store)
+
+static spinlock_t idle_switch_lock = SPIN_LOCK_UNLOCKED(idle_switch_lock);
+
+static struct idlep_kobject
+{
+ struct kobject kobj;
+ int is_poll;
+ void (*idle)(void);
+} idle_kobj;
+
+static ssize_t idle_poll_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%s\n", (idle_kobj.is_poll ? "on" : "off"));
+}
+
+static ssize_t idle_poll_store(struct subsystem *subsys,
+ const char *buf, size_t len)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&idle_switch_lock, flags);
+
+ if (strncmp(buf,"1",1)==0 ||
+ (len >=2 && strncmp(buf,"on",2)==0)) {
+ if (idle_kobj.is_poll != 1) {
+ idle_kobj.is_poll = 1;
+ pm_idle = poll_idle;
+ }
+ } else if (strncmp(buf,"0",1)==0 ||
+ (len >= 3 && strncmp(buf,"off",3)==0)) {
+ if (idle_kobj.is_poll != 0) {
+ idle_kobj.is_poll = 0;
+ pm_idle = idle_kobj.idle;
+ }
+ }
+
+ spin_unlock_irqrestore(&idle_switch_lock, flags);
+
+ return len;
+}
+
+
+KERNEL_ATTR_RW(idle_poll);
+
+static struct attribute * idle_attrs[] = {
+ &idle_poll_attr.attr,
+ NULL
+};
+
+static struct attribute_group idle_attr_group = {
+ .attrs = idle_attrs,
+};
+
+static int __init idle_poll_set_init(void)
+{
+ int err;
+
+ /*
+ * If the default is alread poll_idle then
+ * don't even bother with this.
+ */
+ if (pm_idle == poll_idle)
+ return 0;
+
+ memset(&idle_kobj, 0, sizeof(idle_kobj));
+
+ idle_kobj.is_poll = 0;
+ idle_kobj.idle = pm_idle;
+
+ err = kobject_set_name(&idle_kobj.kobj, "%s", "idle");
+ if (err)
+ goto out;
+
+ idle_kobj.kobj.parent = &kernel_subsys.kset.kobj;
+ err = kobject_register(&idle_kobj.kobj);
+ if (err)
+ goto out;
+
+ err = sysfs_create_group(&idle_kobj.kobj,
+ &idle_attr_group);
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ printk(KERN_INFO "Problem setting up sysfs idle_poll\n");
+ return 0;
+}
+
+late_initcall(idle_poll_set_init);
+#endif /* CONFIG_FS */
+


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/