diff options
Diffstat (limited to 'man2/timer_create.2')
-rw-r--r-- | man2/timer_create.2 | 487 |
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) |