public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
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)
 {

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox