Coverage Report

Created: 2023-03-26 06:02

/src/librabbitmq/librabbitmq/amqp_time.c
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
2
// SPDX-License-Identifier: mit
3
4
#include "amqp_time.h"
5
#include "rabbitmq-c/amqp.h"
6
#include <assert.h>
7
#include <limits.h>
8
#include <string.h>
9
10
#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || \
11
     defined(__MINGW32__) || defined(__MINGW64__))
12
#define AMQP_WIN_TIMER_API
13
#elif (defined(machintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
14
#define AMQP_MAC_TIMER_API
15
#else
16
#define AMQP_POSIX_TIMER_API
17
#endif
18
19
#ifdef AMQP_WIN_TIMER_API
20
#ifndef WIN32_LEAN_AND_MEAN
21
#define WIN32_LEAN_AND_MEAN
22
#endif
23
#include <windows.h>
24
25
uint64_t amqp_get_monotonic_timestamp(void) {
26
  static double NS_PER_COUNT = 0;
27
  LARGE_INTEGER perf_count;
28
29
  if (0 == NS_PER_COUNT) {
30
    LARGE_INTEGER perf_frequency;
31
    if (!QueryPerformanceFrequency(&perf_frequency)) {
32
      return 0;
33
    }
34
    NS_PER_COUNT = (double)AMQP_NS_PER_S / perf_frequency.QuadPart;
35
  }
36
37
  if (!QueryPerformanceCounter(&perf_count)) {
38
    return 0;
39
  }
40
41
  return (uint64_t)(perf_count.QuadPart * NS_PER_COUNT);
42
}
43
#endif /* AMQP_WIN_TIMER_API */
44
45
#ifdef AMQP_MAC_TIMER_API
46
#include <mach/mach_time.h>
47
48
uint64_t amqp_get_monotonic_timestamp(void) {
49
  static mach_timebase_info_data_t s_timebase = {0, 0};
50
  uint64_t timestamp;
51
52
  timestamp = mach_absolute_time();
53
54
  if (s_timebase.denom == 0) {
55
    mach_timebase_info(&s_timebase);
56
    if (0 == s_timebase.denom) {
57
      return 0;
58
    }
59
  }
60
61
  timestamp *= (uint64_t)s_timebase.numer;
62
  timestamp /= (uint64_t)s_timebase.denom;
63
64
  return timestamp;
65
}
66
#endif /* AMQP_MAC_TIMER_API */
67
68
#ifdef AMQP_POSIX_TIMER_API
69
#include <time.h>
70
71
0
uint64_t amqp_get_monotonic_timestamp(void) {
72
#ifdef __hpux
73
  return (uint64_t)gethrtime();
74
#else
75
0
  struct timespec tp;
76
0
  if (-1 == clock_gettime(CLOCK_MONOTONIC, &tp)) {
77
0
    return 0;
78
0
  }
79
80
0
  return ((uint64_t)tp.tv_sec * AMQP_NS_PER_S + (uint64_t)tp.tv_nsec);
81
0
#endif
82
0
}
83
#endif /* AMQP_POSIX_TIMER_API */
84
85
0
int amqp_time_from_now(amqp_time_t *time, const struct timeval *timeout) {
86
0
  uint64_t now_ns;
87
0
  uint64_t delta_ns;
88
89
0
  assert(NULL != time);
90
91
0
  if (NULL == timeout) {
92
0
    *time = amqp_time_infinite();
93
0
    return AMQP_STATUS_OK;
94
0
  }
95
96
0
  if (timeout->tv_sec < 0 || timeout->tv_usec < 0) {
97
0
    return AMQP_STATUS_INVALID_PARAMETER;
98
0
  }
99
100
0
  delta_ns = (uint64_t)timeout->tv_sec * AMQP_NS_PER_S +
101
0
             (uint64_t)timeout->tv_usec * AMQP_NS_PER_US;
102
103
0
  now_ns = amqp_get_monotonic_timestamp();
104
0
  if (0 == now_ns) {
105
0
    return AMQP_STATUS_TIMER_FAILURE;
106
0
  }
107
108
0
  time->time_point_ns = now_ns + delta_ns;
109
0
  if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
110
0
    return AMQP_STATUS_INVALID_PARAMETER;
111
0
  }
112
113
0
  return AMQP_STATUS_OK;
