33 #include <utils_timeout.h> 37 #define TIMEOUT_BITS 28 39 #define TIMEOUT_MASK ((1 << TIMEOUT_BITS) - 1) 42 #define MAX_TIMEOUTS 64 45 static uint64_t tsc_per_us = 0;
51 static inline int timeout_due(
struct timeout *to, uint32_t ts);
54 static inline uint32_t timestamp_us_long(
void);
56 static inline uint32_t timestamp_us(
void);
58 static inline int32_t rel_time(uint32_t cur,
struct timeout *to);
60 static inline void calibrate_tsc(
void);
63 void (*handler)(
struct timeout *, uint8_t,
void *),
void *handler_opaque)
66 memset(mgr, 0,
sizeof(*mgr));
76 return timestamp_us_long();
89 cur_ts &= TIMEOUT_MASK;
92 move_due_timeouts(mgr, cur_ts);
95 while ((to = mgr->
due_first) != NULL && num < MAX_TIMEOUTS) {
111 uint32_t us, uint8_t type)
117 uint32_t us, uint8_t type, uint32_t cur_ts)
121 cur_ts &= TIMEOUT_MASK;
124 if (us >= (1 << (TIMEOUT_BITS - 1))) {
125 fprintf(stderr,
"timeout_arm: specified timeout is out of range (needs to " 126 "be < %u, but got %u)\n", (1 << (TIMEOUT_BITS - 1)), us);
131 move_due_timeouts(mgr, cur_ts);
134 for (tp = mgr->
timeouts_last; tp != NULL && rel_time(cur_ts, tp) > us;
167 fprintf(stderr,
"timeout_disarm: timeout neither in timeouts_first nor " 181 fprintf(stderr,
"timeout_disarm: timeout neither in timeouts_last nor " 190 uint32_t util_timeout_next(
struct timeout_manager *mgr, uint32_t cur_ts)
202 cur_ts &= TIMEOUT_MASK;
204 return (next < 0 ? 0 : next);
207 static inline void move_due_timeouts(
struct timeout_manager *mgr, uint32_t cur_ts)
234 static inline int timeout_due(
struct timeout *to, uint32_t ts)
236 return rel_time(ts, to) <= 0;
239 static inline uint32_t timestamp_us_long(
void)
241 return util_rdtsc() / tsc_per_us;
244 static inline uint32_t timestamp_us(
void)
246 return timestamp_us_long() & TIMEOUT_MASK;
249 static inline int32_t rel_time(uint32_t cur_ts,
struct timeout *to)
251 const uint32_t middle = (1 << (TIMEOUT_BITS - 1));
255 if (cur_ts < middle) {
257 start = (cur_ts - middle) & TIMEOUT_MASK;
258 end = (1 << TIMEOUT_BITS);
259 if (start <= to_ts && to_ts < end) {
261 return to_ts - start - middle;
264 return to_ts - cur_ts;
266 }
else if (cur_ts == middle) {
268 return to_ts - cur_ts;
272 end = ((cur_ts + middle) & TIMEOUT_MASK) + 1;
273 if (start <= cur_ts && to_ts < end) {
275 return to_ts + ((1 << TIMEOUT_BITS) - cur_ts);
278 return to_ts - cur_ts;
284 static inline void calibrate_tsc(
void)
286 struct timespec ts_before, ts_after;
293 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts_before) != 0) {
294 fprintf(stderr,
"calibrate_tsc: clock_gettime(CLOCK_MONOTONIC_RAW) " 301 tsc = util_rdtsc() - tsc;
303 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts_after) != 0) {
304 fprintf(stderr,
"calibrate_tsc: clock_gettime(CLOCK_MONOTONIC_RAW) " 309 freq = ((ts_after.tv_sec * 1000000UL) + (ts_after.tv_nsec / 1000)) -
310 ((ts_before.tv_sec * 1000000UL) + (ts_before.tv_nsec / 1000));
311 tsc_per_us = tsc / freq;
struct timeout * timeouts_first
uint32_t timeout_type
Time and type. Type is stored in the 4 most significant bits, and the time in the 28 least significan...
uint32_t util_timeout_time_us(void)
struct timeout * timeouts_last
struct timeout * due_last
struct timeout * due_first
int util_timeout_init(struct timeout_manager *mgr, void(*handler)(struct timeout *, uint8_t, void *), void *handler_opaque)
void util_timeout_poll(struct timeout_manager *mgr)
void(* handler)(struct timeout *, uint8_t, void *)
void util_timeout_disarm(struct timeout_manager *mgr, struct timeout *to)
void util_timeout_poll_ts(struct timeout_manager *mgr, uint32_t cur_ts)
void util_timeout_arm_ts(struct timeout_manager *mgr, struct timeout *to, uint32_t us, uint8_t type, uint32_t cur_ts)
void util_timeout_arm(struct timeout_manager *mgr, struct timeout *to, uint32_t us, uint8_t type)