]>
Commit | Line | Data |
---|---|---|
45b81c9c MK |
1 | .\" Copyright (C) 2008 Michael Kerrisk <mtk.manpages@gmail.com> |
2 | .\" | |
e4a74ca8 | 3 | .\" SPDX-License-Identifier: GPL-2.0-or-later |
45b81c9c | 4 | .\" |
45186a5d | 5 | .TH TIMERFD_CREATE 2 2021-03-22 "Linux man-pages (unreleased)" |
45b81c9c MK |
6 | .SH NAME |
7 | timerfd_create, timerfd_settime, timerfd_gettime \- | |
8 | timers that notify via file descriptors | |
e1984c98 AC |
9 | .SH LIBRARY |
10 | Standard C library | |
8fc3b2cf | 11 | .RI ( libc ", " \-lc ) |
45b81c9c | 12 | .SH SYNOPSIS |
45b81c9c MK |
13 | .nf |
14 | .B #include <sys/timerfd.h> | |
68e4db0a | 15 | .PP |
45b81c9c | 16 | .BI "int timerfd_create(int " clockid ", int " flags ); |
68e4db0a | 17 | .PP |
45b81c9c MK |
18 | .BI "int timerfd_settime(int " fd ", int " flags , |
19 | .BI " const struct itimerspec *" new_value , | |
5c902597 | 20 | .BI " struct itimerspec *" old_value ); |
45b81c9c MK |
21 | .BI "int timerfd_gettime(int " fd ", struct itimerspec *" curr_value ); |
22 | .fi | |
23 | .SH DESCRIPTION | |
24 | These system calls create and operate on a timer | |
25 | that delivers timer expiration notifications via a file descriptor. | |
26 | They provide an alternative to the use of | |
27 | .BR setitimer (2) | |
28 | or | |
804f03e6 | 29 | .BR timer_create (2), |
45b81c9c MK |
30 | with the advantage that the file descriptor may be monitored by |
31 | .BR select (2), | |
32 | .BR poll (2), | |
33 | and | |
34 | .BR epoll (7). | |
efeece04 | 35 | .PP |
45b81c9c | 36 | The use of these three system calls is analogous to the use of |
804f03e6 MK |
37 | .BR timer_create (2), |
38 | .BR timer_settime (2), | |
45b81c9c | 39 | and |
804f03e6 | 40 | .BR timer_gettime (2). |
45b81c9c | 41 | (There is no analog of |
804f03e6 | 42 | .BR timer_getoverrun (2), |
45b81c9c MK |
43 | since that functionality is provided by |
44 | .BR read (2), | |
45 | as described below.) | |
46 | .\" | |
47 | .SS timerfd_create() | |
48 | .BR timerfd_create () | |
49 | creates a new timer object, | |
50 | and returns a file descriptor that refers to that timer. | |
51 | The | |
52 | .I clockid | |
53 | argument specifies the clock that is used to mark the progress | |
205b1bce | 54 | of the timer, and must be one of the following: |
4b76fffb | 55 | .TP |
45b81c9c | 56 | .B CLOCK_REALTIME |
4b76fffb MK |
57 | A settable system-wide real-time clock. |
58 | .TP | |
45b81c9c | 59 | .B CLOCK_MONOTONIC |
4b76fffb MK |
60 | A nonsettable monotonically increasing clock that measures time |
61 | from some unspecified point in the past that does not change | |
62 | after system startup. | |
4c747119 MK |
63 | .TP |
64 | .BR CLOCK_BOOTTIME " (Since Linux 3.15)" | |
65 | .\" commit 4a2378a943f09907fb1ae35c15de917f60289c14 | |
66 | Like | |
67 | .BR CLOCK_MONOTONIC , | |
68 | this is a monotonically increasing clock. | |
69 | However, whereas the | |
1ae6b2c7 | 70 | .B CLOCK_MONOTONIC |
4c747119 | 71 | clock does not measure the time while a system is suspended, the |
1ae6b2c7 | 72 | .B CLOCK_BOOTTIME |
4c747119 MK |
73 | clock does include the time during which the system is suspended. |
74 | This is useful for applications that need to be suspend-aware. | |
1ae6b2c7 | 75 | .B CLOCK_REALTIME |
4c747119 MK |
76 | is not suitable for such applications, since that clock is affected |
77 | by discontinuous changes to the system clock. | |
78 | .TP | |
79 | .BR CLOCK_REALTIME_ALARM " (since Linux 3.11)" | |
80 | .\" commit 11ffa9d6065f344a9bd769a2452f26f2f671e5f8 | |
81 | This clock is like | |
82 | .BR CLOCK_REALTIME , | |
83 | but will wake the system if it is suspended. | |
84 | The caller must have the | |
85 | .B CAP_WAKE_ALARM | |
86 | capability in order to set a timer against this clock. | |
87 | .TP | |
88 | .BR CLOCK_BOOTTIME_ALARM " (since Linux 3.11)" | |
89 | .\" commit 11ffa9d6065f344a9bd769a2452f26f2f671e5f8 | |
90 | This clock is like | |
91 | .BR CLOCK_BOOTTIME , | |
92 | but will wake the system if it is suspended. | |
93 | The caller must have the | |
94 | .B CAP_WAKE_ALARM | |
95 | capability in order to set a timer against this clock. | |
4b76fffb | 96 | .PP |
ff5de6ec MK |
97 | See |
98 | .BR clock_getres (2) | |
99 | for some further details on the above clocks. | |
100 | .PP | |
45b81c9c | 101 | The current value of each of these clocks can be retrieved using |
0eb44391 | 102 | .BR clock_gettime (2). |
efeece04 | 103 | .PP |
3df1b973 | 104 | Starting with Linux 2.6.27, the following values may be bitwise ORed in |
1ae6b2c7 | 105 | .I flags |
3df1b973 MK |
106 | to change the behavior of |
107 | .BR timerfd_create (): | |
108 | .TP 14 | |
109 | .B TFD_NONBLOCK | |
110 | Set the | |
1ae6b2c7 | 111 | .B O_NONBLOCK |
7f11e32c MK |
112 | file status flag on the open file description (see |
113 | .BR open (2)) | |
114 | referred to by the new file descriptor. | |
3df1b973 | 115 | Using this flag saves extra calls to |
ef7db4f5 | 116 | .BR fcntl (2) |
3df1b973 MK |
117 | to achieve the same result. |
118 | .TP | |
119 | .B TFD_CLOEXEC | |
120 | Set the close-on-exec | |
121 | .RB ( FD_CLOEXEC ) | |
122 | flag on the new file descriptor. | |
c5571b61 | 123 | See the description of the |
3df1b973 MK |
124 | .B O_CLOEXEC |
125 | flag in | |
126 | .BR open (2) | |
127 | for reasons why this may be useful. | |
128 | .PP | |
129 | In Linux versions up to and including 2.6.26, | |
45b81c9c | 130 | .I flags |
3df1b973 | 131 | must be specified as zero. |
45b81c9c MK |
132 | .SS timerfd_settime() |
133 | .BR timerfd_settime () | |
134 | arms (starts) or disarms (stops) | |
135 | the timer referred to by the file descriptor | |
136 | .IR fd . | |
efeece04 | 137 | .PP |
45b81c9c MK |
138 | The |
139 | .I new_value | |
140 | argument specifies the initial expiration and interval for the timer. | |
141 | The | |
251ebc1e | 142 | .I itimerspec |
5a04ab88 AC |
143 | structure used for this argument is described in |
144 | .BR itimerspec (3type). | |
45b81c9c MK |
145 | .PP |
146 | .I new_value.it_value | |
147 | specifies the initial expiration of the timer, | |
148 | in seconds and nanoseconds. | |
149 | Setting either field of | |
150 | .I new_value.it_value | |
c7094399 | 151 | to a nonzero value arms the timer. |
45b81c9c MK |
152 | Setting both fields of |
153 | .I new_value.it_value | |
154 | to zero disarms the timer. | |
efeece04 | 155 | .PP |
45b81c9c MK |
156 | Setting one or both fields of |
157 | .I new_value.it_interval | |
c7094399 | 158 | to nonzero values specifies the period, in seconds and nanoseconds, |
45b81c9c MK |
159 | for repeated timer expirations after the initial expiration. |
160 | If both fields of | |
161 | .I new_value.it_interval | |
162 | are zero, the timer expires just once, at the time specified by | |
163 | .IR new_value.it_value . | |
efeece04 | 164 | .PP |
51062576 MK |
165 | By default, |
166 | the initial expiration time specified in | |
167 | .I new_value | |
168 | is interpreted relative to the current time | |
169 | on the timer's clock at the time of the call (i.e., | |
170 | .I new_value.it_value | |
171 | specifies a time relative to the current value of the clock specified by | |
172 | .IR clockid ). | |
173 | An absolute timeout can be selected via the | |
174 | .I flags | |
175 | argument. | |
efeece04 | 176 | .PP |
45b81c9c MK |
177 | The |
178 | .I flags | |
51062576 MK |
179 | argument is a bit mask that can include the following values: |
180 | .TP | |
181 | .B TFD_TIMER_ABSTIME | |
182 | Interpret | |
183 | .I new_value.it_value | |
184 | as an absolute value on the timer's clock. | |
185 | The timer will expire when the value of the timer's | |
45b81c9c | 186 | clock reaches the value specified in |
51062576 | 187 | .IR new_value.it_value . |
e9477548 | 188 | .TP |
1ae6b2c7 | 189 | .B TFD_TIMER_CANCEL_ON_SET |
e9477548 MK |
190 | If this flag is specified along with |
191 | .B TFD_TIMER_ABSTIME | |
192 | and the clock for this timer is | |
1ae6b2c7 | 193 | .B CLOCK_REALTIME |
e9477548 MK |
194 | or |
195 | .BR CLOCK_REALTIME_ALARM , | |
196 | then mark this timer as cancelable if the real-time clock | |
197 | undergoes a discontinuous change | |
198 | .RB ( settimeofday (2), | |
199 | .BR clock_settime (2), | |
200 | or similar). | |
201 | When such changes occur, a current or future | |
202 | .BR read (2) | |
203 | from the file descriptor will fail with the error | |
204 | .BR ECANCELED . | |
51062576 | 205 | .PP |
009cdc22 | 206 | If the |
5c902597 | 207 | .I old_value |
009cdc22 MK |
208 | argument is not NULL, then the |
209 | .I itimerspec | |
210 | structure that it points to is used to return the setting of the timer | |
211 | that was current at the time of the call; | |
212 | see the description of | |
45b81c9c MK |
213 | .BR timerfd_gettime () |
214 | following. | |
215 | .\" | |
216 | .SS timerfd_gettime() | |
217 | .BR timerfd_gettime () | |
218 | returns, in | |
219 | .IR curr_value , | |
220 | an | |
1ae6b2c7 | 221 | .I itimerspec |
dc55661b | 222 | structure that contains the current setting of the timer |
45b81c9c MK |
223 | referred to by the file descriptor |
224 | .IR fd . | |
efeece04 | 225 | .PP |
45b81c9c MK |
226 | The |
227 | .I it_value | |
228 | field returns the amount of time | |
229 | until the timer will next expire. | |
230 | If both fields of this structure are zero, | |
231 | then the timer is currently disarmed. | |
232 | This field always contains a relative value, regardless of whether the | |
1ae6b2c7 | 233 | .B TFD_TIMER_ABSTIME |
45b81c9c | 234 | flag was specified when setting the timer. |
efeece04 | 235 | .PP |
45b81c9c MK |
236 | The |
237 | .I it_interval | |
238 | field returns the interval of the timer. | |
239 | If both fields of this structure are zero, | |
240 | then the timer is set to expire just once, at the time specified by | |
241 | .IR curr_value.it_value . | |
242 | .SS Operating on a timer file descriptor | |
243 | The file descriptor returned by | |
244 | .BR timerfd_create () | |
066dcd09 | 245 | supports the following additional operations: |
45b81c9c MK |
246 | .TP |
247 | .BR read (2) | |
248 | If the timer has already expired one or more times since | |
249 | its settings were last modified using | |
250 | .BR timerfd_settime (), | |
251 | or since the last successful | |
252 | .BR read (2), | |
253 | then the buffer given to | |
254 | .BR read (2) | |
255 | returns an unsigned 8-byte integer | |
256 | .RI ( uint64_t ) | |
257 | containing the number of expirations that have occurred. | |
88879aeb MK |
258 | (The returned value is in host byte order\(emthat is, |
259 | the native byte order for integers on the host machine.) | |
45b81c9c MK |
260 | .IP |
261 | If no timer expirations have occurred at the time of the | |
262 | .BR read (2), | |
263 | then the call either blocks until the next timer expiration, | |
264 | or fails with the error | |
265 | .B EAGAIN | |
ff40dbb3 | 266 | if the file descriptor has been made nonblocking |
45b81c9c MK |
267 | (via the use of the |
268 | .BR fcntl (2) | |
269 | .B F_SETFL | |
270 | operation to set the | |
271 | .B O_NONBLOCK | |
272 | flag). | |
273 | .IP | |
274 | A | |
275 | .BR read (2) | |
26cd31fd | 276 | fails with the error |
45b81c9c MK |
277 | .B EINVAL |
278 | if the size of the supplied buffer is less than 8 bytes. | |
efeece04 | 279 | .IP |
e9477548 | 280 | If the associated clock is either |
1ae6b2c7 | 281 | .B CLOCK_REALTIME |
e9477548 MK |
282 | or |
283 | .BR CLOCK_REALTIME_ALARM , | |
284 | the timer is absolute | |
285 | .RB ( TFD_TIMER_ABSTIME ), | |
286 | and the flag | |
1ae6b2c7 | 287 | .B TFD_TIMER_CANCEL_ON_SET |
e9477548 MK |
288 | was specified when calling |
289 | .BR timerfd_settime (), | |
290 | then | |
291 | .BR read (2) | |
26cd31fd | 292 | fails with the error |
1ae6b2c7 | 293 | .B ECANCELED |
e9477548 MK |
294 | if the real-time clock undergoes a discontinuous change. |
295 | (This allows the reading application to discover | |
296 | such discontinuous changes to the clock.) | |
1ae24555 MK |
297 | .IP |
298 | If the associated clock is either | |
1ae6b2c7 | 299 | .B CLOCK_REALTIME |
1ae24555 MK |
300 | or |
301 | .BR CLOCK_REALTIME_ALARM , | |
302 | the timer is absolute | |
303 | .RB ( TFD_TIMER_ABSTIME ), | |
304 | and the flag | |
1ae6b2c7 | 305 | .B TFD_TIMER_CANCEL_ON_SET |
1ae24555 MK |
306 | was |
307 | .I not | |
308 | specified when calling | |
309 | .BR timerfd_settime (), | |
310 | then a discontinuous negative change to the clock (e.g., | |
311 | .BR clock_settime (2)) | |
312 | may cause | |
313 | .BR read (2) | |
314 | to unblock, but return a value of 0 (i.e., no bytes read), | |
315 | if the clock change occurs after the time expired, | |
316 | but before the | |
317 | .BR read (2) | |
318 | on the file descriptor. | |
45b81c9c MK |
319 | .TP |
320 | .BR poll "(2), " select "(2) (and similar)" | |
321 | The file descriptor is readable | |
322 | (the | |
323 | .BR select (2) | |
324 | .I readfds | |
325 | argument; the | |
326 | .BR poll (2) | |
327 | .B POLLIN | |
328 | flag) | |
329 | if one or more timer expirations have occurred. | |
330 | .IP | |
331 | The file descriptor also supports the other file-descriptor | |
332 | multiplexing APIs: | |
333 | .BR pselect (2), | |
334 | .BR ppoll (2), | |
335 | and | |
336 | .BR epoll (7). | |
337 | .TP | |
6614e292 | 338 | .BR ioctl (2) |
80d27367 MK |
339 | The following timerfd-specific command is supported: |
340 | .RS | |
341 | .TP | |
40f6b649 MK |
342 | .BR TFD_IOC_SET_TICKS " (since Linux 3.17)" |
343 | .\" commit 5442e9fbd7c23172a1c9bc736629cd123a9923f0 | |
80d27367 MK |
344 | Adjust the number of timer expirations that have occurred. |
345 | The argument is a pointer to a nonzero 8-byte integer | |
5a3eb9cd CG |
346 | .RI ( uint64_t *) |
347 | containing the new number of expirations. | |
80d27367 | 348 | Once the number is set, any waiter on the timer is woken up. |
5a3eb9cd | 349 | The only purpose of this command is to restore the expirations |
80d27367 MK |
350 | for the purpose of checkpoint/restore. |
351 | This operation is available only if the kernel was configured with the | |
1ae6b2c7 | 352 | .B CONFIG_CHECKPOINT_RESTORE |
80d27367 MK |
353 | option. |
354 | .RE | |
5a3eb9cd | 355 | .TP |
45b81c9c MK |
356 | .BR close (2) |
357 | When the file descriptor is no longer required it should be closed. | |
358 | When all file descriptors associated with the same timer object | |
359 | have been closed, | |
360 | the timer is disarmed and its resources are freed by the kernel. | |
361 | .\" | |
362 | .SS fork(2) semantics | |
363 | After a | |
364 | .BR fork (2), | |
365 | the child inherits a copy of the file descriptor created by | |
366 | .BR timerfd_create (). | |
367 | The file descriptor refers to the same underlying | |
368 | timer object as the corresponding file descriptor in the parent, | |
369 | and | |
370 | .BR read (2)s | |
371 | in the child will return information about | |
372 | expirations of the timer. | |
373 | .\" | |
374 | .SS execve(2) semantics | |
375 | A file descriptor created by | |
376 | .BR timerfd_create () | |
377 | is preserved across | |
378 | .BR execve (2), | |
379 | and continues to generate timer expirations if the timer was armed. | |
47297adb | 380 | .SH RETURN VALUE |
45b81c9c MK |
381 | On success, |
382 | .BR timerfd_create () | |
383 | returns a new file descriptor. | |
384 | On error, \-1 is returned and | |
385 | .I errno | |
386 | is set to indicate the error. | |
efeece04 | 387 | .PP |
45b81c9c MK |
388 | .BR timerfd_settime () |
389 | and | |
390 | .BR timerfd_gettime () | |
391 | return 0 on success; | |
392 | on error they return \-1, and set | |
393 | .I errno | |
394 | to indicate the error. | |
395 | .SH ERRORS | |
396 | .BR timerfd_create () | |
397 | can fail with the following errors: | |
398 | .TP | |
399 | .B EINVAL | |
400 | The | |
401 | .I clockid | |
04e2e313 | 402 | is not valid. |
3df1b973 MK |
403 | .TP |
404 | .B EINVAL | |
405 | .I flags | |
406 | is invalid; | |
407 | or, in Linux 2.6.26 or earlier, | |
45b81c9c | 408 | .I flags |
c7094399 | 409 | is nonzero. |
45b81c9c MK |
410 | .TP |
411 | .B EMFILE | |
26c32fab | 412 | The per-process limit on the number of open file descriptors has been reached. |
45b81c9c MK |
413 | .TP |
414 | .B ENFILE | |
415 | The system-wide limit on the total number of open files has been | |
416 | reached. | |
417 | .TP | |
418 | .B ENODEV | |
419 | Could not mount (internal) anonymous inode device. | |
420 | .TP | |
421 | .B ENOMEM | |
422 | There was insufficient kernel memory to create the timer. | |
96d951a4 MK |
423 | .TP |
424 | .B EPERM | |
425 | .I clockid | |
426 | was | |
1ae6b2c7 | 427 | .B CLOCK_REALTIME_ALARM |
96d951a4 | 428 | or |
1ae6b2c7 | 429 | .B CLOCK_BOOTTIME_ALARM |
96d951a4 | 430 | but the caller did not have the |
1ae6b2c7 | 431 | .B CAP_WAKE_ALARM |
96d951a4 | 432 | capability. |
45b81c9c MK |
433 | .PP |
434 | .BR timerfd_settime () | |
435 | and | |
436 | .BR timerfd_gettime () | |
437 | can fail with the following errors: | |
438 | .TP | |
439 | .B EBADF | |
440 | .I fd | |
441 | is not a valid file descriptor. | |
442 | .TP | |
2bbb3907 MK |
443 | .B EFAULT |
444 | .IR new_value , | |
445 | .IR old_value , | |
446 | or | |
447 | .I curr_value | |
5c405d85 | 448 | is not a valid pointer. |
2bbb3907 | 449 | .TP |
45b81c9c MK |
450 | .B EINVAL |
451 | .I fd | |
452 | is not a valid timerfd file descriptor. | |
c71b054d MK |
453 | .PP |
454 | .BR timerfd_settime () | |
455 | can also fail with the following errors: | |
456 | .TP | |
0f1553b5 MK |
457 | .B ECANCELED |
458 | See NOTES. | |
459 | .TP | |
c71b054d | 460 | .B EINVAL |
45b81c9c MK |
461 | .I new_value |
462 | is not properly initialized (one of the | |
463 | .I tv_nsec | |
464 | falls outside the range zero to 999,999,999). | |
86d95cf2 MK |
465 | .TP |
466 | .B EINVAL | |
467 | .\" This case only checked since 2.6.29, and 2.2.2[78].some-stable-version. | |
468 | .\" In older kernel versions, no check was made for invalid flags. | |
469 | .I flags | |
470 | is invalid. | |
45b81c9c MK |
471 | .SH VERSIONS |
472 | These system calls are available on Linux since kernel 2.6.25. | |
d6a54d42 | 473 | Library support is provided by glibc since version 2.8. |
3113c7f3 | 474 | .SH STANDARDS |
45b81c9c | 475 | These system calls are Linux-specific. |
0f1553b5 MK |
476 | .SH NOTES |
477 | Suppose the following scenario for | |
1ae6b2c7 | 478 | .B CLOCK_REALTIME |
0f1553b5 | 479 | or |
1ae6b2c7 | 480 | .B CLOCK_REALTIME_ALARM |
0f1553b5 MK |
481 | timer that was created with |
482 | .BR timerfd_create (): | |
483 | .IP (a) 4 | |
484 | The timer has been started | |
485 | .RB ( timerfd_settime ()) | |
486 | with the | |
1ae6b2c7 | 487 | .B TFD_TIMER_ABSTIME |
0f1553b5 | 488 | and |
1ae6b2c7 | 489 | .B TFD_TIMER_CANCEL_ON_SET |
0f1553b5 MK |
490 | flags; |
491 | .IP (b) | |
ac6dcc48 | 492 | A discontinuous change (e.g., |
0f1553b5 MK |
493 | .BR settimeofday (2)) |
494 | is subsequently made to the | |
1ae6b2c7 | 495 | .B CLOCK_REALTIME |
0f1553b5 MK |
496 | clock; and |
497 | .IP (c) | |
498 | the caller once more calls | |
499 | .BR timerfd_settime () | |
500 | to rearm the timer (without first doing a | |
501 | .BR read (2) | |
502 | on the file descriptor). | |
503 | .PP | |
504 | In this case the following occurs: | |
505 | .IP \(bu 2 | |
506 | The | |
507 | .BR timerfd_settime () | |
508 | returns \-1 with | |
509 | .I errno | |
510 | set to | |
511 | .BR ECANCELED . | |
512 | (This enables the caller to know that the previous timer was affected | |
513 | by a discontinuous change to the clock.) | |
514 | .IP \(bu | |
515 | The timer | |
516 | .I "is successfully rearmed" | |
517 | with the settings provided in the second | |
518 | .BR timerfd_settime () | |
519 | call. | |
520 | (This was probably an implementation accident, but won't be fixed now, | |
521 | in case there are applications that depend on this behaviour.) | |
7484d5a7 MK |
522 | .SH BUGS |
523 | Currently, | |
524 | .\" 2.6.29 | |
525 | .BR timerfd_create () | |
526 | supports fewer types of clock IDs than | |
527 | .BR timer_create (2). | |
a14af333 | 528 | .SH EXAMPLES |
45b81c9c MK |
529 | The following program creates a timer and then monitors its progress. |
530 | The program accepts up to three command-line arguments. | |
531 | The first argument specifies the number of seconds for | |
532 | the initial expiration of the timer. | |
533 | The second argument specifies the interval for the timer, in seconds. | |
534 | The third argument specifies the number of times the program should | |
535 | allow the timer to expire before terminating. | |
536 | The second and third command-line arguments are optional. | |
efeece04 | 537 | .PP |
45b81c9c | 538 | The following shell session demonstrates the use of the program: |
e646a1ba | 539 | .PP |
45b81c9c | 540 | .in +4n |
e646a1ba | 541 | .EX |
b43a3b30 | 542 | .RB "$" " a.out 3 1 100" |
45b81c9c MK |
543 | 0.000: timer started |
544 | 3.000: read: 1; total=1 | |
545 | 4.000: read: 1; total=2 | |
d064d41a | 546 | .BR "\(haZ " " # type control\-Z to suspend the program" |
45b81c9c | 547 | [1]+ Stopped ./timerfd3_demo 3 1 100 |
b43a3b30 | 548 | .RB "$ " "fg" " # Resume execution after a few seconds" |
45b81c9c MK |
549 | a.out 3 1 100 |
550 | 9.660: read: 5; total=7 | |
551 | 10.000: read: 1; total=8 | |
552 | 11.000: read: 1; total=9 | |
d064d41a | 553 | .BR "\(haC " " # type control\-C to suspend the program" |
b8302363 | 554 | .EE |
45b81c9c | 555 | .in |
9c330504 | 556 | .SS Program source |
d84d0300 | 557 | \& |
33857069 | 558 | .\" SRC BEGIN (timerfd_create.c) |
e7d0bb47 | 559 | .EX |
45b81c9c MK |
560 | .\" The commented out code here is what we currently need until |
561 | .\" the required stuff is in glibc | |
562 | .\" | |
563 | .\" | |
d064d41a | 564 | .\"/* Link with \-lrt */ |
45b81c9c MK |
565 | .\"#define _GNU_SOURCE |
566 | .\"#include <sys/syscall.h> | |
567 | .\"#include <unistd.h> | |
568 | .\"#include <time.h> | |
569 | .\"#if defined(__i386__) | |
570 | .\"#define __NR_timerfd_create 322 | |
571 | .\"#define __NR_timerfd_settime 325 | |
572 | .\"#define __NR_timerfd_gettime 326 | |
573 | .\"#endif | |
574 | .\" | |
575 | .\"static int | |
576 | .\"timerfd_create(int clockid, int flags) | |
577 | .\"{ | |
578 | .\" return syscall(__NR_timerfd_create, clockid, flags); | |
579 | .\"} | |
580 | .\" | |
581 | .\"static int | |
582 | .\"timerfd_settime(int fd, int flags, struct itimerspec *new_value, | |
583 | .\" struct itimerspec *curr_value) | |
584 | .\"{ | |
585 | .\" return syscall(__NR_timerfd_settime, fd, flags, new_value, | |
586 | .\" curr_value); | |
587 | .\"} | |
588 | .\" | |
589 | .\"static int | |
590 | .\"timerfd_gettime(int fd, struct itimerspec *curr_value) | |
591 | .\"{ | |
592 | .\" return syscall(__NR_timerfd_gettime, fd, curr_value); | |
593 | .\"} | |
594 | .\" | |
595 | .\"#define TFD_TIMER_ABSTIME (1 << 0) | |
596 | .\" | |
597 | .\"//////////////////////////////////////////////////////////// | |
47b94bbd AC |
598 | #include <inttypes.h> |
599 | #include <stdio.h> | |
600 | #include <stdlib.h> | |
45b81c9c MK |
601 | #include <sys/timerfd.h> |
602 | #include <time.h> | |
603 | #include <unistd.h> | |
45b81c9c | 604 | |
d1a71985 | 605 | #define handle_error(msg) \e |
45b81c9c MK |
606 | do { perror(msg); exit(EXIT_FAILURE); } while (0) |
607 | ||
608 | static void | |
609 | print_elapsed_time(void) | |
610 | { | |
611 | static struct timespec start; | |
612 | struct timespec curr; | |
613 | static int first_call = 1; | |
614 | int secs, nsecs; | |
615 | ||
616 | if (first_call) { | |
617 | first_call = 0; | |
618 | if (clock_gettime(CLOCK_MONOTONIC, &start) == \-1) | |
619 | handle_error("clock_gettime"); | |
620 | } | |
621 | ||
622 | if (clock_gettime(CLOCK_MONOTONIC, &curr) == \-1) | |
623 | handle_error("clock_gettime"); | |
624 | ||
625 | secs = curr.tv_sec \- start.tv_sec; | |
626 | nsecs = curr.tv_nsec \- start.tv_nsec; | |
627 | if (nsecs < 0) { | |
628 | secs\-\-; | |
629 | nsecs += 1000000000; | |
630 | } | |
631 | printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000); | |
632 | } | |
633 | ||
634 | int | |
635 | main(int argc, char *argv[]) | |
636 | { | |
637 | struct itimerspec new_value; | |
638 | int max_exp, fd; | |
639 | struct timespec now; | |
640 | uint64_t exp, tot_exp; | |
641 | ssize_t s; | |
642 | ||
55f2fc29 | 643 | if (argc != 2 && argc != 4) { |
d1a71985 | 644 | fprintf(stderr, "%s init\-secs [interval\-secs max\-exp]\en", |
45b81c9c MK |
645 | argv[0]); |
646 | exit(EXIT_FAILURE); | |
647 | } | |
648 | ||
649 | if (clock_gettime(CLOCK_REALTIME, &now) == \-1) | |
650 | handle_error("clock_gettime"); | |
651 | ||
652 | /* Create a CLOCK_REALTIME absolute timer with initial | |
46b20ca1 | 653 | expiration and interval as specified in command line. */ |
45b81c9c MK |
654 | |
655 | new_value.it_value.tv_sec = now.tv_sec + atoi(argv[1]); | |
656 | new_value.it_value.tv_nsec = now.tv_nsec; | |
657 | if (argc == 2) { | |
658 | new_value.it_interval.tv_sec = 0; | |
659 | max_exp = 1; | |
660 | } else { | |
661 | new_value.it_interval.tv_sec = atoi(argv[2]); | |
662 | max_exp = atoi(argv[3]); | |
663 | } | |
664 | new_value.it_interval.tv_nsec = 0; | |
665 | ||
666 | fd = timerfd_create(CLOCK_REALTIME, 0); | |
667 | if (fd == \-1) | |
668 | handle_error("timerfd_create"); | |
669 | ||
a279595b | 670 | if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == \-1) |
45b81c9c MK |
671 | handle_error("timerfd_settime"); |
672 | ||
673 | print_elapsed_time(); | |
d1a71985 | 674 | printf("timer started\en"); |
45b81c9c MK |
675 | |
676 | for (tot_exp = 0; tot_exp < max_exp;) { | |
677 | s = read(fd, &exp, sizeof(uint64_t)); | |
678 | if (s != sizeof(uint64_t)) | |
679 | handle_error("read"); | |
680 | ||
681 | tot_exp += exp; | |
682 | print_elapsed_time(); | |
fbd150d9 | 683 | printf("read: %" PRIu64 "; total=%" PRIu64 "\en", exp, tot_exp); |
45b81c9c MK |
684 | } |
685 | ||
686 | exit(EXIT_SUCCESS); | |
687 | } | |
e7d0bb47 | 688 | .EE |
33857069 | 689 | .\" SRC END |
47297adb | 690 | .SH SEE ALSO |
45b81c9c MK |
691 | .BR eventfd (2), |
692 | .BR poll (2), | |
693 | .BR read (2), | |
694 | .BR select (2), | |
695 | .BR setitimer (2), | |
696 | .BR signalfd (2), | |
804f03e6 MK |
697 | .BR timer_create (2), |
698 | .BR timer_gettime (2), | |
699 | .BR timer_settime (2), | |
e97e048a | 700 | .BR timespec (3), |
45b81c9c MK |
701 | .BR epoll (7), |
702 | .BR time (7) |