Coverage Report

Created: 2026-10-28 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/librabbitmq/librabbitmq/amqp_time.c
Line
Count
Source
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
18.2k
uint64_t amqp_get_monotonic_timestamp(void) {
72
#ifdef __hpux
73
  return (uint64_t)gethrtime();
74
#else
75
18.2k
  struct timespec tp;
76
18.2k
  if (-1 == clock_gettime(CLOCK_MONOTONIC, &tp)) {
77
0
    return 0;
78
0
  }
79
80
18.2k
  return ((uint64_t)tp.tv_sec * AMQP_NS_PER_S + (uint64_t)tp.tv_nsec);
81
18.2k
#endif
82
18.2k
}
83
#endif /* AMQP_POSIX_TIMER_API */
84
85
11.7k
int amqp_time_from_now(amqp_time_t *time, const struct timeval *timeout) {
86
11.7k
  uint64_t now_ns;
87
11.7k
  uint64_t delta_ns;
88
89
11.7k
  assert(NULL != time);
90
91
11.7k
  if (NULL == timeout) {
92
0
    *time = amqp_time_infinite();
93
0
    return AMQP_STATUS_OK;
94
0
  }
95
96
11.7k
  if (timeout->tv_sec < 0 || timeout->tv_usec < 0) {
97
0
    return AMQP_STATUS_INVALID_PARAMETER;
98
0
  }
99
100
11.7k
  delta_ns = (uint64_t)timeout->tv_sec * AMQP_NS_PER_S +
101
11.7k
             (uint64_t)timeout->tv_usec * AMQP_NS_PER_US;
102
103
11.7k
  now_ns = amqp_get_monotonic_timestamp();
104
11.7k
  if (0 == now_ns) {
105
0
    return AMQP_STATUS_TIMER_FAILURE;
106
0
  }
107
108
11.7k
  time->time_point_ns = now_ns + delta_ns;
109
11.7k
  if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
110
0
    return AMQP_STATUS_INVALID_PARAMETER;
111
0
  }
112
113
11.7k
  return AMQP_STATUS_OK;
114
11.7k
}
115
116
21.5k
int amqp_time_s_from_now(amqp_time_t *time, int seconds) {
117
21.5k
  uint64_t now_ns;
118
21.5k
  uint64_t delta_ns;
119
21.5k
  assert(NULL != time);
120
121
21.5k
  if (0 >= seconds) {
122
21.5k
    *time = amqp_time_infinite();
123
21.5k
    return AMQP_STATUS_OK;
124
21.5k
  }
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
22.5k
amqp_time_t amqp_time_infinite(void) {
141
22.5k
  amqp_time_t time;
142
22.5k
  time.time_point_ns = UINT64_MAX;
143
22.5k
  return time;
144
22.5k
}
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
6.45k
                       struct timeval **out) {
175
6.45k
  uint64_t now_ns;
176
6.45k
  uint64_t delta_ns;
177
178
6.45k
  assert(in != NULL);
179
6.45k
  if (UINT64_MAX == time.time_point_ns) {
180
0
    *out = NULL;
181
0
    return AMQP_STATUS_OK;
182
0
  }
183
6.45k
  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
6.45k
  now_ns = amqp_get_monotonic_timestamp();
191
6.45k
  if (0 == now_ns) {
192
0
    return AMQP_STATUS_TIMER_FAILURE;
193
0
  }
194
195
6.45k
  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
6.45k
  delta_ns = time.time_point_ns - now_ns;
203
6.45k
  in->tv_sec = (int)(delta_ns / AMQP_NS_PER_S);
204
6.45k
  in->tv_usec = (int)((delta_ns % AMQP_NS_PER_S) / AMQP_NS_PER_US);
205
6.45k
  *out = in;
206
207
6.45k
  return AMQP_STATUS_OK;
208
6.45k
}
209
210
6.53k
int amqp_time_has_past(amqp_time_t time) {
211
6.53k
  uint64_t now_ns;
212
6.53k
  if (UINT64_MAX == time.time_point_ns) {
213
6.53k
    return AMQP_STATUS_OK;
214
6.53k
  }
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
16.2k
amqp_time_t amqp_time_first(amqp_time_t l, amqp_time_t r) {
228
16.2k
  if (l.time_point_ns < r.time_point_ns) {
229
8.70k
    return l;
230
8.70k
  }
231
7.59k
  return r;
232
16.2k
}
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
}