mirror of https://github.com/mkerrisk/man-pages
502 lines
14 KiB
Groff
502 lines
14 KiB
Groff
.\" Copyright (c) 2009 Linux Foundation, written by Michael Kerrisk
|
|
.\" <mtk.manpages@gmail.com>
|
|
.\"
|
|
.\" %%%LICENSE_START(VERBATIM)
|
|
.\" Permission is granted to make and distribute verbatim copies of this
|
|
.\" manual provided the copyright notice and this permission notice are
|
|
.\" preserved on all copies.
|
|
.\"
|
|
.\" Permission is granted to copy and distribute modified versions of this
|
|
.\" manual under the conditions for verbatim copying, provided that the
|
|
.\" entire resulting derived work is distributed under the terms of a
|
|
.\" permission notice identical to this one.
|
|
.\"
|
|
.\" Since the Linux kernel and libraries are constantly changing, this
|
|
.\" manual page may be incorrect or out-of-date. The author(s) assume no
|
|
.\" responsibility for errors or omissions, or for damages resulting from
|
|
.\" the use of the information contained herein. The author(s) may not
|
|
.\" have taken the same level of care in the production of this manual,
|
|
.\" which is licensed free of charge, as they might when working
|
|
.\" professionally.
|
|
.\"
|
|
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
.\" the source, must acknowledge the copyright and authors of this work.
|
|
.\" %%%LICENSE_END
|
|
.\"
|
|
.TH TIMER_CREATE 2 2020-04-11 Linux "Linux Programmer's Manual"
|
|
.SH NAME
|
|
timer_create \- create a POSIX per-process timer
|
|
.SH SYNOPSIS
|
|
.nf
|
|
.B #include <signal.h>
|
|
.B #include <time.h>
|
|
.PP
|
|
.BI "int timer_create(clockid_t " clockid ", struct sigevent *" sevp ,
|
|
.BI " timer_t *" timerid );
|
|
.fi
|
|
.PP
|
|
Link with \fI\-lrt\fP.
|
|
.PP
|
|
.RS -4
|
|
Feature Test Macro Requirements for glibc (see
|
|
.BR feature_test_macros (7)):
|
|
.RE
|
|
.PP
|
|
.BR timer_create ():
|
|
_POSIX_C_SOURCE\ >=\ 199309L
|
|
.SH DESCRIPTION
|
|
.BR timer_create ()
|
|
creates a new per-process interval timer.
|
|
The ID of the new timer is returned in the buffer pointed to by
|
|
.IR timerid ,
|
|
which must be a non-null pointer.
|
|
This ID is unique within the process, until the timer is deleted.
|
|
The new timer is initially disarmed.
|
|
.PP
|
|
The
|
|
.I clockid
|
|
argument specifies the clock that the new timer uses to measure time.
|
|
It can be specified as one of the following values:
|
|
.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.
|
|
.\" Note: the CLOCK_MONOTONIC_RAW clock added for clock_gettime()
|
|
.\" in 2.6.28 is not supported for POSIX timers -- mtk, Feb 2009
|
|
.TP
|
|
.BR CLOCK_PROCESS_CPUTIME_ID " (since Linux 2.6.12)"
|
|
A clock that measures (user and system) CPU time consumed by
|
|
(all of the threads in) the calling process.
|
|
.TP
|
|
.BR CLOCK_THREAD_CPUTIME_ID " (since Linux 2.6.12)"
|
|
A clock that measures (user and system) CPU time consumed by
|
|
the calling thread.
|
|
.\" The CLOCK_MONOTONIC_RAW that was added in 2.6.28 can't be used
|
|
.\" to create a timer -- mtk, Feb 2009
|
|
.TP
|
|
.BR CLOCK_BOOTTIME " (Since Linux 2.6.39)"
|
|
.\" commit 70a08cca1227dc31c784ec930099a4417a06e7d0
|
|
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.0)"
|
|
.\" commit 9a7adcf5c6dea63d2e47e6f6d2f7a6c9f48b9337
|
|
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.0)"
|
|
.\" commit 9a7adcf5c6dea63d2e47e6f6d2f7a6c9f48b9337
|
|
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.
|
|
.TP
|
|
.BR CLOCK_TAI " (since Linux 3.10)"
|
|
A system-wide clock derived from wall-clock time but ignoring leap seconds.
|
|
.PP
|
|
See
|
|
.BR clock_getres (2)
|
|
for some further details on the above clocks.
|
|
.PP
|
|
As well as the above values,
|
|
.I clockid
|
|
can be specified as the
|
|
.I clockid
|
|
returned by a call to
|
|
.BR clock_getcpuclockid (3)
|
|
or
|
|
.BR pthread_getcpuclockid (3).
|
|
.PP
|
|
The
|
|
.I sevp
|
|
argument points to a
|
|
.I sigevent
|
|
structure that specifies how the caller
|
|
should be notified when the timer expires.
|
|
For the definition and general details of this structure, see
|
|
.BR sigevent (7).
|
|
.PP
|
|
The
|
|
.I sevp.sigev_notify
|
|
field can have the following values:
|
|
.TP
|
|
.BR SIGEV_NONE
|
|
Don't asynchronously notify when the timer expires.
|
|
Progress of the timer can be monitored using
|
|
.BR timer_gettime (2).
|
|
.TP
|
|
.BR SIGEV_SIGNAL
|
|
Upon timer expiration, generate the signal
|
|
.I sigev_signo
|
|
for the process.
|
|
See
|
|
.BR sigevent (7)
|
|
for general details.
|
|
The
|
|
.I si_code
|
|
field of the
|
|
.I siginfo_t
|
|
structure will be set to
|
|
.BR SI_TIMER .
|
|
At any point in time,
|
|
at most one signal is queued to the process for a given timer; see
|
|
.BR timer_getoverrun (2)
|
|
for more details.
|
|
.TP
|
|
.BR SIGEV_THREAD
|
|
Upon timer expiration, invoke
|
|
.I sigev_notify_function
|
|
as if it were the start function of a new thread.
|
|
See
|
|
.BR sigevent (7)
|
|
for details.
|
|
.TP
|
|
.BR SIGEV_THREAD_ID " (Linux-specific)"
|
|
As for
|
|
.BR SIGEV_SIGNAL ,
|
|
but the signal is targeted at the thread whose ID is given in
|
|
.IR sigev_notify_thread_id ,
|
|
which must be a thread in the same process as the caller.
|
|
The
|
|
.IR sigev_notify_thread_id
|
|
field specifies a kernel thread ID, that is, the value returned by
|
|
.BR clone (2)
|
|
or
|
|
.BR gettid (2).
|
|
This flag is intended only for use by threading libraries.
|
|
.PP
|
|
Specifying
|
|
.I sevp
|
|
as NULL is equivalent to specifying a pointer to a
|
|
.I sigevent
|
|
structure in which
|
|
.I sigev_notify
|
|
is
|
|
.BR SIGEV_SIGNAL ,
|
|
.I sigev_signo
|
|
is
|
|
.BR SIGALRM ,
|
|
and
|
|
.I sigev_value.sival_int
|
|
is the timer ID.
|
|
.SH RETURN VALUE
|
|
On success,
|
|
.BR timer_create ()
|
|
returns 0, and the ID of the new timer is placed in
|
|
.IR *timerid .
|
|
On failure, \-1 is returned, and
|
|
.I errno
|
|
is set to indicate the error.
|
|
.SH ERRORS
|
|
.TP
|
|
.B EAGAIN
|
|
Temporary error during kernel allocation of timer structures.
|
|
.TP
|
|
.B EINVAL
|
|
Clock ID,
|
|
.IR sigev_notify ,
|
|
.IR sigev_signo ,
|
|
or
|
|
.IR sigev_notify_thread_id
|
|
is invalid.
|
|
.TP
|
|
.B ENOMEM
|
|
.\" glibc layer: malloc()
|
|
Could not allocate memory.
|
|
.TP
|
|
.B ENOTSUP
|
|
The kernel does not support creating a timer against this
|
|
.IR clockid .
|
|
.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.
|
|
.SH VERSIONS
|
|
This system call is available since Linux 2.6.
|
|
.SH CONFORMING TO
|
|
POSIX.1-2001, POSIX.1-2008.
|
|
.SH NOTES
|
|
A program may create multiple interval timers using
|
|
.BR timer_create ().
|
|
.PP
|
|
Timers are not inherited by the child of a
|
|
.BR fork (2),
|
|
and are disarmed and deleted during an
|
|
.BR execve (2).
|
|
.PP
|
|
The kernel preallocates a "queued real-time signal"
|
|
for each timer created using
|
|
.BR timer_create ().
|
|
Consequently, the number of timers is limited by the
|
|
.BR RLIMIT_SIGPENDING
|
|
resource limit (see
|
|
.BR setrlimit (2)).
|
|
.PP
|
|
The timers created by
|
|
.BR timer_create ()
|
|
are commonly known as "POSIX (interval) timers".
|
|
The POSIX timers API consists of the following interfaces:
|
|
.IP * 3
|
|
.BR timer_create ():
|
|
Create a timer.
|
|
.IP *
|
|
.BR timer_settime (2):
|
|
Arm (start) or disarm (stop) a timer.
|
|
.IP *
|
|
.BR timer_gettime (2):
|
|
Fetch the time remaining until the next expiration of a timer,
|
|
along with the interval setting of the timer.
|
|
.IP *
|
|
.BR timer_getoverrun (2):
|
|
Return the overrun count for the last timer expiration.
|
|
.IP *
|
|
.BR timer_delete (2):
|
|
Disarm and delete a timer.
|
|
.PP
|
|
Since Linux 3.10, the
|
|
.IR /proc/[pid]/timers
|
|
file can be used to list the POSIX timers for the process with PID
|
|
.IR pid .
|
|
See
|
|
.BR proc (5)
|
|
for further information.
|
|
.PP
|
|
Since Linux 4.10,
|
|
.\" baa73d9e478ff32d62f3f9422822b59dd9a95a21
|
|
support for POSIX timers is a configurable option that is enabled by default.
|
|
Kernel support can be disabled via the
|
|
.BR CONFIG_POSIX_TIMERS
|
|
option.
|
|
.\"
|
|
.SS C library/kernel differences
|
|
Part of the implementation of the POSIX timers API is provided by glibc.
|
|
.\" See nptl/sysdeps/unix/sysv/linux/timer_create.c
|
|
In particular:
|
|
.IP * 3
|
|
Much of the functionality for
|
|
.BR SIGEV_THREAD
|
|
is implemented within glibc, rather than the kernel.
|
|
(This is necessarily so,
|
|
since the thread involved in handling the notification is one
|
|
that must be managed by the C library POSIX threads implementation.)
|
|
Although the notification delivered to the process is via a thread,
|
|
internally the NPTL implementation uses a
|
|
.I sigev_notify
|
|
value of
|
|
.BR SIGEV_THREAD_ID
|
|
along with a real-time signal that is reserved by the implementation (see
|
|
.BR nptl (7)).
|
|
.IP *
|
|
The implementation of the default case where
|
|
.I evp
|
|
is NULL is handled inside glibc,
|
|
which invokes the underlying system call with a suitably populated
|
|
.I sigevent
|
|
structure.
|
|
.IP *
|
|
The timer IDs presented at user level are maintained by glibc,
|
|
which maps these IDs to the timer IDs employed by the kernel.
|
|
.\" See the glibc source file kernel-posix-timers.h for the structure
|
|
.\" that glibc uses to map user-space timer IDs to kernel timer IDs
|
|
.\" The kernel-level timer ID is exposed via siginfo.si_tid.
|
|
.PP
|
|
The POSIX timers system calls first appeared in Linux 2.6.
|
|
Prior to this,
|
|
glibc provided an incomplete user-space implementation
|
|
.RB ( CLOCK_REALTIME
|
|
timers only) using POSIX threads,
|
|
and in glibc versions before 2.17,
|
|
.\" glibc commit 93a78ac437ba44f493333d7e2a4b0249839ce460
|
|
the implementation falls back to this technique on systems
|
|
running pre-2.6 Linux kernels.
|
|
.SH EXAMPLES
|
|
The program below takes two arguments: a sleep period in seconds,
|
|
and a timer frequency in nanoseconds.
|
|
The program establishes a handler for the signal it uses for the timer,
|
|
blocks that signal,
|
|
creates and arms a timer that expires with the given frequency,
|
|
sleeps for the specified number of seconds,
|
|
and then unblocks the timer signal.
|
|
Assuming that the timer expired at least once while the program slept,
|
|
the signal handler will be invoked,
|
|
and the handler displays some information about the timer notification.
|
|
The program terminates after one invocation of the signal handler.
|
|
.PP
|
|
In the following example run, the program sleeps for 1 second,
|
|
after creating a timer that has a frequency of 100 nanoseconds.
|
|
By the time the signal is unblocked and delivered,
|
|
there have been around ten million overruns.
|
|
.PP
|
|
.in +4n
|
|
.EX
|
|
$ \fB./a.out 1 100\fP
|
|
Establishing handler for signal 34
|
|
Blocking signal 34
|
|
timer ID is 0x804c008
|
|
Sleeping for 1 seconds
|
|
Unblocking signal 34
|
|
Caught signal 34
|
|
sival_ptr = 0xbfb174f4; *sival_ptr = 0x804c008
|
|
overrun count = 10004886
|
|
.EE
|
|
.in
|
|
.SS Program source
|
|
\&
|
|
.EX
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
|
|
#define CLOCKID CLOCK_REALTIME
|
|
#define SIG SIGRTMIN
|
|
|
|
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
|
|
} while (0)
|
|
|
|
static void
|
|
print_siginfo(siginfo_t *si)
|
|
{
|
|
timer_t *tidp;
|
|
int or;
|
|
|
|
tidp = si\->si_value.sival_ptr;
|
|
|
|
printf(" sival_ptr = %p; ", si\->si_value.sival_ptr);
|
|
printf(" *sival_ptr = %#jx\en", (uintmax_t) *tidp);
|
|
|
|
or = timer_getoverrun(*tidp);
|
|
if (or == \-1)
|
|
errExit("timer_getoverrun");
|
|
else
|
|
printf(" overrun count = %d\en", or);
|
|
}
|
|
|
|
static void
|
|
handler(int sig, siginfo_t *si, void *uc)
|
|
{
|
|
/* Note: calling printf() from a signal handler is not safe
|
|
(and should not be done in production programs), since
|
|
printf() is not async\-signal\-safe; see signal-safety(7).
|
|
Nevertheless, we use printf() here as a simple way of
|
|
showing that the handler was called. */
|
|
|
|
printf("Caught signal %d\en", sig);
|
|
print_siginfo(si);
|
|
signal(sig, SIG_IGN);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
timer_t timerid;
|
|
struct sigevent sev;
|
|
struct itimerspec its;
|
|
long long freq_nanosecs;
|
|
sigset_t mask;
|
|
struct sigaction sa;
|
|
|
|
if (argc != 3) {
|
|
fprintf(stderr, "Usage: %s <sleep\-secs> <freq\-nanosecs>\en",
|
|
argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Establish handler for timer signal */
|
|
|
|
printf("Establishing handler for signal %d\en", SIG);
|
|
sa.sa_flags = SA_SIGINFO;
|
|
sa.sa_sigaction = handler;
|
|
sigemptyset(&sa.sa_mask);
|
|
if (sigaction(SIG, &sa, NULL) == \-1)
|
|
errExit("sigaction");
|
|
|
|
/* Block timer signal temporarily */
|
|
|
|
printf("Blocking signal %d\en", SIG);
|
|
sigemptyset(&mask);
|
|
sigaddset(&mask, SIG);
|
|
if (sigprocmask(SIG_SETMASK, &mask, NULL) == \-1)
|
|
errExit("sigprocmask");
|
|
|
|
/* Create the timer */
|
|
|
|
sev.sigev_notify = SIGEV_SIGNAL;
|
|
sev.sigev_signo = SIG;
|
|
sev.sigev_value.sival_ptr = &timerid;
|
|
if (timer_create(CLOCKID, &sev, &timerid) == \-1)
|
|
errExit("timer_create");
|
|
|
|
printf("timer ID is %#jx\en", (uintmax_t) timerid);
|
|
|
|
/* Start the timer */
|
|
|
|
freq_nanosecs = atoll(argv[2]);
|
|
its.it_value.tv_sec = freq_nanosecs / 1000000000;
|
|
its.it_value.tv_nsec = freq_nanosecs % 1000000000;
|
|
its.it_interval.tv_sec = its.it_value.tv_sec;
|
|
its.it_interval.tv_nsec = its.it_value.tv_nsec;
|
|
|
|
if (timer_settime(timerid, 0, &its, NULL) == \-1)
|
|
errExit("timer_settime");
|
|
|
|
/* Sleep for a while; meanwhile, the timer may expire
|
|
multiple times */
|
|
|
|
printf("Sleeping for %d seconds\en", atoi(argv[1]));
|
|
sleep(atoi(argv[1]));
|
|
|
|
/* Unlock the timer signal, so that timer notification
|
|
can be delivered */
|
|
|
|
printf("Unblocking signal %d\en", SIG);
|
|
if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == \-1)
|
|
errExit("sigprocmask");
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
.EE
|
|
.SH SEE ALSO
|
|
.ad l
|
|
.nh
|
|
.BR clock_gettime (2),
|
|
.BR setitimer (2),
|
|
.BR timer_delete (2),
|
|
.BR timer_getoverrun (2),
|
|
.BR timer_settime (2),
|
|
.BR timerfd_create (2),
|
|
.BR clock_getcpuclockid (3),
|
|
.BR pthread_getcpuclockid (3),
|
|
.BR pthreads (7),
|
|
.BR sigevent (7),
|
|
.BR signal (7),
|
|
.BR time (7)
|