summaryrefslogtreecommitdiffstats
path: root/man2/timerfd_create.2
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--man2/timerfd_create.2700
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)