You wouldn't with this code, since accurately measuring the time that code takes to execute is a difficult task.

To get to the question posed by your question title (you should really ask one question at a time...) the accuracy of said functions is dictated by the operating system. On Linux, the system clock granularity is 10ms, so timed process suspension via nanosleep() is only guaranteed to be accurate to 10ms, and even then it's not guaranteed to sleep for exactly the time you specify. (See below.)

On Windows, the clock granularity can be changed to accommodate power management needs (e.g. decrease the granularity to conserve battery power). See MSDN's documentation on the Sleep function.

Note that with Sleep()/nanosleep(), the OS only guarantees that the process suspension will last for at least as long as you specify. The execution of other processes can always delay resumption of your process.

Therefore, the key-up event sent by your code above will be sent at least 2.638 seconds later than the key-down event, and not a millisecond sooner. But it would be possible for the event to be sent 2.7, 2.8, or even 3 seconds later. (Or much later if a realtime process grabbed hold of the CPU and didn't relinquish control for some time.)

Answer from cdhowie on Stack Overflow
Top answer
1 of 4
6

You wouldn't with this code, since accurately measuring the time that code takes to execute is a difficult task.

To get to the question posed by your question title (you should really ask one question at a time...) the accuracy of said functions is dictated by the operating system. On Linux, the system clock granularity is 10ms, so timed process suspension via nanosleep() is only guaranteed to be accurate to 10ms, and even then it's not guaranteed to sleep for exactly the time you specify. (See below.)

On Windows, the clock granularity can be changed to accommodate power management needs (e.g. decrease the granularity to conserve battery power). See MSDN's documentation on the Sleep function.

Note that with Sleep()/nanosleep(), the OS only guarantees that the process suspension will last for at least as long as you specify. The execution of other processes can always delay resumption of your process.

Therefore, the key-up event sent by your code above will be sent at least 2.638 seconds later than the key-down event, and not a millisecond sooner. But it would be possible for the event to be sent 2.7, 2.8, or even 3 seconds later. (Or much later if a realtime process grabbed hold of the CPU and didn't relinquish control for some time.)

2 of 4
1

Sleep works in terms of the standard Windows thread scheduling. It is accurate up to about 20-50 milliseconds.

So that it's ok for user experience-dependent things. However it's absolutely inappropriate for real-time things.

Beside of this, there're much better ways to simulate keyboard/mouse events. Please see SendInput.

🌐
GNU
gnu.org › software › libc › manual › html_node › Sleeping.html
The GNU C Library - GNU Project - Free Software Foundation (FSF)
This glibc manual version 2.43 (latest) is available in the following formats: · The manual is available for the following releases of glibc:
Discussions

Explain how the sleep command works.
36 votes, 13 comments. I have the source for the sleep command from coreutils in front of me but I do not quite understand what is actually making… More on reddit.com
🌐 r/C_Programming
13
36
March 9, 2022
Pop quiz: what does `sleep 1 2 3` do?
In addition to seconds, sleep(1) in GNU coreutils can also sleep for minutes, hours, or days, given the appropriate suffix: sleep 1m # sleeps for one minute sleep 3h # sleeps for three hours sleep 2d # sleeps for two days Given multiple arguments, you can mix and match these suffixes to sleep for some arbitrary amount of time; e.g. to sleep for 2h hours, 47 minutes, and 11 seconds, you simply do this: sleep 2h 47m 11s Hence the feature to sleep for the sum of the arguments. With non-GNU sleep, you do an awkward dance where you convert everything to seconds and sum it, or run multiple commands, e.g. sleep 7200; sleep 2820; sleep 11 # 2h, 47m, 11s sleep 10031 # sum of above More on reddit.com
🌐 r/commandline
20
29
August 5, 2015
c - What's the algorithm behind sleep()? - Stack Overflow
The best known incarnation of sleep() is in C (to be more accurate, in the libraries that come with C compilers, such as GNU's libc), although almost every language today has its equivalent, but the implementation of sleep in some languages (think Bash) is not what we're looking at in this ... More on stackoverflow.com
🌐 stackoverflow.com
Does sleep work differently on Linux?
Sleep works a bit different in linux yeah. It sounds like your system is entering one of the lesser sleep states, which would explain the drain. Usually the system chooses the best supported solution, you can check in /sys/power/mem_sleep what your system is set to use when it tries to suspend to ram. You can also see the available options in /sys/power/state where there's usually 3: freeze, mem, disk. "Freeze" is basically just a low power mode while "disk" means the system saves the contents of ram into swap and powers off, and on resume reloads the ram from swap to continue from where you left off. To make it easy, as far as I understand it they're basically in the order of freeze, mem with s2idle, mem with deep and disk in terms of power saving. You can play around with different modes of suspend to try them out as root, with echo "deep" > /sys/power/mem_sleep to choose the deeper mode of regular sleep and then sleep with echo "mem" > /sys/power/state to put the system to sleep. Be aware that you might not be able to resume if the system doesn't support this, so make sure you aren't doing anything important if you play around with this. The arch wiki has some further information about how to troubleshoot sleep, and there's also the best practice of debugging sleep issues which is technical, but has some good testing you can do. Almost all of this kind of issues are related to ACPI in my experience, and it really sucks. One of the common workarounds is using acpi_osi=some value in the kernel line in grub to force a specific ACPI compatibility mode basically, which is very tedious. More on reddit.com
🌐 r/linuxquestions
7
5
March 27, 2021
🌐
GNU
ftp.gnu.org › pub › old-gnu › Manuals › glibc-2.2.5 › html_node › Sleeping.html
The GNU C Library
Resist the temptation to implement a sleep for a fixed amount of time by using the return value of sleep, when nonzero, to call sleep again. This will work with a certain amount of accuracy as long as signals arrive infrequently. But each signal can cause the eventual wakeup time to be off by an additional second or so. Suppose a few signals happen to arrive in rapid succession by bad luck--there is no limit on how much this could shorten or lengthen the wait.
🌐
GNU
gnu.org › software › hello › manual › libc › Sleeping.html
Sleeping (The GNU C Library)
The sleep function is declared in unistd.h. Resist the temptation to implement a sleep for a fixed amount of time by using the return value of sleep, when nonzero, to call sleep again. This will work with a certain amount of accuracy as long as signals arrive infrequently.
🌐
GNU
gnu.org › software › coreutils › manual › html_node › sleep-invocation.html
sleep invocation (GNU Coreutils 9.11)
Due to shell aliases and built-in sleep functions, using an unadorned sleep interactively or in a script may get you different functionality than that described here.
🌐
Google Groups
groups.google.com › g › comp.unix.programmer › c › WqpQWYkA_NM
GNU sleep's "infinity" parameter
Every so often, in a shell script or whatever, one needs to sleep (pause) "forever". Usually, what you do is something like: sleep <verybignumber> and that is usually sufficient. However, in fact, GNU sleep can be called with a parameter of "infinity", which, it seems, does really sleep "forever".
🌐
DevOps Daily
devops-daily.com › home › posts › bash › how to sleep for milliseconds in bash and linux
How to Sleep for Milliseconds in Bash and Linux
November 23, 2025 - For millisecond delays in Bash, use sleep 0.1 (100ms) or sleep 0.001 (1ms) on systems with GNU sleep. For older systems, use usleep with microseconds, or fall back to Python/Perl for cross-platform compatibility.
Find elsewhere
🌐
Arch Linux Forums
bbs.archlinux.org › viewtopic.php
How does sleep command works? / GNU/Linux Discussion / Arch Linux Forums
you can also "ctrl-c" to cancel sleep while it's waiting. ... It looks like a loop that just continuously counts the number of nanoseconds that have passed to see if you've reached the requested time. Actually keeping track of nanoseconds is handled by timespec.
🌐
Linux Man Pages
man7.org › linux › man-pages › man1 › sleep.1.html
sleep(1) - Linux manual page
3 weeks ago - Pause for NUMBER seconds, where NUMBER is an integer or floating-point. SUFFIX may be 's','m','h', or 'd', for seconds, minutes, hours, days. With multiple arguments, pause for the sum of their values. --help display this help and exit --version output version information and exit · Written by Jim Meyering and Paul Eggert. Report bugs to: bug-coreutils@gnu.org GNU coreutils home page: <https://www.gnu.org/software/coreutils/> General help using GNU software: <https://www.gnu.org/gethelp/> Report any translation bugs to <https://translationproject.org/team/>
🌐
Reddit
reddit.com › r/c_programming › explain how the sleep command works.
r/C_Programming on Reddit: Explain how the sleep command works.
March 9, 2022 - One final issue: if your program should receive a signal while sleeping, the operating system will put it back on the eligible list right away, and the sleep() function will fail with EINTR. ... Meaning it calls the xnanosleep function for which the xnanosleep gnulib module is called.
🌐
nixCraft
cyberciti.biz › nixcraft › howto › bash shell › what does the sleep command do in linux?
What does the sleep command do in Linux? - nixCraft
December 13, 2022 - /bin/sleep is Linux or Unix command to delay for a specified amount of time. You can suspend the calling shell script for a specified time. For example, pause for 10 seconds or stop execution for 2 mintues. In other words, the sleep command pauses the execution on the next shell command for a given time. GNU version of sleep command supports additional options
🌐
Reddit
reddit.com › r/commandline › pop quiz: what does `sleep 1 2 3` do?
r/commandline on Reddit: Pop quiz: what does `sleep 1 2 3` do?
August 5, 2015 -

Here are the results across a few different systems (no shell built-ins though):

sysadment@freebsd10 $ (date +%s ; /bin/sleep 1 2 3 ; date +%s)
1438748148
usage: sleep seconds
1438748148

sysadment@macosx $ (date +%s ; /bin/sleep 1 2 3 ; date +%s)
1438748171
usage: sleep seconds
1438748171

sysadment@debian7 $ (date +%s ; /bin/sleep 1 2 3 ; date +%s)
1438748200
1438748206

Yeah, I didn't expect that last one either. GNU coreutils sleep, when given two or more arguments, sleeps for a time equal to the sum of the argument values. TIL

🌐
Wikipedia
en.wikipedia.org › wiki › Sleep_(command)
sleep (command) - Wikipedia
February 3, 2026 - However, sleep 5.5h (a floating point) is allowed. Consecutive executions of sleep can also be used. ... Sleep 5 hours, then sleep another 30 minutes. The GNU Project's implementation of sleep (part of coreutils) allows the user to pass an arbitrary floating point or multiple arguments, therefore sleep 5h 30m (a space separating hours and minutes is needed) will work on any system which uses GNU sleep, including Linux.
Top answer
1 of 8
87

Bash has a "loadable" sleep which supports fractional seconds, and eliminates overheads of an external command:

$ cd bash-3.2.48/examples/loadables
$ make sleep && mv sleep sleep.so
$ enable -f sleep.so sleep

Then:

$ which sleep
/usr/bin/sleep
$ builtin sleep
sleep: usage: sleep seconds[.fraction]
$ time (for f in `seq 1 10`; do builtin sleep 0.1; done)
real    0m1.000s
user    0m0.004s
sys     0m0.004s

The downside is that the loadables may not be provided with your bash binary, so you would need to compile them yourself as shown (though on Solaris it would not necessarily be as simple as above).

As of bash-4.4 (September 2016) all the loadables are now built and installed by default on platforms that support it, though they are built as separate shared-object files, and without a .so suffix. Unless your distro/OS has done something creative (sadly RHEL/CentOS 8 build bash-4.4 with loadable extensions deliberately removed), you should be able to do instead:

[ -z "$BASH_LOADABLES_PATH" ] &&
  BASH_LOADABLES_PATH=$(pkg-config bash --variable=loadablesdir 2>/dev/null)  
enable -f sleep sleep

(The man page implies BASH_LOADABLES_PATH is set automatically, I find this is not the case in the official distribution as of 4.4.12. If and when it is set correctly you need only enable -f filename commandname as required.)

If that's not suitable, the next easiest thing to do is build or obtain sleep from GNU coreutils, this supports the required feature. The POSIX sleep command is minimal, older Solaris versions implemented only that. Solaris 11 sleep does support fractional seconds.

As a last resort you could use perl (or any other scripting that you have to hand) with the caveat that initialising the interpreter may be comparable to the intended sleep time:

$ perl -e "select(undef,undef,undef,0.1);"
$ echo "after 100" | tclsh
2 of 8
183

The documentation for the sleep command from coreutils says:

Historical implementations of sleep have required that number be an integer, and only accepted a single argument without a suffix. However, GNU sleep accepts arbitrary floating point numbers. See Floating point.

Hence you can use sleep 0.1, sleep 1.0e-1 and similar arguments.

🌐
Linux Man Pages
man7.org › linux › man-pages › man3 › sleep.3.html
sleep(3) - Linux manual page
sleep() causes the calling thread to sleep either until the number of real-time seconds specified in seconds have elapsed or until a signal arrives which is not ignored.
Top answer
1 of 8
47

The "update" to question shows some misunderstanding of how modern OSs work.

The kernel is not "allowed" a time slice. The kernel is the thing that gives out time slices to user processes. The "timer" is not set to wake the sleeping process up - it is set to stop the currently running process.

In essence, the kernel attempts to fairly distribute the CPU time by stopping processes that are on CPU too long. For a simplified picture, let's say that no process is allowed to use the CPU more than 2 milliseconds. So, the kernel would set timer to 2 milliseconds, and let the process run. When the timer fires an interrupt, the kernel gets control. It saves the running process' current state (registers, instruction pointer and so on), and the control is not returned to it. Instead, another process is picked from the list of processes waiting to be given CPU, and the process that was interrupted goes to the back of the queue.

The sleeping process is simply not in the queue of things waiting for CPU. Instead, it's stored in the sleeping queue. Whenever kernel gets timer interrupt, the sleep queue is checked, and the processes whose time have come get transferred to "waiting for CPU" queue.

This is, of course, a gross simplification. It takes very sophisticated algorithms to ensure security, fairness, balance, prioritize, prevent starvation, do it all fast and with minimum amount of memory used for kernel data.

2 of 8
36

There's a kernel data structure called the sleep queue. It's a priority queue. Whenever a process is added to the sleep queue, the expiration time of the most-soon-to-be-awakened process is calculated, and a timer is set. At that time, the expired job is taken off the queue and the process resumes execution.

(amusing trivia: in older unix implementations, there was a queue for processes for which fork() had been called, but for which the child process had not been created. It was of course called the fork queue.)

HTH!

🌐
Linux Man Pages
linux.die.net › man › 1 › sleep
sleep(1): delay for specified amount of time - Linux man page
Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days. Unlike most implementations that ...