Skip to content

Commit f36eb17

Browse files
anna-marialxKAGA-KOKO
authored andcommitted
timers: Update function descriptions of sleep/delay related functions
A lot of commonly used functions for inserting a sleep or delay lack a proper function description. Add function descriptions to all of them to have important information in a central place close to the code. No functional change. Signed-off-by: Anna-Maria Behnsen <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Frederic Weisbecker <[email protected]> Link: https://lore.kernel.org/all/20241014-devel-anna-maria-b4-timers-flseep-v3-5-dc8b907cb62f@linutronix.de
1 parent 102f085 commit f36eb17

File tree

3 files changed

+120
-22
lines changed

3 files changed

+120
-22
lines changed

include/asm-generic/delay.h

+37-4
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,39 @@ extern void __const_udelay(unsigned long xloops);
1212
extern void __delay(unsigned long loops);
1313

1414
/*
15-
* The weird n/20000 thing suppresses a "comparison is always false due to
16-
* limited range of data type" warning with non-const 8-bit arguments.
15+
* Implementation details:
16+
*
17+
* * The weird n/20000 thing suppresses a "comparison is always false due to
18+
* limited range of data type" warning with non-const 8-bit arguments.
19+
* * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
20+
* * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
1721
*/
1822

19-
/* 0x10c7 is 2**32 / 1000000 (rounded up) */
23+
/**
24+
* udelay - Inserting a delay based on microseconds with busy waiting
25+
* @usec: requested delay in microseconds
26+
*
27+
* When delaying in an atomic context ndelay(), udelay() and mdelay() are the
28+
* only valid variants of delaying/sleeping to go with.
29+
*
30+
* When inserting delays in non atomic context which are shorter than the time
31+
* which is required to queue e.g. an hrtimer and to enter then the scheduler,
32+
* it is also valuable to use udelay(). But it is not simple to specify a
33+
* generic threshold for this which will fit for all systems. An approximation
34+
* is a threshold for all delays up to 10 microseconds.
35+
*
36+
* When having a delay which is larger than the architecture specific
37+
* %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
38+
* risk is given.
39+
*
40+
* Please note that ndelay(), udelay() and mdelay() may return early for several
41+
* reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
42+
*
43+
* #. computed loops_per_jiffy too low (due to the time taken to execute the
44+
* timer interrupt.)
45+
* #. cache behaviour affecting the time it takes to execute the loop function.
46+
* #. CPU clock rate changes.
47+
*/
2048
#define udelay(n) \
2149
({ \
2250
if (__builtin_constant_p(n)) { \
@@ -29,7 +57,12 @@ extern void __delay(unsigned long loops);
2957
} \
3058
})
3159

