mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
Documentation: Add timers/timers-howto.txt
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_range, msleep, and msleep_interrubtible the question "How do I just wait 1 ms for my hardware to latch?" has the non-intuitive "best" answer: usleep_range(1000,1500) 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@codeaurora.org> Cc: apw@canonical.com Cc: corbet@lwn.net Cc: arjan@linux.intel.com Cc: Randy Dunlap <rdunlap@xenotime.net> Cc: Andrew Morton <akpm@linux-foundation.org> LKML-Reference: <1280786467-26999-3-git-send-email-ppannuto@codeaurora.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
5e7f5a178b
commit
0fcb80818b
105
Documentation/timers/timers-howto.txt
Normal file
105
Documentation/timers/timers-howto.txt
Normal file
@ -0,0 +1,105 @@
|
||||
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...
|
||||
|
||||
ATOMIC CONTEXT:
|
||||
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 and code should
|
||||
be refactored to allow for the use of msleep.
|
||||
|
||||
NON-ATOMIC CONTEXT:
|
||||
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_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.
|
||||
|
||||
SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms):
|
||||
* 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.
|
||||
|
||||
- Why is there no "usleep" / What is a good range?
|
||||
Since usleep_range is built on top of hrtimers, the
|
||||
wakeup will be very precise (ish), thus a simple
|
||||
usleep function would likely introduce a large number
|
||||
of undesired interrupts.
|
||||
|
||||
With the introduction of a range, the scheduler is
|
||||
free to coalesce your wakeup with any other wakeup
|
||||
that may have happened for other reasons, or at the
|
||||
worst case, fire an interrupt for your upper bound.
|
||||
|
||||
The larger a range you supply, the greater a chance
|
||||
that you will not trigger an interrupt; this should
|
||||
be balanced with what is an acceptable upper bound on
|
||||
delay / performance for your specific code path. Exact
|
||||
tolerances here are very situation specific, thus it
|
||||
is left to the caller to determine a reasonable range.
|
||||
|
||||
SLEEPING FOR LARGER MSECS ( 10ms+ )
|
||||
* 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.
|
Loading…
Reference in New Issue
Block a user