Re: [PATCH] msleep() with hrtimers

From: Roman Zippel
Date: Tue Aug 07 2007 - 23:46:49 EST




On Tue, 7 Aug 2007, Andrew Morton wrote:

> On Wed, 8 Aug 2007 01:16:49 +0200 (CEST)
> Roman Zippel <zippel@xxxxxxxxxxxxxx> wrote:
>
> > Hi,
> >
> > On Tue, 7 Aug 2007, Andrew Morton wrote:
> >
> > > I'd be surprised if there was significant overhead - the maximum frequency
> > > at which msleep() can be called is 1000Hz. We'd need an awful lot of
> > > overhead for that to cause problems, surely?
> > >
> > > <thinks he's missing something again>
> >
> > _Anybody_ has yet to answer what's wrong with adding a nanosleep() and
> > using that instead.
> >
>
> You mean that the implementation could be simplified if msleep() were to
> simply call do_nanosleep()?

The current msleep is fine and doesn't need any "fixing".
Not all the world is i386, _please_ keep hrtimer usage where it's
required. Simple timer should be given preference unless the higher
resolution is really needed, which is not the case here.

> That would work, although a bit of refactoring would be needed so that we
> could implement the TASK_UNINTERRUPTIBLE msleep() that way.

The function is not that big, so below is a nanosleep implementation based
on Jonathan's patch. This will user give a choice, so there is no need to
force all users to use hrtimer for a simple sleep.
Please apply this patch instead.

bye, Roman

Signed-off-by: Roman Zippel <zippel@xxxxxxxxxxxxxx>

---
include/linux/delay.h | 5 +++++
kernel/timer.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)

Index: linux-2.6/include/linux/delay.h
===================================================================
--- linux-2.6.orig/include/linux/delay.h
+++ linux-2.6/include/linux/delay.h
@@ -9,6 +9,7 @@

extern unsigned long loops_per_jiffy;

+#include <linux/ktime.h>
#include <asm/delay.h>

/*
@@ -36,6 +37,10 @@ extern unsigned long loops_per_jiffy;
#endif

void calibrate_delay(void);
+
+void nanosleep(ktime_t time);
+int nanosleep_interruptible(ktime_t *time);
+
void msleep(unsigned int msecs);
unsigned long msleep_interruptible(unsigned int msecs);

Index: linux-2.6/kernel/timer.c
===================================================================
--- linux-2.6.orig/kernel/timer.c
+++ linux-2.6/kernel/timer.c
@@ -1377,3 +1377,52 @@ unsigned long msleep_interruptible(unsig
}

EXPORT_SYMBOL(msleep_interruptible);
+
+static int do_nanosleep(ktime_t *time, int sigs)
+{
+ enum hrtimer_mode mode = HRTIMER_MODE_REL;
+ int state = sigs ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+ struct hrtimer_sleeper sleeper;
+
+ hrtimer_init_sleeper(&sleeper, current);
+ hrtimer_init(&sleeper.timer, CLOCK_MONOTONIC, mode);
+ sleeper.timer.expires = *time;
+
+ do {
+ set_current_state(state);
+ hrtimer_start(&sleeper.timer, sleeper.timer.expires, mode);
+ if (sleeper.task)
+ schedule();
+ hrtimer_cancel(&sleeper.timer);
+ mode = HRTIMER_MODE_ABS;
+ if (!sleeper.task)
+ return 1;
+ } while (!sigs || !signal_pending(current));
+
+ *time = sleeper.timer.expires;
+ return 0;
+}
+
+/**
+ * nanosleep - sleep safely even with waitqueue interruptions
+ * @time: Time to sleep for
+ */
+void nanosleep(ktime_t time)
+{
+ do_nanosleep(&time, 0);
+}
+EXPORT_SYMBOL(nanosleep);
+
+/**
+ * nanosleep_interruptible - sleep waiting for signals
+ * @time: Time to sleep for
+ */
+int nanosleep_interruptible(ktime_t *time)
+{
+ if (do_nanosleep(time, 1))
+ return 1;
+
+ *time = ktime_sub(*time, ktime_get());
+ return 0;
+}
+EXPORT_SYMBOL(nanosleep_interruptible);
-
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/