mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-17 22:05:08 +00:00
122 lines
3.4 KiB
ReStructuredText
122 lines
3.4 KiB
ReStructuredText
|
.. 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
|