From: Nishanth Aravamudan <nacc@us.ibm.com>
To: linux-kernel@vger.kernel.org
Cc: domen@coderock.org
Subject: [PATCH 2/2] include/delay.h: replace msleep() and msleep_interruptible() with macros
Date: Fri, 19 Nov 2004 17:23:32 -0800 [thread overview]
Message-ID: <20041120012332.GF6181@us.ibm.com> (raw)
In-Reply-To: <20041120005601.GB7466@us.ibm.com>
On Fri, Nov 19, 2004 at 04:56:01PM -0800, Nishanth Aravamudan wrote:
> On Fri, Nov 19, 2004 at 04:48:41PM -0800, Nishanth Aravamudan wrote:
> > On Tue, Nov 16, 2004 at 06:49:44PM -0800, Nishanth Aravamudan wrote:
> > > Hi,
> > >
> > > After some pretty heavy discussion on IRC, I felt that it may be
> > > important / useful to bring the discussion of schedule_timeout() to
> > > LKML. There are two issues being considered:
> > >
> > > 1) msleep_interruptible()
> > >
> > > For reference, here is the code for this function:
> > >
> > > /**
> > > * msleep_interruptible - sleep waiting for waitqueue interruptions
> > > * @msecs: Time in milliseconds to sleep for
> > > */
> > > unsigned long msleep_interruptible(unsigned int msecs)
> > > {
> > > unsigned long timeout = msecs_to_jiffies(msecs);
> > >
> > > while (timeout && !signal_pending(current)) {
> > > set_current_state(TASK_INTERRUPTIBLE);
> > > timeout = schedule_timeout(timeout);
> > > }
> > > return jiffies_to_msecs(timeout);
> > > }
> > >
> > > The first issue deals with whether the while() loop is at all necessary.
> > > From my understanding (primarily from how the code "should" behave, but
> > > also backed up by code itself), I think the following code:
> > >
> > > set_current_state(TASK_INTERRUPTIBLE);
> > > timeout = schedule_timeout(timeout);
> > >
> > > should be interpreted as:
> > >
> > > a) I wish to sleep for timeout jiffies; however
> > > b) If a signal occurs before timeout jiffies have gone by, I
> > > would also like to wake up.
> > >
> > > With this interpretation, though, the while()-conditional becomes
> > > questionable. I can see two cases (think inclusive OR not exclusive) for
> > > schedule_timeout() returning:
> > >
> > > a) A signal was received and thus signal_pending(current) will
> > > be true, exiting the loop. In this case, timeout will be
> > > some non-negative value (0 is a corner case, I believe, where
> > > both the timer fires and a signal is received in the last jiffy).
> > > b) The timer in schedule_timeout() has expired and thus it will
> > > return 0. This indicates the function has delayed the requested
> > > time (at least) and timeout will be set to 0, again exiting the
> > > loop.
> > >
> > > Clearly, then, if my interpretion is correct, schedule_timeout() will
> > > always return to a state in msleep_interruptible() which causes the loop
> > > to only iterate the one time. Does this make sense? Is my interpretation
> > > of schedule_timeout()s functioning somehow flawed? If not, we probably
> > > can go ahead and change the msleep_interruptible() code, yes?
> >
> > Ok, since nobody seems to have objected to my ideas as of yet, I went
> > ahead and implemented them, with much help from Domen and others. I
> > believe there are two options for these changes. One involves using
> > macros instead, the other involves reworking the functions.
>
> Here is patch 2/2, which modifies include/linux/delay.h to contain the
> appropriate macros. Much consideration was given the various names and
> calling syntax, but corrections/requests/changes are welcome.
>
> -Nish
>
> Description: Remove prototypes of msleep() and msleep_interruptible() to
> prepare for the macro versions of these functions. Add macros for 4
> types of sleeps:
> 1) Unconditional sleep (msleep)
> 2) Sleep until signalled (msleep_interruptible)
> 3) Sleep until wait-queue event (msleep_wq)
> 4) Sleep until either signalled or wait-queue event
> (msleep_wq_interruptible)
> These 4 cases are all distinct and handled separately by passing
> appropriate flags to __msleep_sig and __msleep_wq, which should *not*
> ever be called directly by kernel code.
>
> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
>
> --- 2.6.10-rc2-vanilla/include/linux/delay.h 2004-11-19 16:11:52.000000000 -0800
> +++ 2.6.10-rc2/include/linux/delay.h 2004-11-19 16:52:40.000000000 -0800
> @@ -38,8 +38,56 @@ extern unsigned long loops_per_jiffy;
> #define ndelay(x) udelay(((x)+999)/1000)
> #endif
>
> -void msleep(unsigned int msecs);
> -unsigned long msleep_interruptible(unsigned int msecs);
> +/*
> + * Sleep in state while condition is true
> + */
> +#define __msleep_sig(unsigned int msecs, long state, int condition) \
> + do { \
> + unsigned long timeout = msecs_to_jiffies(msecs) + 1; \
> + \
> + while (timeout && condition) { \
> + set_current_state(state); \
> + timeout = schedule_timeout(timeout); \
> + } \
> + \
> + return jiffies_to_msecs(timeout); \
> + } while(0)
> +
> +/*
> + * Sleep in state until schedule_timeout() returns
> + */
> +#define __msleep_wq(unsigned int msecs, long state) \
> + do { \
> + unsigned long timeout = msecs_to_jiffies(msecs) + 1; \
> + \
> + set_current_state(condition); \
Obvious typo, fixed in patch below...
Description: Remove prototypes of msleep() and msleep_interruptible() to
prepare for the macro versions of these functions. Add macros for 4
types of sleeps:
1) Unconditional sleep (msleep)
2) Sleep until signalled (msleep_interruptible)
3) Sleep until wait-queue event (msleep_wq)
4) Sleep until either signalled or wait-queue event
(msleep_wq_interruptible)
These 4 cases are all distinct and handled separately by passing
appropriate flags to __msleep_sig and __msleep_wq, which should *not*
ever be called directly by kernel code.
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
--- 2.6.10-rc2-vanilla/include/linux/delay.h 2004-11-19 16:11:52.000000000 -0800
+++ 2.6.10-rc2/include/linux/delay.h 2004-11-19 16:52:40.000000000 -0800
@@ -38,8 +38,56 @@ extern unsigned long loops_per_jiffy;
#define ndelay(x) udelay(((x)+999)/1000)
#endif
-void msleep(unsigned int msecs);
-unsigned long msleep_interruptible(unsigned int msecs);
+/*
+ * Sleep in state while condition is true
+ */
+#define __msleep_sig(unsigned int msecs, long state, int condition) \
+ do { \
+ unsigned long timeout = msecs_to_jiffies(msecs) + 1; \
+ \
+ while (timeout && condition) { \
+ set_current_state(state); \
+ timeout = schedule_timeout(timeout); \
+ } \
+ \
+ return jiffies_to_msecs(timeout); \
+ } while(0)
+
+/*
+ * Sleep in state until schedule_timeout() returns
+ */
+#define __msleep_wq(unsigned int msecs, long state) \
+ do { \
+ unsigned long timeout = msecs_to_jiffies(msecs) + 1; \
+ \
+ set_current_state(state); \
+ timeout = schedule_timeout(timeout); \
+ \
+ return jiffies_to_msecs(timeout); \
+ } while(0)
+
+/*
+ * Sleep until at least msecs ms have elapsed
+ */
+#define msleep(msecs) (void)__msleep_sig(msecs, TASK_UNINTERRUPTIBLE, 1)
+
+/*
+ * Sleep until at least msecs ms have elapsed or a signal is received
+ */
+#define msleep_interruptible(msecs) \
+ __msleep_sig(msecs, TASK_INTERRUPTIBLE, !signals_pending(current))
+
+/*
+ * Sleep until at least msecs ms have elapsed or a wait-queue event occurs
+ */
+#define msleep_wq(msecs) __msleep_wq_state(msecs, TASK_UNINTERRUPTIBLE)
+
+/*
+ * Sleep until at least msecs ms have elapsed or a wait-queue event occurs
+ * or a signal is received
+ */
+#define msleep_wq_interruptible(msecs) \
+ __msleep_wq_state(msecs, TASK_INTERRUPTIBLE);
static inline void ssleep(unsigned int seconds)
{
next prev parent reply other threads:[~2004-11-20 1:27 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-11-17 2:49 schedule_timeout() issues / questions Nishanth Aravamudan
2004-11-20 0:48 ` [PATCH 1/2] kernel/timer.c: remove msleep() and msleep_interruptible() Nishanth Aravamudan
2004-11-20 0:56 ` [PATCH 2/2] include/delay.h: replace msleep() and msleep_interruptible() with macros Nishanth Aravamudan
2004-11-20 1:23 ` Nishanth Aravamudan [this message]
2004-11-20 1:25 ` Nishanth Aravamudan
[not found] ` <200411201037.22237.oliver@neukum.org>
2004-11-22 18:01 ` Nishanth Aravamudan
[not found] ` <200411221934.53425.oliver@neukum.org>
2004-11-22 19:50 ` [PATCH ] kernel/timer: correct msleep_interruptible() comment Nishanth Aravamudan
2004-11-20 0:56 ` [PATCH 1/2] kernel/timer.c: remove msleep() and msleep_interruptible() Nishanth Aravamudan
2004-11-20 1:17 ` [PATCH 1/2] kernel/timer: remove msleep{,_interruptible}(); add __msleep_{sig,wq}() Nishanth Aravamudan
2004-11-20 1:21 ` [PATCH 2/2] include/delay: replace msleep{,_interruptible}() with macros Nishanth Aravamudan
2004-11-20 1:26 ` Nishanth Aravamudan
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=20041120012332.GF6181@us.ibm.com \
--to=nacc@us.ibm.com \
--cc=domen@coderock.org \
--cc=linux-kernel@vger.kernel.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.