| .. SPDX-License-Identifier: GPL-2.0 | |
| Delay and 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. | |
| The following table gives a rough overview about the existing function | |
| 'families' and their limitations. This overview table does not replace the | |
| reading of the function description before usage! | |
| .. list-table:: | |
| :widths: 20 20 20 20 20 | |
| :header-rows: 2 | |
| * - | |
| - `*delay()` | |
| - `usleep_range*()` | |
| - `*sleep()` | |
| - `fsleep()` | |
| * - | |
| - busy-wait loop | |
| - hrtimers based | |
| - timer list timers based | |
| - combines the others | |
| * - Usage in atomic Context | |
| - yes | |
| - no | |
| - no | |
| - no | |
| * - precise on "short intervals" | |
| - yes | |
| - yes | |
| - depends | |
| - yes | |
| * - precise on "long intervals" | |
| - Do not use! | |
| - yes | |
| - max 12.5% slack | |
| - yes | |
| * - interruptible variant | |
| - no | |
| - yes | |
| - yes | |
| - no | |
| A generic advice for non atomic contexts could be: | |
| #. Use `fsleep()` whenever unsure (as it combines all the advantages of the | |
| others) | |
| #. Use `*sleep()` whenever possible | |
| #. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient | |
| #. Use `*delay()` for very, very short delays | |
| Find some more detailed information about the function 'families' in the next | |
| sections. | |
| `*delay()` family of functions | |
| ------------------------------ | |
| These functions use the jiffy estimation of clock speed and will busy wait for | |
| enough loop cycles to achieve the desired delay. udelay() is the basic | |
| implementation and ndelay() as well as mdelay() are variants. | |
| These functions are mainly used to add a delay in atomic context. Please make | |
| sure to ask yourself before adding a delay in atomic context: Is this really | |
| required? | |
| .. kernel-doc:: include/asm-generic/delay.h | |
| :identifiers: udelay ndelay | |
| .. kernel-doc:: include/linux/delay.h | |
| :identifiers: mdelay | |
| `usleep_range*()` and `*sleep()` family of functions | |
| ---------------------------------------------------- | |
| These functions use hrtimers or timer list timers to provide the requested | |
| sleeping duration. In order to decide which function is the right one to use, | |
| take some basic information into account: | |
| #. hrtimers are more expensive as they are using an rb-tree (instead of hashing) | |
| #. hrtimers are more expensive when the requested sleeping duration is the first | |
| timer which means real hardware has to be programmed | |
| #. timer list timers always provide some sort of slack as they are jiffy based | |
| The generic advice is repeated here: | |
| #. Use `fsleep()` whenever unsure (as it combines all the advantages of the | |
| others) | |
| #. Use `*sleep()` whenever possible | |
| #. Use `usleep_range*()` whenever accuracy of `*sleep()` is not sufficient | |
| First check fsleep() function description and to learn more about accuracy, | |
| please check msleep() function description. | |
| `usleep_range*()` | |
| ~~~~~~~~~~~~~~~~~ | |
| .. kernel-doc:: include/linux/delay.h | |
| :identifiers: usleep_range usleep_range_idle | |
| .. kernel-doc:: kernel/time/sleep_timeout.c | |
| :identifiers: usleep_range_state | |
| `*sleep()` | |
| ~~~~~~~~~~ | |
| .. kernel-doc:: kernel/time/sleep_timeout.c | |
| :identifiers: msleep msleep_interruptible | |
| .. kernel-doc:: include/linux/delay.h | |
| :identifiers: ssleep fsleep |