mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Merge commit 'a4451535' into thread-next
This commit is contained in:
120
sysdep/unix/io.c
120
sysdep/unix/io.c
@@ -36,6 +36,7 @@
|
||||
#include "lib/resource.h"
|
||||
#include "lib/socket.h"
|
||||
#include "lib/event.h"
|
||||
#include "lib/locking.h"
|
||||
#include "lib/timer.h"
|
||||
#include "lib/string.h"
|
||||
#include "nest/iface.h"
|
||||
@@ -122,55 +123,50 @@ rf_fileno(struct rfile *f)
|
||||
|
||||
btime boot_time;
|
||||
|
||||
|
||||
void
|
||||
times_init(struct timeloop *loop)
|
||||
times_update(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
int rv;
|
||||
|
||||
btime old_time = current_time();
|
||||
btime old_real_time = current_real_time();
|
||||
|
||||
rv = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (rv < 0)
|
||||
die("Monotonic clock is missing");
|
||||
|
||||
if ((ts.tv_sec < 0) || (((u64) ts.tv_sec) > ((u64) 1 << 40)))
|
||||
log(L_WARN "Monotonic clock is crazy");
|
||||
|
||||
loop->last_time = ts.tv_sec S + ts.tv_nsec NS;
|
||||
loop->real_time = 0;
|
||||
}
|
||||
|
||||
void
|
||||
times_update(struct timeloop *loop)
|
||||
{
|
||||
struct timespec ts;
|
||||
int rv;
|
||||
|
||||
rv = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (rv < 0)
|
||||
die("clock_gettime: %m");
|
||||
|
||||
|
||||
btime new_time = ts.tv_sec S + ts.tv_nsec NS;
|
||||
|
||||
if (new_time < loop->last_time)
|
||||
if (new_time < old_time)
|
||||
log(L_ERR "Monotonic clock is broken");
|
||||
|
||||
loop->last_time = new_time;
|
||||
loop->real_time = 0;
|
||||
}
|
||||
|
||||
void
|
||||
times_update_real_time(struct timeloop *loop)
|
||||
{
|
||||
struct timespec ts;
|
||||
int rv;
|
||||
|
||||
rv = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
if (rv < 0)
|
||||
die("clock_gettime: %m");
|
||||
|
||||
loop->real_time = ts.tv_sec S + ts.tv_nsec NS;
|
||||
}
|
||||
btime new_real_time = ts.tv_sec S + ts.tv_nsec NS;
|
||||
|
||||
if (!atomic_compare_exchange_strong_explicit(
|
||||
&last_time,
|
||||
&old_time,
|
||||
new_time,
|
||||
memory_order_acq_rel,
|
||||
memory_order_relaxed))
|
||||
DBG("Time update collision: last_time");
|
||||
|
||||
if (!atomic_compare_exchange_strong_explicit(
|
||||
&real_time,
|
||||
&old_real_time,
|
||||
new_real_time,
|
||||
memory_order_acq_rel,
|
||||
memory_order_relaxed))
|
||||
DBG("Time update collision: real_time");
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: Sockets
|
||||
@@ -2037,30 +2033,17 @@ struct event_log_entry
|
||||
static struct event_log_entry event_log[EVENT_LOG_LENGTH];
|
||||
static struct event_log_entry *event_open;
|
||||
static int event_log_pos, event_log_num, watchdog_active;
|
||||
static btime last_time;
|
||||
static btime last_io_time;
|
||||
static btime loop_time;
|
||||
|
||||
static void
|
||||
io_update_time(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
int rv;
|
||||
|
||||
/*
|
||||
* This is third time-tracking procedure (after update_times() above and
|
||||
* times_update() in BFD), dedicated to internal event log and latency
|
||||
* tracking. Hopefully, we consolidate these sometimes.
|
||||
*/
|
||||
|
||||
rv = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (rv < 0)
|
||||
die("clock_gettime: %m");
|
||||
|
||||
last_time = ts.tv_sec S + ts.tv_nsec NS;
|
||||
last_io_time = current_time();
|
||||
|
||||
if (event_open)
|
||||
{
|
||||
event_open->duration = last_time - event_open->timestamp;
|
||||
event_open->duration = last_io_time - event_open->timestamp;
|
||||
|
||||
if (event_open->duration > config->latency_limit)
|
||||
log(L_WARN "Event 0x%p 0x%p took %u.%03u ms",
|
||||
@@ -2089,7 +2072,7 @@ io_log_event(void *hook, void *data)
|
||||
|
||||
en->hook = hook;
|
||||
en->data = data;
|
||||
en->timestamp = last_time;
|
||||
en->timestamp = last_io_time;
|
||||
en->duration = 0;
|
||||
|
||||
event_log_num++;
|
||||
@@ -2117,14 +2100,14 @@ io_log_dump(void)
|
||||
struct event_log_entry *en = event_log + (event_log_pos + i) % EVENT_LOG_LENGTH;
|
||||
if (en->hook)
|
||||
log(L_DEBUG " Event 0x%p 0x%p at %8d for %d ms", en->hook, en->data,
|
||||
(int) ((last_time - en->timestamp) TO_MS), (int) (en->duration TO_MS));
|
||||
(int) ((last_io_time - en->timestamp) TO_MS), (int) (en->duration TO_MS));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
watchdog_sigalrm(int sig UNUSED)
|
||||
{
|
||||
/* Update last_time and duration, but skip latency check */
|
||||
/* Update last_io_time and duration, but skip latency check */
|
||||
config->latency_limit = 0xffffffff;
|
||||
io_update_time();
|
||||
|
||||
@@ -2137,7 +2120,7 @@ watchdog_start1(void)
|
||||
{
|
||||
io_update_time();
|
||||
|
||||
loop_time = last_time;
|
||||
loop_time = last_io_time;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -2145,7 +2128,7 @@ watchdog_start(void)
|
||||
{
|
||||
io_update_time();
|
||||
|
||||
loop_time = last_time;
|
||||
loop_time = last_io_time;
|
||||
event_log_num = 0;
|
||||
|
||||
if (config->watchdog_timeout)
|
||||
@@ -2166,7 +2149,7 @@ watchdog_stop(void)
|
||||
watchdog_active = 0;
|
||||
}
|
||||
|
||||
btime duration = last_time - loop_time;
|
||||
btime duration = last_io_time - loop_time;
|
||||
if (duration > config->watchdog_warning)
|
||||
log(L_WARN "I/O loop cycle took %u.%03u ms for %d events",
|
||||
(uint) (duration TO_MS), (uint) (duration % 1000), event_log_num);
|
||||
@@ -2196,6 +2179,15 @@ static int short_loops = 0;
|
||||
#define SHORT_LOOP_MAX 10
|
||||
#define WORK_EVENTS_MAX 10
|
||||
|
||||
static int poll_reload_pipe[2];
|
||||
|
||||
void
|
||||
io_loop_reload(void)
|
||||
{
|
||||
char b;
|
||||
write(poll_reload_pipe[1], &b, 1);
|
||||
}
|
||||
|
||||
void
|
||||
io_loop(void)
|
||||
{
|
||||
@@ -2207,10 +2199,13 @@ io_loop(void)
|
||||
int fdmax = 256;
|
||||
struct pollfd *pfd = xmalloc(fdmax * sizeof(struct pollfd));
|
||||
|
||||
if (pipe(poll_reload_pipe) < 0)
|
||||
die("pipe(poll_reload_pipe) failed: %m");
|
||||
|
||||
watchdog_start1();
|
||||
for(;;)
|
||||
{
|
||||
times_update(&main_timeloop);
|
||||
times_update();
|
||||
events = ev_run_list(&global_event_list);
|
||||
events = ev_run_list_limited(&global_work_list, WORK_EVENTS_MAX) || events;
|
||||
timers_fire(&main_timeloop);
|
||||
@@ -2220,12 +2215,17 @@ io_loop(void)
|
||||
poll_tout = (events ? 0 : 3000); /* Time in milliseconds */
|
||||
if (t = timers_first(&main_timeloop))
|
||||
{
|
||||
times_update(&main_timeloop);
|
||||
times_update();
|
||||
timeout = (tm_remains(t) TO_MS) + 1;
|
||||
poll_tout = MIN(poll_tout, timeout);
|
||||
}
|
||||
|
||||
nfds = 0;
|
||||
/* A hack to reload main io_loop() when something has changed asynchronously. */
|
||||
pfd[0].fd = poll_reload_pipe[0];
|
||||
pfd[0].events = POLLIN;
|
||||
|
||||
nfds = 1;
|
||||
|
||||
WALK_LIST(n, sock_list)
|
||||
{
|
||||
pfd[nfds] = (struct pollfd) { .fd = -1 }; /* everything other set to 0 by this */
|
||||
@@ -2284,7 +2284,9 @@ io_loop(void)
|
||||
|
||||
/* And finally enter poll() to find active sockets */
|
||||
watchdog_stop();
|
||||
the_bird_unlock();
|
||||
pout = poll(pfd, nfds, poll_tout);
|
||||
the_bird_lock();
|
||||
watchdog_start();
|
||||
|
||||
if (pout < 0)
|
||||
@@ -2295,7 +2297,15 @@ io_loop(void)
|
||||
}
|
||||
if (pout)
|
||||
{
|
||||
times_update(&main_timeloop);
|
||||
if (pfd[0].revents & POLLIN)
|
||||
{
|
||||
/* IO loop reload requested */
|
||||
char b;
|
||||
read(poll_reload_pipe[0], &b, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
times_update();
|
||||
|
||||
/* guaranteed to be non-empty */
|
||||
current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
|
||||
|
Reference in New Issue
Block a user