diff options
Diffstat (limited to '')
-rw-r--r-- | man2/timerfd_create.2 | 700 |
1 files changed, 700 insertions, 0 deletions
diff --git a/man2/timerfd_create.2 b/man2/timerfd_create.2 new file mode 100644 index 0000000..6ceea56 --- /dev/null +++ b/man2/timerfd_create.2 @@ -0,0 +1,700 @@ +.\" Copyright (C) 2008 Michael Kerrisk <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: GPL-2.0-or-later +.\" +.TH timerfd_create 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +timerfd_create, timerfd_settime, timerfd_gettime \- +timers that notify via file descriptors +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.B #include <sys/timerfd.h> +.PP +.BI "int timerfd_create(int " clockid ", int " flags ); +.PP +.BI "int timerfd_settime(int " fd ", int " flags , +.BI " const struct itimerspec *" new_value , +.BI " struct itimerspec *_Nullable " old_value ); +.BI "int timerfd_gettime(int " fd ", struct itimerspec *" curr_value ); +.fi +.SH DESCRIPTION +These system calls create and operate on a timer +that delivers timer expiration notifications via a file descriptor. +They provide an alternative to the use of +.BR setitimer (2) +or +.BR timer_create (2), +with the advantage that the file descriptor may be monitored by +.BR select (2), +.BR poll (2), +and +.BR epoll (7). +.PP +The use of these three system calls is analogous to the use of +.BR timer_create (2), +.BR timer_settime (2), +and +.BR timer_gettime (2). +(There is no analog of +.BR timer_getoverrun (2), +since that functionality is provided by +.BR read (2), +as described below.) +.\" +.SS timerfd_create() +.BR timerfd_create () +creates a new timer object, +and returns a file descriptor that refers to that timer. +The +.I clockid +argument specifies the clock that is used to mark the progress +of the timer, and must be one of the following: +.TP +.B CLOCK_REALTIME +A settable system-wide real-time clock. +.TP +.B CLOCK_MONOTONIC +A nonsettable monotonically increasing clock that measures time +from some unspecified point in the past that does not change +after system startup. +.TP +.BR CLOCK_BOOTTIME " (Since Linux 3.15)" +.\" commit 4a2378a943f09907fb1ae35c15de917f60289c14 +Like +.BR CLOCK_MONOTONIC , +this is a monotonically increasing clock. +However, whereas the +.B CLOCK_MONOTONIC +clock does not measure the time while a system is suspended, the +.B CLOCK_BOOTTIME +clock does include the time during which the system is suspended. +This is useful for applications that need to be suspend-aware. +.B CLOCK_REALTIME +is not suitable for such applications, since that clock is affected +by discontinuous changes to the system clock. +.TP +.BR CLOCK_REALTIME_ALARM " (since Linux 3.11)" +.\" commit 11ffa9d6065f344a9bd769a2452f26f2f671e5f8 +This clock is like +.BR CLOCK_REALTIME , +but will wake the system if it is suspended. +The caller must have the +.B CAP_WAKE_ALARM +capability in order to set a timer against this clock. +.TP +.BR CLOCK_BOOTTIME_ALARM " (since Linux 3.11)" +.\" commit 11ffa9d6065f344a9bd769a2452f26f2f671e5f8 +This clock is like +.BR CLOCK_BOOTTIME , +but will wake the system if it is suspended. +The caller must have the +.B CAP_WAKE_ALARM +capability in order to set a timer against this clock. +.PP +See +.BR clock_getres (2) +for some further details on the above clocks. +.PP +The current value of each of these clocks can be retrieved using +.BR clock_gettime (2). +.PP +Starting with Linux 2.6.27, the following values may be bitwise ORed in +.I flags +to change the behavior of +.BR timerfd_create (): +.TP 14 +.B TFD_NONBLOCK +Set the +.B O_NONBLOCK +file status flag on the open file description (see +.BR open (2)) +referred to by the new file descriptor. +Using this flag saves extra calls to +.BR fcntl (2) +to achieve the same result. +.TP +.B TFD_CLOEXEC +Set the close-on-exec +.RB ( FD_CLOEXEC ) +flag on the new file descriptor. +See the description of the +.B O_CLOEXEC +flag in +.BR open (2) +for reasons why this may be useful. +.PP +In Linux versions up to and including 2.6.26, +.I flags +must be specified as zero. +.SS timerfd_settime() +.BR timerfd_settime () +arms (starts) or disarms (stops) +the timer referred to by the file descriptor +.IR fd . +.PP +The +.I new_value +argument specifies the initial expiration and interval for the timer. +The +.I itimerspec +structure used for this argument is described in +.BR itimerspec (3type). +.PP +.I new_value.it_value +specifies the initial expiration of the timer, +in seconds and nanoseconds. +Setting either field of +.I new_value.it_value +to a nonzero value arms the timer. +Setting both fields of +.I new_value.it_value +to zero disarms the timer. +.PP +Setting one or both fields of +.I new_value.it_interval +to nonzero values specifies the period, in seconds and nanoseconds, +for repeated timer expirations after the initial expiration. +If both fields of +.I new_value.it_interval +are zero, the timer expires just once, at the time specified by +.IR new_value.it_value . +.PP +By default, +the initial expiration time specified in +.I new_value +is interpreted relative to the current time +on the timer's clock at the time of the call (i.e., +.I new_value.it_value +specifies a time relative to the current value of the clock specified by +.IR clockid ). +An absolute timeout can be selected via the +.I flags +argument. +.PP +The +.I flags +argument is a bit mask that can include the following values: +.TP +.B TFD_TIMER_ABSTIME +Interpret +.I new_value.it_value +as an absolute value on the timer's clock. +The timer will expire when the value of the timer's +clock reaches the value specified in +.IR new_value.it_value . +.TP +.B TFD_TIMER_CANCEL_ON_SET +If this flag is specified along with +.B TFD_TIMER_ABSTIME +and the clock for this timer is +.B CLOCK_REALTIME +or +.BR CLOCK_REALTIME_ALARM , +then mark this timer as cancelable if the real-time clock +undergoes a discontinuous change +.RB ( settimeofday (2), +.BR clock_settime (2), +or similar). +When such changes occur, a current or future +.BR read (2) +from the file descriptor will fail with the error +.BR ECANCELED . +.PP +If the +.I old_value +argument is not NULL, then the +.I itimerspec +structure that it points to is used to return the setting of the timer +that was current at the time of the call; +see the description of +.BR timerfd_gettime () +following. +.\" +.SS timerfd_gettime() +.BR timerfd_gettime () +returns, in +.IR curr_value , +an +.I itimerspec +structure that contains the current setting of the timer +referred to by the file descriptor +.IR fd . +.PP +The +.I it_value +field returns the amount of time +until the timer will next expire. +If both fields of this structure are zero, +then the timer is currently disarmed. +This field always contains a relative value, regardless of whether the +.B TFD_TIMER_ABSTIME +flag was specified when setting the timer. +.PP +The +.I it_interval +field returns the interval of the timer. +If both fields of this structure are zero, +then the timer is set to expire just once, at the time specified by +.IR curr_value.it_value . +.SS Operating on a timer file descriptor +The file descriptor returned by +.BR timerfd_create () +supports the following additional operations: +.TP +.BR read (2) +If the timer has already expired one or more times since +its settings were last modified using +.BR timerfd_settime (), +or since the last successful +.BR read (2), +then the buffer given to +.BR read (2) +returns an unsigned 8-byte integer +.RI ( uint64_t ) +containing the number of expirations that have occurred. +(The returned value is in host byte order\[em]that is, +the native byte order for integers on the host machine.) +.IP +If no timer expirations have occurred at the time of the +.BR read (2), +then the call either blocks until the next timer expiration, +or fails with the error +.B EAGAIN +if the file descriptor has been made nonblocking +(via the use of the +.BR fcntl (2) +.B F_SETFL +operation to set the +.B O_NONBLOCK +flag). +.IP +A +.BR read (2) +fails with the error +.B EINVAL +if the size of the supplied buffer is less than 8 bytes. +.IP +If the associated clock is either +.B CLOCK_REALTIME +or +.BR CLOCK_REALTIME_ALARM , +the timer is absolute +.RB ( TFD_TIMER_ABSTIME ), +and the flag +.B TFD_TIMER_CANCEL_ON_SET +was specified when calling +.BR timerfd_settime (), +then +.BR read (2) +fails with the error +.B ECANCELED +if the real-time clock undergoes a discontinuous change. +(This allows the reading application to discover +such discontinuous changes to the clock.) +.IP +If the associated clock is either +.B CLOCK_REALTIME +or +.BR CLOCK_REALTIME_ALARM , +the timer is absolute +.RB ( TFD_TIMER_ABSTIME ), +and the flag +.B TFD_TIMER_CANCEL_ON_SET +was +.I not +specified when calling +.BR timerfd_settime (), +then a discontinuous negative change to the clock (e.g., +.BR clock_settime (2)) +may cause +.BR read (2) +to unblock, but return a value of 0 (i.e., no bytes read), +if the clock change occurs after the time expired, +but before the +.BR read (2) +on the file descriptor. +.TP +.BR poll "(2), " select "(2) (and similar)" +The file descriptor is readable +(the +.BR select (2) +.I readfds +argument; the +.BR poll (2) +.B POLLIN +flag) +if one or more timer expirations have occurred. +.IP +The file descriptor also supports the other file-descriptor +multiplexing APIs: +.BR pselect (2), +.BR ppoll (2), +and +.BR epoll (7). +.TP +.BR ioctl (2) +The following timerfd-specific command is supported: +.RS +.TP +.BR TFD_IOC_SET_TICKS " (since Linux 3.17)" +.\" commit 5442e9fbd7c23172a1c9bc736629cd123a9923f0 +Adjust the number of timer expirations that have occurred. +The argument is a pointer to a nonzero 8-byte integer +.RI ( uint64_t *) +containing the new number of expirations. +Once the number is set, any waiter on the timer is woken up. +The only purpose of this command is to restore the expirations +for the purpose of checkpoint/restore. +This operation is available only if the kernel was configured with the +.B CONFIG_CHECKPOINT_RESTORE +option. +.RE +.TP +.BR close (2) +When the file descriptor is no longer required it should be closed. +When all file descriptors associated with the same timer object +have been closed, +the timer is disarmed and its resources are freed by the kernel. +.\" +.SS fork(2) semantics +After a +.BR fork (2), +the child inherits a copy of the file descriptor created by +.BR timerfd_create (). +The file descriptor refers to the same underlying +timer object as the corresponding file descriptor in the parent, +and +.BR read (2)s +in the child will return information about +expirations of the timer. +.\" +.SS execve(2) semantics +A file descriptor created by +.BR timerfd_create () +is preserved across +.BR execve (2), +and continues to generate timer expirations if the timer was armed. +.SH RETURN VALUE +On success, +.BR timerfd_create () +returns a new file descriptor. +On error, \-1 is returned and +.I errno +is set to indicate the error. +.PP +.BR timerfd_settime () +and +.BR timerfd_gettime () +return 0 on success; +on error they return \-1, and set +.I errno +to indicate the error. +.SH ERRORS +.BR timerfd_create () +can fail with the following errors: +.TP +.B EINVAL +The +.I clockid +is not valid. +.TP +.B EINVAL +.I flags +is invalid; +or, in Linux 2.6.26 or earlier, +.I flags +is nonzero. +.TP +.B EMFILE +The per-process limit on the number of open file descriptors has been reached. +.TP +.B ENFILE +The system-wide limit on the total number of open files has been +reached. +.TP +.B ENODEV +Could not mount (internal) anonymous inode device. +.TP +.B ENOMEM +There was insufficient kernel memory to create the timer. +.TP +.B EPERM +.I clockid +was +.B CLOCK_REALTIME_ALARM +or +.B CLOCK_BOOTTIME_ALARM +but the caller did not have the +.B CAP_WAKE_ALARM +capability. +.PP +.BR timerfd_settime () +and +.BR timerfd_gettime () +can fail with the following errors: +.TP +.B EBADF +.I fd +is not a valid file descriptor. +.TP +.B EFAULT +.IR new_value , +.IR old_value , +or +.I curr_value +is not a valid pointer. +.TP +.B EINVAL +.I fd +is not a valid timerfd file descriptor. +.PP +.BR timerfd_settime () +can also fail with the following errors: +.TP +.B ECANCELED +See NOTES. +.TP +.B EINVAL +.I new_value +is not properly initialized (one of the +.I tv_nsec +falls outside the range zero to 999,999,999). +.TP +.B EINVAL +.\" This case only checked since Linux 2.6.29, and Linux 2.2.2[78].some-stable-version. +.\" In older kernel versions, no check was made for invalid flags. +.I flags +is invalid. +.SH STANDARDS +Linux. +.SH HISTORY +Linux 2.6.25, +glibc 2.8. +.SH NOTES +Suppose the following scenario for +.B CLOCK_REALTIME +or +.B CLOCK_REALTIME_ALARM +timer that was created with +.BR timerfd_create (): +.IP (1) 5 +The timer has been started +.RB ( timerfd_settime ()) +with the +.B TFD_TIMER_ABSTIME +and +.B TFD_TIMER_CANCEL_ON_SET +flags; +.IP (2) +A discontinuous change (e.g., +.BR settimeofday (2)) +is subsequently made to the +.B CLOCK_REALTIME +clock; and +.IP (3) +the caller once more calls +.BR timerfd_settime () +to rearm the timer (without first doing a +.BR read (2) +on the file descriptor). +.PP +In this case the following occurs: +.IP \[bu] 3 +The +.BR timerfd_settime () +returns \-1 with +.I errno +set to +.BR ECANCELED . +(This enables the caller to know that the previous timer was affected +by a discontinuous change to the clock.) +.IP \[bu] +The timer +.I "is successfully rearmed" +with the settings provided in the second +.BR timerfd_settime () +call. +(This was probably an implementation accident, but won't be fixed now, +in case there are applications that depend on this behaviour.) +.SH BUGS +Currently, +.\" 2.6.29 +.BR timerfd_create () +supports fewer types of clock IDs than +.BR timer_create (2). +.SH EXAMPLES +The following program creates a timer and then monitors its progress. +The program accepts up to three command-line arguments. +The first argument specifies the number of seconds for +the initial expiration of the timer. +The second argument specifies the interval for the timer, in seconds. +The third argument specifies the number of times the program should +allow the timer to expire before terminating. +The second and third command-line arguments are optional. +.PP +The following shell session demonstrates the use of the program: +.PP +.in +4n +.EX +.RB "$" " a.out 3 1 100" +0.000: timer started +3.000: read: 1; total=1 +4.000: read: 1; total=2 +.BR "\[ha]Z " " # type control\-Z to suspend the program" +[1]+ Stopped ./timerfd3_demo 3 1 100 +.RB "$ " "fg" " # Resume execution after a few seconds" +a.out 3 1 100 +9.660: read: 5; total=7 +10.000: read: 1; total=8 +11.000: read: 1; total=9 +.BR "\[ha]C " " # type control\-C to suspend the program" +.EE +.in +.SS Program source +\& +.\" SRC BEGIN (timerfd_create.c) +.EX +.\" The commented out code here is what we currently need until +.\" the required stuff is in glibc +.\" +.\" +.\"/* Link with \-lrt */ +.\"#define _GNU_SOURCE +.\"#include <sys/syscall.h> +.\"#include <unistd.h> +.\"#include <time.h> +.\"#if defined(__i386__) +.\"#define __NR_timerfd_create 322 +.\"#define __NR_timerfd_settime 325 +.\"#define __NR_timerfd_gettime 326 +.\"#endif +.\" +.\"static int +.\"timerfd_create(int clockid, int flags) +.\"{ +.\" return syscall(__NR_timerfd_create, clockid, flags); +.\"} +.\" +.\"static int +.\"timerfd_settime(int fd, int flags, struct itimerspec *new_value, +.\" struct itimerspec *curr_value) +.\"{ +.\" return syscall(__NR_timerfd_settime, fd, flags, new_value, +.\" curr_value); +.\"} +.\" +.\"static int +.\"timerfd_gettime(int fd, struct itimerspec *curr_value) +.\"{ +.\" return syscall(__NR_timerfd_gettime, fd, curr_value); +.\"} +.\" +.\"#define TFD_TIMER_ABSTIME (1 << 0) +.\" +.\"//////////////////////////////////////////////////////////// +#include <err.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/timerfd.h> +#include <time.h> +#include <unistd.h> +\& +static void +print_elapsed_time(void) +{ + int secs, nsecs; + static int first_call = 1; + struct timespec curr; + static struct timespec start; +\& + if (first_call) { + first_call = 0; + if (clock_gettime(CLOCK_MONOTONIC, &start) == \-1) + err(EXIT_FAILURE, "clock_gettime"); + } +\& + if (clock_gettime(CLOCK_MONOTONIC, &curr) == \-1) + err(EXIT_FAILURE, "clock_gettime"); +\& + secs = curr.tv_sec \- start.tv_sec; + nsecs = curr.tv_nsec \- start.tv_nsec; + if (nsecs < 0) { + secs\-\-; + nsecs += 1000000000; + } + printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000); +} +\& +int +main(int argc, char *argv[]) +{ + int fd; + ssize_t s; + uint64_t exp, tot_exp, max_exp; + struct timespec now; + struct itimerspec new_value; +\& + if (argc != 2 && argc != 4) { + fprintf(stderr, "%s init\-secs [interval\-secs max\-exp]\en", + argv[0]); + exit(EXIT_FAILURE); + } +\& + if (clock_gettime(CLOCK_REALTIME, &now) == \-1) + err(EXIT_FAILURE, "clock_gettime"); +\& + /* Create a CLOCK_REALTIME absolute timer with initial + expiration and interval as specified in command line. */ +\& + new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]); + new_value.it_value.tv_nsec = now.tv_nsec; + if (argc == 2) { + new_value.it_interval.tv_sec = 0; + max_exp = 1; + } else { + new_value.it_interval.tv_sec = atoi(argv[2]); + max_exp = atoi(argv[3]); + } + new_value.it_interval.tv_nsec = 0; +\& + fd = timerfd_create(CLOCK_REALTIME, 0); + if (fd == \-1) + err(EXIT_FAILURE, "timerfd_create"); +\& + if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == \-1) + err(EXIT_FAILURE, "timerfd_settime"); +\& + print_elapsed_time(); + printf("timer started\en"); +\& + for (tot_exp = 0; tot_exp < max_exp;) { + s = read(fd, &exp, sizeof(uint64_t)); + if (s != sizeof(uint64_t)) + err(EXIT_FAILURE, "read"); +\& + tot_exp += exp; + print_elapsed_time(); + printf("read: %" PRIu64 "; total=%" PRIu64 "\en", exp, tot_exp); + } +\& + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR eventfd (2), +.BR poll (2), +.BR read (2), +.BR select (2), +.BR setitimer (2), +.BR signalfd (2), +.BR timer_create (2), +.BR timer_gettime (2), +.BR timer_settime (2), +.BR timespec (3), +.BR epoll (7), +.BR time (7) |