/src/lvm2/libdm/libdm-timestamp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2006 Rackable Systems All rights reserved. |
3 | | * Copyright (C) 2015 Red Hat, Inc. All rights reserved. |
4 | | * |
5 | | * This file is part of the device-mapper userspace tools. |
6 | | * |
7 | | * This copyrighted material is made available to anyone wishing to use, |
8 | | * modify, copy, or redistribute it subject to the terms and conditions |
9 | | * of the GNU Lesser General Public License v.2.1. |
10 | | * |
11 | | * You should have received a copy of the GNU Lesser General Public License |
12 | | * along with this program; if not, write to the Free Software Foundation, |
13 | | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
14 | | */ |
15 | | |
16 | | /* |
17 | | * Abstract out the time methods used so they can be adjusted later - |
18 | | * the results of these routines should stay in-core. |
19 | | */ |
20 | | |
21 | | #include "libdm/misc/dmlib.h" |
22 | | |
23 | | #include <stdlib.h> |
24 | | |
25 | | #define NSEC_PER_USEC UINT64_C(1000) |
26 | | #define NSEC_PER_MSEC UINT64_C(1000000) |
27 | 0 | #define NSEC_PER_SEC UINT64_C(1000000000) |
28 | | |
29 | | /* |
30 | | * The realtime section uses clock_gettime with the CLOCK_MONOTONIC |
31 | | * parameter to prevent issues with time warps |
32 | | * This implementation requires librt. |
33 | | */ |
34 | | #ifdef HAVE_REALTIME |
35 | | |
36 | | #include <time.h> |
37 | | |
38 | | struct dm_timestamp { |
39 | | struct timespec t; |
40 | | }; |
41 | | |
42 | | static uint64_t _timestamp_to_uint64(struct dm_timestamp *ts) |
43 | 0 | { |
44 | 0 | uint64_t stamp = 0; |
45 | |
|
46 | 0 | stamp += (uint64_t) ts->t.tv_sec * NSEC_PER_SEC; |
47 | 0 | stamp += (uint64_t) ts->t.tv_nsec; |
48 | |
|
49 | 0 | return stamp; |
50 | 0 | } |
51 | | |
52 | | struct dm_timestamp *dm_timestamp_alloc(void) |
53 | 0 | { |
54 | 0 | struct dm_timestamp *ts = NULL; |
55 | |
|
56 | 0 | if (!(ts = dm_zalloc(sizeof(*ts)))) |
57 | 0 | stack; |
58 | |
|
59 | 0 | return ts; |
60 | 0 | } |
61 | | |
62 | | int dm_timestamp_get(struct dm_timestamp *ts) |
63 | 0 | { |
64 | 0 | if (!ts) |
65 | 0 | return 0; |
66 | | |
67 | 0 | if (clock_gettime(CLOCK_MONOTONIC, &ts->t)) { |
68 | 0 | log_sys_error("clock_gettime", "get_timestamp"); |
69 | 0 | ts->t.tv_sec = 0; |
70 | 0 | ts->t.tv_nsec = 0; |
71 | 0 | return 0; |
72 | 0 | } |
73 | | |
74 | 0 | return 1; |
75 | 0 | } |
76 | | |
77 | | #else /* ! HAVE_REALTIME */ |
78 | | |
79 | | /* |
80 | | * The !realtime section just uses gettimeofday and is therefore subject |
81 | | * to ntp-type time warps - not sure if should allow that. |
82 | | */ |
83 | | |
84 | | #include <sys/time.h> |
85 | | |
86 | | struct dm_timestamp { |
87 | | struct timeval t; |
88 | | }; |
89 | | |
90 | | static uint64_t _timestamp_to_uint64(struct dm_timestamp *ts) |
91 | | { |
92 | | uint64_t stamp = 0; |
93 | | |
94 | | stamp += ts->t.tv_sec * NSEC_PER_SEC; |
95 | | stamp += ts->t.tv_usec * NSEC_PER_USEC; |
96 | | |
97 | | return stamp; |
98 | | } |
99 | | |
100 | | struct dm_timestamp *dm_timestamp_alloc(void) |
101 | | { |
102 | | struct dm_timestamp *ts; |
103 | | |
104 | | if (!(ts = dm_malloc(sizeof(*ts)))) |
105 | | stack; |
106 | | |
107 | | return ts; |
108 | | } |
109 | | |
110 | | int dm_timestamp_get(struct dm_timestamp *ts) |
111 | | { |
112 | | if (!ts) |
113 | | return 0; |
114 | | |
115 | | if (gettimeofday(&ts->t, NULL)) { |
116 | | log_sys_error("gettimeofday", "get_timestamp"); |
117 | | ts->t.tv_sec = 0; |
118 | | ts->t.tv_usec = 0; |
119 | | return 0; |
120 | | } |
121 | | |
122 | | return 1; |
123 | | } |
124 | | |
125 | | #endif /* HAVE_REALTIME */ |
126 | | |
127 | | /* |
128 | | * Compare two timestamps. |
129 | | * |
130 | | * Return: -1 if ts1 is less than ts2 |
131 | | * 0 if ts1 is equal to ts2 |
132 | | * 1 if ts1 is greater than ts2 |
133 | | */ |
134 | | int dm_timestamp_compare(struct dm_timestamp *ts1, struct dm_timestamp *ts2) |
135 | 0 | { |
136 | 0 | uint64_t t1, t2; |
137 | |
|
138 | 0 | t1 = _timestamp_to_uint64(ts1); |
139 | 0 | t2 = _timestamp_to_uint64(ts2); |
140 | |
|
141 | 0 | if (t2 < t1) |
142 | 0 | return 1; |
143 | | |
144 | 0 | if (t1 < t2) |
145 | 0 | return -1; |
146 | | |
147 | 0 | return 0; |
148 | 0 | } |
149 | | |
150 | | /* |
151 | | * Return the absolute difference in nanoseconds between |
152 | | * the dm_timestamp objects ts1 and ts2. |
153 | | * |
154 | | * Callers that need to know whether ts1 is before, equal to, or after ts2 |
155 | | * in addition to the magnitude should use dm_timestamp_compare. |
156 | | */ |
157 | | uint64_t dm_timestamp_delta(struct dm_timestamp *ts1, struct dm_timestamp *ts2) |
158 | 0 | { |
159 | 0 | uint64_t t1, t2; |
160 | |
|
161 | 0 | t1 = _timestamp_to_uint64(ts1); |
162 | 0 | t2 = _timestamp_to_uint64(ts2); |
163 | |
|
164 | 0 | if (t1 > t2) |
165 | 0 | return t1 - t2; |
166 | | |
167 | 0 | return t2 - t1; |
168 | 0 | } |
169 | | |
170 | | void dm_timestamp_copy(struct dm_timestamp *ts_new, struct dm_timestamp *ts_old) |
171 | 0 | { |
172 | 0 | *ts_new = *ts_old; |
173 | 0 | } |
174 | | |
175 | | void dm_timestamp_destroy(struct dm_timestamp *ts) |
176 | 10.9k | { |
177 | 10.9k | dm_free(ts); |
178 | 10.9k | } |