| .\" Copyright (C) 2008 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" |
| .\" %%%LICENSE_START(GPLv2+_SW_3_PARA) |
| .\" This program is free software; you can redistribute it and/or modify |
| .\" it under the terms of the GNU General Public License as published by |
| .\" the Free Software Foundation; either version 2 of the License, or |
| .\" (at your option) any later version. |
| .\" |
| .\" This program is distributed in the hope that it will be useful, |
| .\" but WITHOUT ANY WARRANTY; without even the implied warranty of |
| .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| .\" GNU General Public License for more details. |
| .\" |
| .\" You should have received a copy of the GNU General Public |
| .\" License along with this manual; if not, see |
| .\" <http://www.gnu.org/licenses/>. |
| .\" %%%LICENSE_END |
| .\" |
| .TH TIMERFD_CREATE 2 2021-03-22 Linux "Linux Programmer's Manual" |
| .SH NAME |
| timerfd_create, timerfd_settime, timerfd_gettime \- |
| timers that notify via file descriptors |
| .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 *" 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 |
| .BR CLOCK_MONOTONIC |
| clock does not measure the time while a system is suspended, the |
| .BR CLOCK_BOOTTIME |
| clock does include the time during which the system is suspended. |
| This is useful for applications that need to be suspend-aware. |
| .BR 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 |
| .IR flags |
| to change the behavior of |
| .BR timerfd_create (): |
| .TP 14 |
| .B TFD_NONBLOCK |
| Set the |
| .BR 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 contains two fields, |
| each of which is in turn a structure of type |
| .IR timespec : |
| .PP |
| .in +4n |
| .EX |
| struct timespec { |
| time_t tv_sec; /* Seconds */ |
| long tv_nsec; /* Nanoseconds */ |
| }; |
| |
| struct itimerspec { |
| struct timespec it_interval; /* Interval for periodic timer */ |
| struct timespec it_value; /* Initial expiration */ |
| }; |
| .EE |
| .in |
| .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 |
| .BR TFD_TIMER_CANCEL_ON_SET |
| If this flag is specified along with |
| .B TFD_TIMER_ABSTIME |
| and the clock for this timer is |
| .BR 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 |
| .IR 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 |
| .BR 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\(emthat 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 |
| .BR CLOCK_REALTIME |
| or |
| .BR CLOCK_REALTIME_ALARM , |
| the timer is absolute |
| .RB ( TFD_TIMER_ABSTIME ), |
| and the flag |
| .BR TFD_TIMER_CANCEL_ON_SET |
| was specified when calling |
| .BR timerfd_settime (), |
| then |
| .BR read (2) |
| fails with the error |
| .BR 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 |
| .BR CLOCK_REALTIME |
| or |
| .BR CLOCK_REALTIME_ALARM , |
| the timer is absolute |
| .RB ( TFD_TIMER_ABSTIME ), |
| and the flag |
| .BR 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 |
| .BR 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 |
| .BR CLOCK_REALTIME_ALARM |
| or |
| .BR CLOCK_BOOTTIME_ALARM |
| but the caller did not have the |
| .BR 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 valid a 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 2.6.29, and 2.2.2[78].some-stable-version. |
| .\" In older kernel versions, no check was made for invalid flags. |
| .I flags |
| is invalid. |
| .SH VERSIONS |
| These system calls are available on Linux since kernel 2.6.25. |
| Library support is provided by glibc since version 2.8. |
| .SH CONFORMING TO |
| These system calls are Linux-specific. |
| .SH NOTES |
| Suppose the following scenario for |
| .BR CLOCK_REALTIME |
| or |
| .BR CLOCK_REALTIME_ALARM |
| timer that was created with |
| .BR timerfd_create (): |
| .IP (a) 4 |
| The timer has been started |
| .RB ( timerfd_settime ()) |
| with the |
| .BR TFD_TIMER_ABSTIME |
| and |
| .BR TFD_TIMER_CANCEL_ON_SET |
| flags; |
| .IP (b) |
| A discontinuous change (e.g., |
| .BR settimeofday (2)) |
| is subsequently made to the |
| .BR CLOCK_REALTIME |
| clock; and |
| .IP (c) |
| 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 2 |
| 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 "\(haZ " " # 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 "\(haC " " # type control\-C to suspend the program" |
| .EE |
| .in |
| .SS Program source |
| \& |
| .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 <sys/timerfd.h> |
| #include <time.h> |
| #include <unistd.h> |
| #include <inttypes.h> /* Definition of PRIu64 */ |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <stdint.h> /* Definition of uint64_t */ |
| |
| #define handle_error(msg) \e |
| do { perror(msg); exit(EXIT_FAILURE); } while (0) |
| |
| static void |
| print_elapsed_time(void) |
| { |
| static struct timespec start; |
| struct timespec curr; |
| static int first_call = 1; |
| int secs, nsecs; |
| |
| if (first_call) { |
| first_call = 0; |
| if (clock_gettime(CLOCK_MONOTONIC, &start) == \-1) |
| handle_error("clock_gettime"); |
| } |
| |
| if (clock_gettime(CLOCK_MONOTONIC, &curr) == \-1) |
| handle_error("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[]) |
| { |
| struct itimerspec new_value; |
| int max_exp, fd; |
| struct timespec now; |
| uint64_t exp, tot_exp; |
| ssize_t s; |
| |
| 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) |
| handle_error("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) |
| handle_error("timerfd_create"); |
| |
| if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == \-1) |
| handle_error("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)) |
| handle_error("read"); |
| |
| tot_exp += exp; |
| print_elapsed_time(); |
| printf("read: %" PRIu64 "; total=%" PRIu64 "\en", exp, tot_exp); |
| } |
| |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .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 epoll (7), |
| .BR time (7) |