summaryrefslogtreecommitdiffstats
path: root/man2/timer_create.2
diff options
context:
space:
mode:
Diffstat (limited to 'man2/timer_create.2')
-rw-r--r--man2/timer_create.2487
1 files changed, 487 insertions, 0 deletions
diff --git a/man2/timer_create.2 b/man2/timer_create.2
new file mode 100644
index 0000000..3265b27
--- /dev/null
+++ b/man2/timer_create.2
@@ -0,0 +1,487 @@
+.\" Copyright (c) 2009 Linux Foundation, written by Michael Kerrisk
+.\" <mtk.manpages@gmail.com>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH timer_create 2 2023-05-03 "Linux man-pages 6.05.01"
+.SH NAME
+timer_create \- create a POSIX per-process timer
+.SH LIBRARY
+Real-time library
+.RI ( librt ", " \-lrt )
+.SH SYNOPSIS
+.nf
+.BR "#include <signal.h>" " /* Definition of " SIGEV_* " constants */"
+.B #include <time.h>
+.PP
+.BI "int timer_create(clockid_t " clockid ,
+.BI " struct sigevent *_Nullable restrict " sevp ,
+.BI " timer_t *restrict " timerid );
+.fi
+.PP
+.RS -4
+Feature Test Macro Requirements for glibc (see
+.BR feature_test_macros (7)):
+.RE
+.PP
+.BR timer_create ():
+.nf
+ _POSIX_C_SOURCE >= 199309L
+.fi
+.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 Linux 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 Linux 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
+.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.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
+.B SIGEV_NONE
+Don't asynchronously notify when the timer expires.
+Progress of the timer can be monitored using
+.BR timer_gettime (2).
+.TP
+.B 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
+.B 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
+.I 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
+.I 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
+.B CLOCK_REALTIME_ALARM
+or
+.B CLOCK_BOOTTIME_ALARM
+but the caller did not have the
+.B CAP_WAKE_ALARM
+capability.
+.SH VERSIONS
+.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 \[bu] 3
+Much of the functionality for
+.B 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
+.B SIGEV_THREAD_ID
+along with a real-time signal that is reserved by the implementation (see
+.BR nptl (7)).
+.IP \[bu]
+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 \[bu]
+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.
+.SH STANDARDS
+POSIX.1-2008.
+.SH HISTORY
+Linux 2.6.
+POSIX.1-2001.
+.PP
+Prior to Linux 2.6,
+glibc provided an incomplete user-space implementation
+.RB ( CLOCK_REALTIME
+timers only) using POSIX threads,
+and before glibc 2.17,
+.\" glibc commit 93a78ac437ba44f493333d7e2a4b0249839ce460
+the implementation falls back to this technique on systems
+running kernels older than Linux 2.6.
+.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
+.B 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:
+.TP
+.BR timer_create ()
+Create a timer.
+.TP
+.BR timer_settime (2)
+Arm (start) or disarm (stop) a timer.
+.TP
+.BR timer_gettime (2)
+Fetch the time remaining until the next expiration of a timer,
+along with the interval setting of the timer.
+.TP
+.BR timer_getoverrun (2)
+Return the overrun count for the last timer expiration.
+.TP
+.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
+.B CONFIG_POSIX_TIMERS
+option.
+.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
+\&
+.\" SRC BEGIN (timer_create.c)
+.EX
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.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)
+{
+ int or;
+ timer_t *tidp;
+\&
+ 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;
+ sigset_t mask;
+ long long freq_nanosecs;
+ struct sigevent sev;
+ struct sigaction sa;
+ struct itimerspec its;
+\&
+ 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
+.\" SRC END
+.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)