114
0
}
115
116
0
int amqp_time_s_from_now(amqp_time_t *time, int seconds) {
117
0
  uint64_t now_ns;
118
0
  uint64_t delta_ns;
119
0
  assert(NULL != time);
120
121
0
  if (0 >= seconds) {
122
0
    *time = amqp_time_infinite();
123
0
    return AMQP_STATUS_OK;
124
0
  }
125
126
0
  now_ns = amqp_get_monotonic_timestamp();
127
0
  if (0 == now_ns) {
128
0
    return AMQP_STATUS_TIMER_FAILURE;
129
0
  }
130
131
0
  delta_ns = (uint64_t)seconds * AMQP_NS_PER_S;
132
0
  time->time_point_ns = now_ns + delta_ns;
133
0
  if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
134
0
    return AMQP_STATUS_INVALID_PARAMETER;
135
0
  }
136
137
0
  return AMQP_STATUS_OK;
138
0
}
139
140
0
amqp_time_t amqp_time_infinite(void) {
141
0
  amqp_time_t time;
142
0
  time.time_point_ns = UINT64_MAX;
143
0
  return time;
144
0
}
145
146
0
int amqp_time_ms_until(amqp_time_t time) {
147
0
  uint64_t now_ns;
148
0
  uint64_t delta_ns;
149
0
  int left_ms;
150
151
0
  if (UINT64_MAX == time.time_point_ns) {
152
0
    return -1;
153
0
  }
154
0
  if (0 == time.time_point_ns) {
155
0
    return 0;
156
0
  }
157
158
0
  now_ns = amqp_get_monotonic_timestamp();
159
0
  if (0 == now_ns) {
160
0
    return AMQP_STATUS_TIMER_FAILURE;
161
0
  }
162
163
0
  if (now_ns >= time.time_point_ns) {
164
0
    return 0;
165
0
  }
166
167
0
  delta_ns = time.time_point_ns - now_ns;
168
0
  left_ms = (int)(delta_ns / AMQP_NS_PER_MS);
169
170
0
  return left_ms;
171
0
}
172
173
int amqp_time_tv_until(amqp_time_t time, struct timeval *in,
174
0
                       struct timeval **out) {
175
0
  uint64_t now_ns;
176
0
  uint64_t delta_ns;
177
178
0
  assert(in != NULL);
179
0
  if (UINT64_MAX == time.time_point_ns) {
180
0
    *out = NULL;
181
0
    return AMQP_STATUS_OK;
182
0
  }
183
0
  if (0 == time.time_point_ns) {
184
0
    in->tv_sec = 0;
185
0
    in->tv_usec = 0;
186
0
    *out = in;
187
0
    return AMQP_STATUS_OK;
188
0
  }
189
190
0
  now_ns = amqp_get_monotonic_timestamp();
191
0
  if (0 == now_ns) {
192
0
    return AMQP_STATUS_TIMER_FAILURE;
193
0
  }
194
195
0
  if (now_ns >= time.time_point_ns) {
196
0
    in->tv_sec = 0;
197
0
    in->tv_usec = 0;
198
0
    *out = in;
199
0
    return AMQP_STATUS_OK;
200
0
  }
201
202
0
  delta_ns = time.time_point_ns - now_ns;
203
0
  in->tv_sec = (int)(delta_ns / AMQP_NS_PER_S);
204
0
  in->tv_usec = (int)((delta_ns % AMQP_NS_PER_S) / AMQP_NS_PER_US);
205
0
  *out = in;
206
207
0
  return AMQP_STATUS_OK;
208
0
}
209
210
0
int amqp_time_has_past(amqp_time_t time) {
211
0
  uint64_t now_ns;
212
0
  if (UINT64_MAX == time.time_point_ns) {
213
0
    return AMQP_STATUS_OK;
214
0
  }
215
216
0
  now_ns = amqp_get_monotonic_timestamp();
217
0
  if (0 == now_ns) {
218
0
    return AMQP_STATUS_TIMER_FAILURE;
219
0
  }
220
221
0
  if (now_ns > time.time_point_ns) {
222
0
    return AMQP_STATUS_TIMEOUT;
223
0
  }
224
0
  return AMQP_STATUS_OK;
225
0
}
226
227
0
amqp_time_t amqp_time_first(amqp_time_t l, amqp_time_t r) {
228
0
  if (l.time_point_ns < r.time_point_ns) {
229
0
    return l;
230
0
  }
231
0
  return r;
232
0
}
233
234
0
int amqp_time_equal(amqp_time_t l, amqp_time_t r) {
235
0
  return l.time_point_ns == r.time_point_ns;
236
0
}