summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-27 19:15:22 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-27 19:15:22 +0100
commit8fb1c09df1540aa3fca1148bed6a08ffc3090669 (patch)
treeeb03f2a9f3eb8e074abc0533aac7f5ab7cd8926c
parentdf5557705764d5e8f904a31d549fc037f5b1cf47 (diff)
All OSes now do have a cheap monotonic clock, so no caching thread is needed. Also add some relative time helpers
-rw-r--r--opentracker.c19
-rw-r--r--ot_accesslist.c12
-rw-r--r--ot_clean.c6
-rw-r--r--ot_http.c6
-rw-r--r--ot_livesync.c10
-rw-r--r--ot_stats.c2
-rw-r--r--ot_udp.c8
-rw-r--r--tests/stubs.c3
-rw-r--r--trackerlogic.c4
-rw-r--r--trackerlogic.h29
10 files changed, 54 insertions, 45 deletions
diff --git a/opentracker.c b/opentracker.c
index 11da486..6271b9e 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -39,7 +39,6 @@
39#include "trackerlogic.h" 39#include "trackerlogic.h"
40 40
41/* Globals */ 41/* Globals */
42time_t g_now_seconds;
43uint32_t g_tracker_id; 42uint32_t g_tracker_id;
44volatile int g_opentracker_running = 1; 43volatile int g_opentracker_running = 1;
45int g_self_pipe[2]; 44int g_self_pipe[2];
@@ -203,7 +202,7 @@ static void handle_write(const int64_t sock) {
203 waiting to write and go back to waiting for the next request */ 202 waiting to write and go back to waiting for the next request */
204 http_interest_drop(sock, cookie, EVENT_OUT); 203 http_interest_drop(sock, cookie, EVENT_OUT);
205 http_interest_add(sock, cookie, EVENT_IN); 204 http_interest_add(sock, cookie, EVENT_IN);
206 fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT); 205 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT));
207 } else 206 } else
208 handle_dead(sock); 207 handle_dead(sock);
209} 208}
@@ -226,7 +225,7 @@ static void handle_accept(const int64_t serversocket) {
226 memcpy(cookie->ip, ip, sizeof(ot_ip6)); 225 memcpy(cookie->ip, ip, sizeof(ot_ip6));
227 cookie->interest = EVENT_IN; 226 cookie->interest = EVENT_IN;
228 227
229 if (event_add((int)sock, EVENT_IN, fdstate_open(sock, cookie, g_now_seconds + OT_CLIENT_TIMEOUT)) == -1) { 228 if (event_add((int)sock, EVENT_IN, fdstate_open(sock, cookie, time_future_seconds(OT_CLIENT_TIMEOUT))) == -1) {
230 fdstate_close(sock); 229 fdstate_close(sock);
231 free(cookie); 230 free(cookie);
232 close((int)sock); 231 close((int)sock);
@@ -242,7 +241,7 @@ static void handle_accept(const int64_t serversocket) {
242 241
243static void *server_mainloop(void *args) { 242static void *server_mainloop(void *args) {
244 struct ot_workstruct ws; 243 struct ot_workstruct ws;
245 time_t next_timeout_check = g_now_seconds + OT_CLIENT_TIMEOUT_CHECKINTERVAL; 244 time_t next_timeout_check = time_future_seconds(OT_CLIENT_TIMEOUT_CHECKINTERVAL);
246 struct iovec *iovector; 245 struct iovec *iovector;
247 size_t iovec_entries; 246 size_t iovec_entries;
248 int is_partial; 247 int is_partial;
@@ -461,17 +460,7 @@ int drop_privileges(const char *const serveruser, const char *const serverdir) {
461} 460}
462 461
463/* Maintain our copy of the clock. time() on BSDs is very expensive. */ 462/* Maintain our copy of the clock. time() on BSDs is very expensive. */
464static void *time_caching_worker(void *args) {
465 (void)args;
466 while (1) {
467 g_now_seconds = time(NULL);
468 sleep(5);
469 }
470 return NULL;
471}
472
473int main(int argc, char **argv) { 463int main(int argc, char **argv) {
474 pthread_t thread_id; /* time cacher */
475 464
476 random_init(); 465 random_init();
477 if (fdstate_init() == -1) 466 if (fdstate_init() == -1)
@@ -492,8 +481,6 @@ int main(int argc, char **argv) {
492 if (drop_privileges(g_serveruser ? g_serveruser : "nobody", g_serverdir) == -1) 481 if (drop_privileges(g_serveruser ? g_serveruser : "nobody", g_serverdir) == -1)
493 panic("drop_privileges failed, exiting. Last error"); 482 panic("drop_privileges failed, exiting. Last error");
494 483
495 g_now_seconds = time(NULL);
496 pthread_create(&thread_id, NULL, time_caching_worker, NULL);
497 484
498 /* Create our self pipe which allows us to interrupt mainloops 485 /* Create our self pipe which allows us to interrupt mainloops
499 wait in case some data is available to send out */ 486 wait in case some data is available to send out */
diff --git a/ot_accesslist.c b/ot_accesslist.c
index 4bf1701..e8e0476 100644
--- a/ot_accesslist.c
+++ b/ot_accesslist.c
@@ -93,7 +93,7 @@ static ot_accesslist *accesslist_make(ot_accesslist *next, size_t size) {
93 This will never delete head, because that might still be in use. */ 93 This will never delete head, because that might still be in use. */
94static void accesslist_clean(ot_accesslist *accesslist) { 94static void accesslist_clean(ot_accesslist *accesslist) {
95 while (accesslist && accesslist->next) { 95 while (accesslist && accesslist->next) {
96 if (accesslist->next->base + 5 < g_now_minutes) 96 if (accesslist->next->base + 5 < time_now_minutes())
97 accesslist->next = accesslist_free(accesslist->next); 97 accesslist->next = accesslist_free(accesslist->next);
98 accesslist = accesslist->next; 98 accesslist = accesslist->next;
99 } 99 }
@@ -197,7 +197,7 @@ static void accesslist_readfile(void) {
197 197
198 /* Mark old accesslist as "needs to live another five minutes" */ 198 /* Mark old accesslist as "needs to live another five minutes" */
199 if (g_accesslist) 199 if (g_accesslist)
200 g_accesslist->base = g_now_minutes; 200 g_accesslist->base = time_now_minutes();
201 accesslist_new->next = g_accesslist; 201 accesslist_new->next = g_accesslist;
202 g_accesslist = accesslist_new; /* Only now set a new list */ 202 g_accesslist = accesslist_new; /* Only now set a new list */
203 203
@@ -205,11 +205,11 @@ static void accesslist_readfile(void) {
205 /* If we have dynamic accesslists, reloading a new one will always void the add/delete lists. 205 /* If we have dynamic accesslists, reloading a new one will always void the add/delete lists.
206 Insert empty ones at the list head */ 206 Insert empty ones at the list head */
207 if (g_accesslist_add && (accesslist_new = accesslist_make(g_accesslist_add, 0)) != NULL) { 207 if (g_accesslist_add && (accesslist_new = accesslist_make(g_accesslist_add, 0)) != NULL) {
208 g_accesslist_add->base = g_now_minutes; 208 g_accesslist_add->base = time_now_minutes();
209 g_accesslist_add = accesslist_new; 209 g_accesslist_add = accesslist_new;
210 } 210 }
211 if (g_accesslist_delete && (accesslist_new = accesslist_make(g_accesslist_delete, 0)) != NULL) { 211 if (g_accesslist_delete && (accesslist_new = accesslist_make(g_accesslist_delete, 0)) != NULL) {
212 g_accesslist_delete->base = g_now_minutes; 212 g_accesslist_delete->base = time_now_minutes();
213 g_accesslist_delete = accesslist_new; 213 g_accesslist_delete = accesslist_new;
214 } 214 }
215#endif 215#endif
@@ -326,7 +326,7 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_
326 if (accesslist_new) { 326 if (accesslist_new) {
327 memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off); 327 memcpy(accesslist_new->list, (*removing_from)->list, sizeof(ot_hash) * off);
328 memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, sizeof(ot_hash) * ((*removing_from)->size - off - 1)); 328 memcpy(accesslist_new->list + off, (*removing_from)->list + off + 1, sizeof(ot_hash) * ((*removing_from)->size - off - 1));
329 (*removing_from)->base = g_now_minutes; 329 (*removing_from)->base = time_now_minutes();
330 *removing_from = accesslist_new; 330 *removing_from = accesslist_new;
331 } 331 }
332 } 332 }
@@ -351,7 +351,7 @@ static void *accesslist_adddel_worker(const char *fifoname, ot_accesslist *_
351 memcpy(accesslist_new->list, (*adding_to)->list, sizeof(ot_hash) * off); 351 memcpy(accesslist_new->list, (*adding_to)->list, sizeof(ot_hash) * off);
352 memcpy(accesslist_new->list + off, info_hash, sizeof(info_hash)); 352 memcpy(accesslist_new->list + off, info_hash, sizeof(info_hash));
353 memcpy(accesslist_new->list + off + 1, (*adding_to)->list + off, sizeof(ot_hash) * ((*adding_to)->size - off)); 353 memcpy(accesslist_new->list + off + 1, (*adding_to)->list + off, sizeof(ot_hash) * ((*adding_to)->size - off));
354 (*adding_to)->base = g_now_minutes; 354 (*adding_to)->base = time_now_minutes();
355 *adding_to = accesslist_new; 355 *adding_to = accesslist_new;
356 } 356 }
357 } 357 }
diff --git a/ot_clean.c b/ot_clean.c
index bf0504c..dbfa04e 100644
--- a/ot_clean.c
+++ b/ot_clean.c
@@ -46,7 +46,7 @@ static ssize_t clean_single_bucket(ot_peer *peers, size_t peer_count, size_t pee
46 46
47int clean_single_peer_list(ot_peerlist *peer_list, size_t peer_size) { 47int clean_single_peer_list(ot_peerlist *peer_list, size_t peer_size) {
48 ot_vector *peer_vector = &peer_list->peers; 48 ot_vector *peer_vector = &peer_list->peers;
49 time_t timedout = (time_t)(g_now_minutes - peer_list->base); 49 time_t timedout = (time_t)(time_now_minutes() - peer_list->base);
50 size_t num_buckets = 1, removed_seeders = 0; 50 size_t num_buckets = 1, removed_seeders = 0;
51 51
52 /* No need to clean empty torrent */ 52 /* No need to clean empty torrent */
@@ -87,11 +87,11 @@ int clean_single_peer_list(ot_peerlist *peer_list, size_t peer_size) {
87 vector_redistribute_buckets(peer_list, peer_size); 87 vector_redistribute_buckets(peer_list, peer_size);
88 88
89 if (peer_list->peer_count) 89 if (peer_list->peer_count)
90 peer_list->base = g_now_minutes; 90 peer_list->base = time_now_minutes();
91 else { 91 else {
92 /* When we got here, the last time that torrent 92 /* When we got here, the last time that torrent
93 has been touched is OT_PEER_TIMEOUT Minutes before */ 93 has been touched is OT_PEER_TIMEOUT Minutes before */
94 peer_list->base = g_now_minutes - OT_PEER_TIMEOUT; 94 peer_list->base = time_now_minutes() - OT_PEER_TIMEOUT;
95 } 95 }
96 return 0; 96 return 0;
97} 97}
diff --git a/ot_http.c b/ot_http.c
index 2216453..c4f74db 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -222,7 +222,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
222 cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; 222 cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER;
223 } 223 }
224 224
225 fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT_SEND); 225 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT_SEND));
226 http_interest_add(sock, cookie, EVENT_OUT); 226 http_interest_add(sock, cookie, EVENT_OUT);
227 return 0; 227 return 0;
228} 228}
@@ -359,7 +359,7 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
359 ot_scrape_log this_peer, *new_peer; 359 ot_scrape_log this_peer, *new_peer;
360 int exactmatch; 360 int exactmatch;
361 memcpy(this_peer.ip, cookie->ip, sizeof(ot_ip6)); 361 memcpy(this_peer.ip, cookie->ip, sizeof(ot_ip6));
362 this_peer.last_fullscrape = g_now_seconds; 362 this_peer.last_fullscrape = time_now_seconds();
363 pthread_mutex_lock(&g_modest_fullscrape_mutex); 363 pthread_mutex_lock(&g_modest_fullscrape_mutex);
364 new_peer = vector_find_or_insert(&g_modest_fullscrape_timeouts, &this_peer, sizeof(ot_scrape_log), sizeof(ot_ip6), &exactmatch); 364 new_peer = vector_find_or_insert(&g_modest_fullscrape_timeouts, &this_peer, sizeof(ot_scrape_log), sizeof(ot_ip6), &exactmatch);
365 if (!new_peer) { 365 if (!new_peer) {
@@ -710,7 +710,7 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) {
710 log->size = ws->request_size; 710 log->size = ws->request_size;
711 log->data = malloc(ws->request_size); 711 log->data = malloc(ws->request_size);
712 log->next = 0; 712 log->next = 0;
713 log->time = g_now_seconds; 713 log->time = time_now_seconds();
714 memcpy(log->ip, cookie->ip, sizeof(ot_ip6)); 714 memcpy(log->ip, cookie->ip, sizeof(ot_ip6));
715 if (log->data) { 715 if (log->data) {
716 memcpy(log->data, ws->request, ws->request_size); 716 memcpy(log->data, ws->request, ws->request_size);
diff --git a/ot_livesync.c b/ot_livesync.c
index 5a63f3c..fb0bef2 100644
--- a/ot_livesync.c
+++ b/ot_livesync.c
@@ -70,8 +70,8 @@ void livesync_init(void) {
70 g_v6_buf.fill = sizeof(g_tracker_id) + sizeof(uint32_t); 70 g_v6_buf.fill = sizeof(g_tracker_id) + sizeof(uint32_t);
71 g_v4_buf.fill = sizeof(g_tracker_id) + sizeof(uint32_t); 71 g_v4_buf.fill = sizeof(g_tracker_id) + sizeof(uint32_t);
72 72
73 g_v6_buf.next_packet_time = g_now_seconds + LIVESYNC_MAXDELAY; 73 g_v6_buf.next_packet_time = time_future_seconds(LIVESYNC_MAXDELAY);
74 g_v4_buf.next_packet_time = g_now_seconds + LIVESYNC_MAXDELAY; 74 g_v4_buf.next_packet_time = time_future_seconds(LIVESYNC_MAXDELAY);
75 75
76 pthread_create(&thread_id, NULL, livesync_worker, NULL); 76 pthread_create(&thread_id, NULL, livesync_worker, NULL);
77} 77}
@@ -106,7 +106,7 @@ static void livesync_issue_peersync(sync_buffer *buf) {
106 106
107 memcpy(mycopy, buf->data, fill); 107 memcpy(mycopy, buf->data, fill);
108 buf->fill = sizeof(g_tracker_id) + sizeof(uint32_t); 108 buf->fill = sizeof(g_tracker_id) + sizeof(uint32_t);
109 buf->next_packet_time = g_now_seconds + LIVESYNC_MAXDELAY; 109 buf->next_packet_time = time_future_seconds(LIVESYNC_MAXDELAY);
110 110
111 /* From now this thread has a local copy of the buffer and 111 /* From now this thread has a local copy of the buffer and
112 has modified the protected element */ 112 has modified the protected element */
@@ -152,13 +152,13 @@ static void livesync_handle_peersync(struct ot_workstruct *ws, size_t peer_size)
152void livesync_ticker(void) { 152void livesync_ticker(void) {
153 /* livesync_issue_peersync sets g_next_packet_time */ 153 /* livesync_issue_peersync sets g_next_packet_time */
154 pthread_mutex_lock(&g_outbuf_mutex); 154 pthread_mutex_lock(&g_outbuf_mutex);
155 if (g_now_seconds > g_v6_buf.next_packet_time && g_v6_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t)) 155 if (time_now_seconds() > g_v6_buf.next_packet_time && g_v6_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t))
156 livesync_issue_peersync(&g_v6_buf); 156 livesync_issue_peersync(&g_v6_buf);
157 else 157 else
158 pthread_mutex_unlock(&g_outbuf_mutex); 158 pthread_mutex_unlock(&g_outbuf_mutex);
159 159
160 pthread_mutex_lock(&g_outbuf_mutex); 160 pthread_mutex_lock(&g_outbuf_mutex);
161 if (g_now_seconds > g_v4_buf.next_packet_time && g_v4_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t)) 161 if (time_now_seconds() > g_v4_buf.next_packet_time && g_v4_buf.fill > sizeof(g_tracker_id) + sizeof(uint32_t))
162 livesync_issue_peersync(&g_v4_buf); 162 livesync_issue_peersync(&g_v4_buf);
163 else 163 else
164 pthread_mutex_unlock(&g_outbuf_mutex); 164 pthread_mutex_unlock(&g_outbuf_mutex);
diff --git a/ot_stats.c b/ot_stats.c
index 45dc8db..c6af116 100644
--- a/ot_stats.c
+++ b/ot_stats.c
@@ -739,7 +739,7 @@ void stats_deliver(int64_t sock, int tasktype) { mutex_workqueue_pushtask(sock,
739 739
740static pthread_t thread_id; 740static pthread_t thread_id;
741void stats_init(void) { 741void stats_init(void) {
742 ot_start_time = g_now_seconds; 742 ot_start_time = time_now_seconds();
743 pthread_create(&thread_id, NULL, stats_worker, NULL); 743 pthread_create(&thread_id, NULL, stats_worker, NULL);
744} 744}
745 745
diff --git a/ot_udp.c b/ot_udp.c
index 4e760bb..19a6c7c 100644
--- a/ot_udp.c
+++ b/ot_udp.c
@@ -30,7 +30,7 @@ static void udp_generate_rijndael_round_key(void) {
30 rijndaelKeySetupEnc128(g_rijndael_round_key, (uint8_t *)key); 30 rijndaelKeySetupEnc128(g_rijndael_round_key, (uint8_t *)key);
31 31
32 g_key_of_the_hour[0] = random_uint32(); 32 g_key_of_the_hour[0] = random_uint32();
33 g_hour_of_the_key = g_now_minutes; 33 g_hour_of_the_key = time_now_minutes();
34} 34}
35 35
36/* Generate current and previous connection id for ip */ 36/* Generate current and previous connection id for ip */
@@ -39,14 +39,14 @@ static void udp_make_connectionid(uint32_t connid[2], const ot_ip6 remoteip, int
39 int i; 39 int i;
40 uint32_t current_key_of_the_hour; 40 uint32_t current_key_of_the_hour;
41 41
42 if (g_now_minutes - g_hour_of_the_key >= 60) { 42 if (time_now_minutes() - g_hour_of_the_key >= 60) {
43 uint32_t old_key_of_the_hour = g_key_of_the_hour[0]; 43 uint32_t old_key_of_the_hour = g_key_of_the_hour[0];
44 uint32_t new_key_of_the_hour = random_uint32(); 44 uint32_t new_key_of_the_hour = random_uint32();
45 /* If in the meantime another thread has performed 45 /* If in the meantime another thread has performed
46 key rotation, do not overwrite their results */ 46 key rotation, do not overwrite their results */
47 if (g_now_minutes - g_hour_of_the_key >= 60) { 47 if (time_now_minutes() - g_hour_of_the_key >= 60) {
48 /* Upgrade en bloc */ 48 /* Upgrade en bloc */
49 g_hour_of_the_key = g_now_minutes; 49 g_hour_of_the_key = time_now_minutes();
50 g_key_of_the_hour[0] = new_key_of_the_hour; 50 g_key_of_the_hour[0] = new_key_of_the_hour;
51 g_key_of_the_hour[1] = old_key_of_the_hour; 51 g_key_of_the_hour[1] = old_key_of_the_hour;
52 } 52 }
diff --git a/tests/stubs.c b/tests/stubs.c
index 09a7312..a8e6962 100644
--- a/tests/stubs.c
+++ b/tests/stubs.c
@@ -16,8 +16,7 @@ void free_peerlist(ot_peerlist *peer_list) { (void)peer_list; }
16/* ot_accesslist.c is built with WANT_ACCESSLIST_BLACK so that the hash parser 16/* ot_accesslist.c is built with WANT_ACCESSLIST_BLACK so that the hash parser
17 is reachable. These two belong to accesslist_readfile and the reload worker, 17 is reachable. These two belong to accesslist_readfile and the reload worker,
18 neither of which any test drives. */ 18 neither of which any test drives. */
19time_t g_now_seconds; 19_Atomic int g_opentracker_running;
20volatile int g_opentracker_running;
21 20
22/* ot_mutex.c wakes the main loop through the self pipe when a result is 21/* ot_mutex.c wakes the main loop through the self pipe when a result is
23 ready. The queue tests never get that far. */ 22 ready. The queue tests never get that far. */
diff --git a/trackerlogic.c b/trackerlogic.c
index 1f38f07..aac4448 100644
--- a/trackerlogic.c
+++ b/trackerlogic.c
@@ -117,8 +117,8 @@ size_t add_peer_to_torrent_and_return_peers(PROTO_FLAG proto, struct ot_workstru
117 } else 117 } else
118 clean_single_torrent(torrent); 118 clean_single_torrent(torrent);
119 119
120 torrent->peer_list6->base = g_now_minutes; 120 torrent->peer_list6->base = time_now_minutes();
121 torrent->peer_list4->base = g_now_minutes; 121 torrent->peer_list4->base = time_now_minutes();
122 122
123 peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4; 123 peer_list = peer_size == OT_PEER_SIZE6 ? torrent->peer_list6 : torrent->peer_list4;
124 124
diff --git a/trackerlogic.h b/trackerlogic.h
index 63abf78..6af5d6a 100644
--- a/trackerlogic.h
+++ b/trackerlogic.h
@@ -6,6 +6,7 @@
6#ifndef OT_TRACKERLOGIC_H__ 6#ifndef OT_TRACKERLOGIC_H__
7#define OT_TRACKERLOGIC_H__ 7#define OT_TRACKERLOGIC_H__
8 8
9#include <stdatomic.h>
9#include <stdint.h> 10#include <stdint.h>
10#include <stdlib.h> 11#include <stdlib.h>
11#include <sys/time.h> 12#include <sys/time.h>
@@ -68,9 +69,31 @@ typedef struct {
68#define RANDOMTORRENTS (1024 * 1024 * 1) 69#define RANDOMTORRENTS (1024 * 1024 * 1)
69 70
70/* From opentracker.c */ 71/* From opentracker.c */
71extern time_t g_now_seconds; 72/* The kernel already keeps a coarse wall clock, updated every tick and
72extern volatile int g_opentracker_running; 73 published where reading it costs no system call. That is what opentracker
73#define g_now_minutes (g_now_seconds / 60) 74 used to keep a thread for, at five second resolution. */
75#if defined(CLOCK_REALTIME_COARSE)
76#define OT_CLOCK_CHEAP CLOCK_REALTIME_COARSE /* Linux */
77#elif defined(CLOCK_REALTIME_FAST)
78#define OT_CLOCK_CHEAP CLOCK_REALTIME_FAST /* the BSDs */
79#else
80#define OT_CLOCK_CHEAP CLOCK_REALTIME /* macOS and whatever else */
81#endif
82
83static inline ot_time time_now_seconds(void) {
84 struct timespec now;
85 clock_gettime(OT_CLOCK_CHEAP, &now);
86 return (ot_time)now.tv_sec;
87}
88
89static inline ot_time time_now_minutes(void) { return time_now_seconds() / 60; }
90
91/* For the deadlines the tracker sets on itself, which read better as the
92 span they allow than as an addition to the current second */
93static inline ot_time time_future_seconds(int span) { return time_now_seconds() + span; }
94/* Cleared from the interrupt handler and read by every worker */
95extern _Atomic int g_opentracker_running;
96
74 97
75extern uint32_t g_tracker_id; 98extern uint32_t g_tracker_id;
76typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA, FLAG_SELFPIPE } PROTO_FLAG; 99typedef enum { FLAG_TCP, FLAG_UDP, FLAG_MCA, FLAG_SELFPIPE } PROTO_FLAG;