]>
Commit | Line | Data |
---|---|---|
cd2876d2 KZ |
1 | /* |
2 | * Please, don't add this file to libcommon because clock_gettime() requires | |
3 | * -lrt on systems with old libc. | |
4 | */ | |
2c5484f7 | 5 | #include <time.h> |
378543e1 | 6 | #include <signal.h> |
2c5484f7 KZ |
7 | #include <sys/sysinfo.h> |
8 | #include <sys/time.h> | |
9 | ||
10 | #include "c.h" | |
11 | #include "nls.h" | |
cd2876d2 | 12 | #include "monotonic.h" |
2c5484f7 KZ |
13 | |
14 | int get_boot_time(struct timeval *boot_time) | |
15 | { | |
60cb2c37 | 16 | #ifdef CLOCK_BOOTTIME |
2c5484f7 | 17 | struct timespec hires_uptime; |
60cb2c37 RM |
18 | struct timeval lores_uptime; |
19 | #endif | |
20 | struct timeval now; | |
88e0f3df | 21 | #ifdef HAVE_SYSINFO |
2c5484f7 | 22 | struct sysinfo info; |
88e0f3df | 23 | #endif |
2c5484f7 KZ |
24 | |
25 | if (gettimeofday(&now, NULL) != 0) { | |
26 | warn(_("gettimeofday failed")); | |
27 | return -errno; | |
28 | } | |
29 | #ifdef CLOCK_BOOTTIME | |
30 | if (clock_gettime(CLOCK_BOOTTIME, &hires_uptime) == 0) { | |
31 | TIMESPEC_TO_TIMEVAL(&lores_uptime, &hires_uptime); | |
32 | timersub(&now, &lores_uptime, boot_time); | |
33 | return 0; | |
34 | } | |
35 | #endif | |
88e0f3df | 36 | #ifdef HAVE_SYSINFO |
2c5484f7 KZ |
37 | /* fallback */ |
38 | if (sysinfo(&info) != 0) | |
39 | warn(_("sysinfo failed")); | |
40 | ||
41 | boot_time->tv_sec = now.tv_sec - info.uptime; | |
42 | boot_time->tv_usec = 0; | |
43 | return 0; | |
88e0f3df ST |
44 | #else |
45 | return -ENOSYS; | |
46 | #endif | |
2c5484f7 | 47 | } |
cd2876d2 KZ |
48 | |
49 | int gettime_monotonic(struct timeval *tv) | |
50 | { | |
51 | #ifdef CLOCK_MONOTONIC | |
52 | /* Can slew only by ntp and adjtime */ | |
53 | int ret; | |
54 | struct timespec ts; | |
55 | ||
56 | # ifdef CLOCK_MONOTONIC_RAW | |
57 | /* Linux specific, cant slew */ | |
58 | if (!(ret = clock_gettime(CLOCK_MONOTONIC_RAW, &ts))) { | |
59 | # else | |
60 | if (!(ret = clock_gettime(CLOCK_MONOTONIC, &ts))) { | |
61 | # endif | |
62 | tv->tv_sec = ts.tv_sec; | |
63 | tv->tv_usec = ts.tv_nsec / 1000; | |
64 | } | |
65 | return ret; | |
66 | #else | |
67 | return gettimeofday(tv, NULL); | |
68 | #endif | |
69 | } | |
378543e1 SK |
70 | |
71 | int setup_timer(timer_t * t_id, struct itimerval *timeout, | |
72 | void (*timeout_handler)(void)) | |
73 | { | |
74 | struct sigaction sig_a; | |
75 | static struct sigevent sig_e = { | |
76 | .sigev_notify = SIGEV_SIGNAL, | |
77 | .sigev_signo = SIGALRM | |
78 | }; | |
79 | struct itimerspec val = { | |
80 | .it_value.tv_sec = timeout->it_value.tv_sec, | |
81 | .it_value.tv_nsec = timeout->it_value.tv_usec * 1000, | |
82 | .it_interval.tv_sec = 0, | |
83 | .it_interval.tv_nsec = 0 | |
84 | }; | |
85 | ||
86 | if (sigemptyset(&sig_a.sa_mask)) | |
87 | return 1; | |
88 | sig_a.sa_flags = SA_SIGINFO; | |
89 | sig_a.sa_handler = timeout_handler; | |
90 | if (sigaction(SIGALRM, &sig_a, 0)) | |
91 | return 1; | |
92 | if (timer_create(CLOCK_MONOTONIC, &sig_e, t_id)) | |
93 | return 1; | |
94 | if (timer_settime(*t_id, SA_SIGINFO, &val, NULL)) | |
95 | return 1; | |
96 | return 0; | |
97 | } | |
98 | ||
99 | void cancel_timer(timer_t *t_id) | |
100 | { | |
101 | timer_delete(*t_id); | |
102 | } |