From 37b3431e0079f988e2b4b5121e429bb23c02a261 Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Wed, 29 Jun 2022 12:31:25 +0000 Subject: [PATCH] main: Add a canary ticker This should help to notice when something is badly blocking the main loop. --- include/time-util.h | 46 +++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 include/time-util.h diff --git a/include/time-util.h b/include/time-util.h new file mode 100644 index 0000000..9f9fa2b --- /dev/null +++ b/include/time-util.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 - 2020 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include +#include + +static inline uint64_t timespec_to_us(const struct timespec* ts) +{ + return (uint64_t)ts->tv_sec * UINT64_C(1000000) + + (uint64_t)ts->tv_nsec / UINT64_C(1000); +} + +static inline uint64_t timespec_to_ms(const struct timespec* ts) +{ + return (uint64_t)ts->tv_sec * UINT64_C(1000) + + (uint64_t)ts->tv_nsec / UINT64_C(1000000); +} + +static inline uint64_t gettime_us(void) +{ + struct timespec ts = { 0 }; + clock_gettime(CLOCK_MONOTONIC, &ts); + return timespec_to_us(&ts); +} + +static inline uint64_t gettime_ms(void) +{ + struct timespec ts = { 0 }; + clock_gettime(CLOCK_MONOTONIC, &ts); + return timespec_to_ms(&ts); +} diff --git a/src/main.c b/src/main.c index 3a47b4e..a508f63 100644 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,10 @@ #include "renderer.h" #include "renderer-egl.h" #include "linux-dmabuf-unstable-v1.h" +#include "time-util.h" + +#define CANARY_TICK_PERIOD INT64_C(100000) // us +#define CANARY_LETHALITY_LEVEL INT64_C(8000) // us struct window { struct wl_surface* wl_surface; @@ -70,6 +74,7 @@ static struct wl_list seats; struct pointer_collection* pointers; struct keyboard_collection* keyboards; static int drm_fd = -1; +static uint64_t last_canary_tick; static bool have_egl = false; @@ -670,6 +675,35 @@ failure: return -1; } +static void on_canary_tick(void* obj) +{ + (void)obj; + + uint64_t t = gettime_us(); + int64_t dt = t - last_canary_tick; + last_canary_tick = t; + + int64_t delay = dt - CANARY_TICK_PERIOD; + + // Early ticks are just a result of late ticks... + if (delay < CANARY_LETHALITY_LEVEL) + return; + + fprintf(stderr, "WARNING: Long delays observed (%"PRIi64"). Something is blocking the main loop\n", + delay); +} + +static void create_canary_ticker(void) +{ + last_canary_tick = gettime_us(); + + struct aml* aml = aml_get_default(); + struct aml_ticker* ticker = aml_ticker_new(CANARY_TICK_PERIOD / 1000ULL, + on_canary_tick, NULL, NULL); + aml_start(aml, ticker); + aml_unref(ticker); +} + void run_main_loop_once(void) { struct aml* aml = aml_get_default(); @@ -862,6 +896,8 @@ int main(int argc, char* argv[]) wl_display_dispatch(wl_display); + create_canary_ticker(); + while (do_run) run_main_loop_once();