| 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(unsigned 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. |