mirror of https://github.com/mkerrisk/man-pages
727 lines
18 KiB
Groff
727 lines
18 KiB
Groff
.\" 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)
|