From: Andrew Morton <akpm@linux-foundation.org>
To: Jonathan Corbet <corbet@lwn.net>
Cc: linux-kernel@vger.kernel.org,
Thomas Gleixner <tglx@linutronix.de>, Ingo Molnar <mingo@elte.hu>,
Roman Zippel <zippel@linux-m68k.org>
Subject: Re: [PATCH] msleep() with hrtimers
Date: Wed, 28 Nov 2007 02:29:49 -0800 [thread overview]
Message-ID: <20071128022949.be8d925f.akpm@linux-foundation.org> (raw)
In-Reply-To: <15327.1186166232@lwn.net>
On Fri, 03 Aug 2007 12:37:12 -0600 Jonathan Corbet <corbet@lwn.net> wrote:
> Here's the second (and probably final) posting of the msleep() with
> hrtimers patch. The problem being addressed here is that the current
> msleep() will stop for a minimum of two jiffies, meaning that, on a
> HZ=100 system, msleep(1) delays for for about 20ms. In a driver with
> one such delay for each of 150 or so register setting operations, the
> extra time adds up to a few seconds.
>
> This patch addresses the situation by using hrtimers. On tickless
> systems with working timers, msleep(1) now sleeps for 1ms, even with
> HZ=100.
>
> Most comments last time were favorable. The one dissenter was Roman,
> who worries about the overhead of using hrtimers for this operation; my
> understanding is that he would rather see a really_msleep() function for
> those who actually want millisecond resolution. I'm not sure how to
> characterize what the cost could be, but it can only be buried by the
> fact that every call sleeps for some number of milliseconds. On my
> system, the several hundred total msleep() calls can't cause any real
> overhead, and almost all happen at initialization time.
>
> I still think it would be useful for msleep() to do what it says it does
> and not vastly oversleep with small arguments. A quick grep turns up
> 450 msleep(1) calls in the current mainline. Andrew, if you agree, can
> you drop this into -mm? If not, I guess I'll let it go.
>
> jon
>
> ---
>
> Use hrtimers so that msleep() sleeps for the requested time
>
> Current msleep() snoozes for at least two jiffies, causing msleep(1) to
> sleep for at least 20ms on HZ=100 systems. Using hrtimers allows
> msleep() to sleep for something much closer to the requested time.
>
> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
>
> --- 2.6.23-rc1/kernel/timer.c.orig 2007-08-02 13:45:20.000000000 -0600
> +++ 2.6.23-rc1/kernel/timer.c 2007-08-03 12:34:48.000000000 -0600
> @@ -1349,18 +1349,43 @@ void __init init_timers(void)
> open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
> }
>
> +
> +
> +
> +static void do_msleep(unsigned int msecs, struct hrtimer_sleeper *sleeper,
> + int sigs)
> +{
> + enum hrtimer_mode mode = HRTIMER_MODE_REL;
> + int state = sigs ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
> +
> + /*
> + * This is really just a reworked and simplified version
> + * of do_nanosleep().
> + */
> + hrtimer_init(&sleeper->timer, CLOCK_MONOTONIC, mode);
> + sleeper->timer.expires = ktime_set(0, msecs*NSEC_PER_MSEC);
> + hrtimer_init_sleeper(sleeper, current);
> +
> + 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;
> + } while (sleeper->task && !(sigs && signal_pending(current)));
> +}
> +
> /**
> * msleep - sleep safely even with waitqueue interruptions
> * @msecs: Time in milliseconds to sleep for
> */
> void msleep(unsigned int msecs)
> {
> - unsigned long timeout = msecs_to_jiffies(msecs) + 1;
> + struct hrtimer_sleeper sleeper;
>
> - while (timeout)
> - timeout = schedule_timeout_uninterruptible(timeout);
> + do_msleep(msecs, &sleeper, 0);
> }
> -
> EXPORT_SYMBOL(msleep);
>
> /**
> @@ -1369,11 +1394,15 @@ EXPORT_SYMBOL(msleep);
> */
> unsigned long msleep_interruptible(unsigned int msecs)
> {
> - unsigned long timeout = msecs_to_jiffies(msecs) + 1;
> + struct hrtimer_sleeper sleeper;
> + ktime_t left;
>
> - while (timeout && !signal_pending(current))
> - timeout = schedule_timeout_interruptible(timeout);
> - return jiffies_to_msecs(timeout);
> -}
> + do_msleep(msecs, &sleeper, 1);
>
> + if (!sleeper.task)
> + return 0;
> + left = ktime_sub(sleeper.timer.expires,
> + sleeper.timer.base->get_time());
> + return max(((long) ktime_to_ns(left))/NSEC_PER_MSEC, 1L);
> +}
> EXPORT_SYMBOL(msleep_interruptible);
This patch (which appears to have got stranded in Thomas's git-hrt tree)
breaks hotplugging of the wireless mouse on my Vaio.
Kinda strange - sometimes things come up and work but more often the
machine simply fails to notice that the mouse was plugged in at all.
It could be a bug in USB...
<gets a sinking feeling>
<looks down-thread>
ah shit, I already reported this bug on August 9 and I just spent an hour
and a half re-finding it. Thanks, guys.
Anyway, here's a fix which doesn't fix it:
- Don't return from msleep() in state TASK_[UN]INTERRUPTIBLE
- Someone seems to have fallen asleep on the enter key. Fix.
--- a/kernel/timer.c~git-hrt-fix
+++ a/kernel/timer.c
@@ -1347,7 +1347,6 @@ static struct notifier_block __cpuinitda
.notifier_call = timer_cpu_notify,
};
-
void __init init_timers(void)
{
int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE,
@@ -1360,9 +1359,6 @@ void __init init_timers(void)
open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
}
-
-
-
static void do_msleep(unsigned int msecs, struct hrtimer_sleeper *sleeper,
int sigs)
{
@@ -1385,6 +1381,7 @@ static void do_msleep(unsigned int msecs
hrtimer_cancel(&sleeper->timer);
mode = HRTIMER_MODE_ABS;
} while (sleeper->task && !(sigs && signal_pending(current)));
+ set_current_state(TASK_RUNNING);
}
/**
_
I'll revert it.
prev parent reply other threads:[~2007-11-28 10:30 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-08-03 18:37 [PATCH] msleep() with hrtimers Jonathan Corbet
2007-08-03 18:54 ` Ingo Molnar
2007-08-03 19:19 ` Roman Zippel
2007-08-03 19:46 ` Arjan van de Ven
2007-08-03 19:58 ` Roman Zippel
2007-08-03 23:53 ` Arjan van de Ven
2007-08-04 3:00 ` Roman Zippel
2007-08-04 19:19 ` Arjan van de Ven
2007-08-06 0:09 ` Roman Zippel
2007-08-06 0:43 ` Arjan van de Ven
2007-08-06 1:03 ` Roman Zippel
2007-08-06 5:39 ` Arjan van de Ven
2007-08-06 10:03 ` Roman Zippel
2007-08-06 10:20 ` Manu Abraham
2007-08-06 15:53 ` Arjan van de Ven
2007-08-07 10:40 ` Manu Abraham
2007-08-07 12:45 ` Roman Zippel
2007-08-08 4:15 ` Arjan van de Ven
2007-08-09 19:31 ` Denis Vlasenko
2007-08-09 20:01 ` Denis Vlasenko
2007-08-07 19:40 ` Andrew Morton
2007-08-07 23:16 ` Roman Zippel
2007-08-07 23:29 ` Andrew Morton
2007-08-08 3:47 ` Roman Zippel
2007-08-08 4:14 ` Andrew Morton
2007-08-09 22:31 ` Roman Zippel
2007-08-08 11:55 ` Andi Kleen
2007-08-08 11:09 ` Manu Abraham
2007-08-08 11:52 ` Andi Kleen
2007-08-08 11:59 ` Manu Abraham
2007-08-09 7:16 ` Andrew Morton
2007-08-09 15:08 ` [linux-usb-devel] " Alan Stern
2007-11-28 10:29 ` Andrew Morton [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071128022949.be8d925f.akpm@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=corbet@lwn.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@linutronix.de \
--cc=zippel@linux-m68k.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.