32-
/* 0x5 is 2**32 / 1000000000 (rounded up) */
60+
/**
61+
* ndelay - Inserting a delay based on nanoseconds with busy waiting
62+
* @nsec: requested delay in nanoseconds
63+
*
64+
* See udelay() for basic information about ndelay() and it's variants.
65+
*/
3366
#define ndelay(n) \
3467
({ \
3568
if (__builtin_constant_p(n)) { \

include/linux/delay.h

+36-12
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,7 @@
66
* Copyright (C) 1993 Linus Torvalds
77
*
88
* Delay routines, using a pre-computed "loops_per_jiffy" value.
9-
*
10-
* Please note that ndelay(), udelay() and mdelay() may return early for
11-
* several reasons:
12-
* 1. computed loops_per_jiffy too low (due to the time taken to
13-
* execute the timer interrupt.)
14-
* 2. cache behaviour affecting the time it takes to execute the
15-
* loop function.
16-
* 3. CPU clock rate changes.
17-
*
18-
* Please see this thread:
19-
* https://lists.openwall.net/linux-kernel/2011/01/09/56
9+
* Sleep routines using timer list timers or hrtimers.
2010
*/
2111

2212
#include <linux/math.h>
@@ -35,12 +25,21 @@ extern unsigned long loops_per_jiffy;
3525
* The 2nd mdelay() definition ensures GCC will optimize away the
3626
* while loop for the common cases where n <= MAX_UDELAY_MS -- Paul G.
3727
*/
38-
3928
#ifndef MAX_UDELAY_MS
4029
#define MAX_UDELAY_MS 5
4130
#endif
4231

4332
#ifndef mdelay
33+
/**
34+
* mdelay - Inserting a delay based on milliseconds with busy waiting
35+
* @n: requested delay in milliseconds
36+
*
37+
* See udelay() for basic information about mdelay() and it's variants.
38+
*
39+
* Please double check, whether mdelay() is the right way to go or whether a
40+
* refactoring of the code is the better variant to be able to use msleep()
41+
* instead.
42+
*/
4443
#define mdelay(n) (\
4544
(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
4645
({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
@@ -63,16 +62,41 @@ unsigned long msleep_interruptible(unsigned int msecs);
6362
void usleep_range_state(unsigned long min, unsigned long max,
6463
unsigned int state);
6564

65+
/**
66+
* usleep_range - Sleep for an approximate time
67+
* @min: Minimum time in microseconds to sleep
68+
* @max: Maximum time in microseconds to sleep
69+
*
70+
* For basic information please refere to usleep_range_state().
71+
*
72+
* The task will be in the state TASK_UNINTERRUPTIBLE during the sleep.
73+
*/
6674
static inline void usleep_range(unsigned long min, unsigned long max)
6775
{
6876
usleep_range_state(min, max, TASK_UNINTERRUPTIBLE);
6977
}
7078

79+
/**
80+
* usleep_range_idle - Sleep for an approximate time with idle time accounting
81+
* @min: Minimum time in microseconds to sleep
82+
* @max: Maximum time in microseconds to sleep
83+
*
84+
* For basic information please refere to usleep_range_state().
85+
*
86+
* The sleeping task has the state TASK_IDLE during the sleep to prevent
87+
* contribution to the load avarage.
88+
*/
7189
static inline void usleep_range_idle(unsigned long min, unsigned long max)
7290
{
7391
usleep_range_state(min, max, TASK_IDLE);
7492
}
7593

94+
/**
95+
* ssleep - wrapper for seconds around msleep
96+
* @seconds: Requested sleep duration in seconds
97+
*
98+
* Please refere to msleep() for detailed information.
99+
*/
76100
static inline void ssleep(unsigned int seconds)
77101
{
78102
msleep(seconds * 1000);

kernel/time/sleep_timeout.c

+47-6
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,34 @@ EXPORT_SYMBOL_GPL(schedule_hrtimeout);
281281

282282
/**
283283
* msleep - sleep safely even with waitqueue interruptions
284-
* @msecs: Time in milliseconds to sleep for
284+
* @msecs: Requested sleep duration in milliseconds
285+
*
286+
* msleep() uses jiffy based timeouts for the sleep duration. Because of the
287+
* design of the timer wheel, the maximum additional percentage delay (slack) is
288+
* 12.5%. This is only valid for timers which will end up in level 1 or a higher
289+
* level of the timer wheel. For explanation of those 12.5% please check the
290+
* detailed description about the basics of the timer wheel.
291+
*
292+
* The slack of timers which will end up in level 0 depends on sleep duration
293+
* (msecs) and HZ configuration and can be calculated in the following way (with
294+
* the timer wheel design restriction that the slack is not less than 12.5%):
295+
*
296+
* ``slack = MSECS_PER_TICK / msecs``
297+
*
298+
* When the allowed slack of the callsite is known, the calculation could be
299+
* turned around to find the minimal allowed sleep duration to meet the
300+
* constraints. For example:
301+
*
302+
* * ``HZ=1000`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 1 / (1/4) = 4``:
303+
* all sleep durations greater or equal 4ms will meet the constraints.
304+
* * ``HZ=1000`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 1 / (1/8) = 8``:
305+
* all sleep durations greater or equal 8ms will meet the constraints.
306+
* * ``HZ=250`` with ``slack=25%``: ``MSECS_PER_TICK / slack = 4 / (1/4) = 16``:
307+
* all sleep durations greater or equal 16ms will meet the constraints.
308+
* * ``HZ=250`` with ``slack=12.5%``: ``MSECS_PER_TICK / slack = 4 / (1/8) = 32``:
309+
* all sleep durations greater or equal 32ms will meet the constraints.
310+
*
311+
* See also the signal aware variant msleep_interruptible().
285312
*/
286313
void msleep(unsigned int msecs)
287314
{
@@ -294,7 +321,15 @@ EXPORT_SYMBOL(msleep);
294321

295322
/**
296323
* msleep_interruptible - sleep waiting for signals
297-
* @msecs: Time in milliseconds to sleep for
324+
* @msecs: Requested sleep duration in milliseconds
325+
*
326+
* See msleep() for some basic information.
327+
*
328+
* The difference between msleep() and msleep_interruptible() is that the sleep
329+
* could be interrupted by a signal delivery and then returns early.
330+
*
331+
* Returns: The remaining time of the sleep duration transformed to msecs (see
332+
* schedule_timeout() for details).
298333
*/
299334
unsigned long msleep_interruptible(unsigned int msecs)
300335
{
@@ -312,11 +347,17 @@ EXPORT_SYMBOL(msleep_interruptible);
312347
* @max: Maximum time in usecs to sleep
313348
* @state: State of the current task that will be while sleeping
314349
*
350+
* usleep_range_state() sleeps at least for the minimum specified time but not
351+
* longer than the maximum specified amount of time. The range might reduce
352+
* power usage by allowing hrtimers to coalesce an already scheduled interrupt
353+
* with this hrtimer. In the worst case, an interrupt is scheduled for the upper
354+
* bound.
355+
*
356+
* The sleeping task is set to the specified state before starting the sleep.
357+
*
315358
* In non-atomic context where the exact wakeup time is flexible, use
316-
* usleep_range_state() instead of udelay(). The sleep improves responsiveness
317-
* by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces
318-
* power usage by allowing hrtimers to take advantage of an already-
319-
* scheduled interrupt instead of scheduling a new one just for this sleep.
359+
* usleep_range() or its variants instead of udelay(). The sleep improves
360+
* responsiveness by avoiding the CPU-hogging busy-wait of udelay().
320361
*/
321362
void __sched usleep_range_state(unsigned long min, unsigned long max, unsigned int state)
322363
{

0 commit comments

Comments
 (0)