[PATCH 2/4] Documentation: Add timers/timers-howto.txt

From: Patrick Pannuto
Date: Wed Jul 28 2010 - 15:34:05 EST

This file seeks to explain the nuances in various delays;
many driver writers are not necessarily familiar with the
various kernel timers, their shortfalls, and quirks. When
faced with

ndelay, udelay, mdelay, usleep, usleep_range, msleep, and

the question "How do I just wait 1 ms for my hardware to
latch?" has the non-intuitive "best" answer:

This patch is followed by a series of checkpatch additions
that seek to help kernel hackers pick the best delay.

Signed-off-by: Patrick Pannuto <ppannuto@xxxxxxxxxxxxxx>
Documentation/timers/timers-howto.txt | 106 +++++++++++++++++++++++++++++++++
1 files changed, 106 insertions(+), 0 deletions(-)
create mode 100644 Documentation/timers/timers-howto.txt

diff --git a/Documentation/timers/timers-howto.txt b/Documentation/timers/timers-howto.txt
new file mode 100644
index 0000000..ea10a3a
--- /dev/null
+++ b/Documentation/timers/timers-howto.txt
@@ -0,0 +1,106 @@
+delays - Information on the various kernel delay / sleep mechanisms
+This document seeks to answer the common question: "What is the
+RightWay (TM) to insert a delay?"
+This question is most often faced by driver writers who have to
+deal with hardware delays and who may not be the most intimately
+familiar with the inner workings of the Linux Kernel.
+Inserting Delays
+The first, and most important, question you need to ask is "Is my
+code in an atomic context?" This should be followed closely by "Does
+it really need to delay in atomic context?" If so...
+ You must use the *delay family of functions. These
+ functions use the jiffie estimation of clock speed
+ and will busy wait for enough loop cycles to achieve
+ the desired delay:
+ ndelay(unsigned long nsecs)
+ udelay(unsigned long usecs)
+ mdelay(unsgined long msecs)
+ udelay is the generally preferred API; ndelay-level
+ precision may not actually exist on many non-PC devices.
+ mdelay is macro wrapper around udelay, to account for
+ possible overflow when passing large arguments to udelay.
+ In general, use of mdelay is discouraged.
+ You should use the *sleep[_range] family of functions.
+ There are a few more options here, while any of them may
+ work correctly, using the "right" sleep function will
+ help the scheduler, power management, and just make your
+ driver better :)
+ -- Backed by busy-wait loop:
+ udelay(unsigned long usecs)
+ -- Backed by hrtimers:
+ usleep(unsigned long usecs)
+ usleep_range(unsigned long min, unsigned long max)
+ -- Backed by jiffies / legacy_timers
+ msleep(unsigned long msecs)
+ msleep_interruptible(unsigned long msecs)
+ Unlike the *delay family, the underlying mechanism
+ driving each of these calls varies, thus there are
+ quirks you should be aware of.
+ SLEEPING FOR "A FEW" USECS ( < ~10us? ):
+ * Use udelay
+ - Why not usleep?
+ On slower systems, (embedded, OR perhaps a speed-
+ stepped PC!) the overhead of setting up the hrtimers
+ for usleep *may* not be worth it. Such an evaluation
+ will obviously depend on your specific situation, but
+ it is something to be aware of.
+ * Use usleep[_range]
+ - Why not msleep for (1ms - 20ms)?
+ Explained originally here:
+ http://lkml.org/lkml/2007/8/3/250
+ msleep(1~20) may not do what the caller intends, and
+ will often sleep longer (~20 ms actual sleep for any
+ value given in the 1~20ms range). In many cases this
+ is not the desired behavior.
+ - What is the difference between usleep and usleep_range?
+ Fundamentally nothing; usleep(unsigned long usecs)
+ simply calls usleep_range(usecs, usecs * 2). This
+ built-in slack is similar in spirit to the slack
+ now built-in to legacy timers (0.4%) - and thus
+ built-in to msleep -, although it is significantly
+ larger.
+ The reasoning for slack is that usleep is built upon
+ hrtimers, and mindless callers of usleep will actually
+ introduce many undesired interrupts. By allowing a
+ range, wakeups can be coalesced. Given the scale, a
+ 200% slack seems a reasonable default value.
+ If your application can afford it, use usleep_range
+ to extend the slack to an even larger window; or, if
+ you need a more precise sleep (?), you can use
+ usleep_range to restrict the slack to a tighter bound.
+ * Use msleep or possibly msleep_interruptible
+ - What's the difference?
+ msleep sets the current task to TASK_UNINTERRUPTIBLE
+ whereas msleep_interruptible sets the current task to
+ TASK_INTERRUPTIBLE before scheduling the sleep. In
+ short, the difference is whether the sleep can be ended
+ early by a signal. In general, just use msleep unless
+ you know you have a need for the interruptible variant.

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/