[PATCH stalld 44/52] stalld: use CLOCK_MONOTONIC for starvation detection
Wander Lairson Costa <[email protected]> Mon, 8 Jun 2026 15:31:54 -0300
| Newsgroups | org.kernel.vger.linux-rt-users |
|---|---|
| Message-ID | <[email protected]> |
Starvation detection relies on time(NULL) to track how long tasks have been waiting. Wall-clock time is subject to NTP adjustments, so a backward clock step can make elapsed durations appear negative and prevent the daemon from ever boosting legitimately starving tasks. Replace all time(NULL) calls with a get_monotonic_time() helper that reads CLOCK_MONOTONIC via clock_gettime(). Monotonic time only moves forward, making starvation tracking immune to external clock changes. Signed-off-by: Wander Lairson Costa <[email protected]> --- src/queue_track.c | 2 +- src/sched_debug.c | 2 +- src/stalld.c | 16 ++++++++-------- src/stalld.h | 8 ++++++++ 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/queue_track.c b/src/queue_track.c index 6089277..2c1a11b 100644 --- a/src/queue_track.c +++ b/src/queue_track.c @@ -195,7 +195,7 @@ static int queue_track_parse(struct cpu_info *cpu_info, char *buffer, size_t buf task->ctxsw = qtask.ctxswc; - task->since = time(NULL); + task->since = get_monotonic_time(); nr_running++; diff --git a/src/sched_debug.c b/src/sched_debug.c index 5e9a9e8..25a11ce 100644 --- a/src/sched_debug.c +++ b/src/sched_debug.c @@ -478,7 +478,7 @@ static int parse_task_lines(char *buffer, struct task_info *task_info, int nr_en task->tgid = get_tgid(task->pid); task->ctxsw = ctxsw; task->prio = prio; - task->since = time(NULL); + task->since = get_monotonic_time(); /* increment the count of tasks processed */ tasks++; } diff --git a/src/stalld.c b/src/stalld.c index a9e98ff..1762033 100644 --- a/src/stalld.c +++ b/src/stalld.c @@ -326,7 +326,7 @@ void print_waiting_tasks(struct cpu_info *cpu_info) if (!config_verbose) return; - now = time(NULL); + now = get_monotonic_time(); printf("CPU %d has %d waiting tasks\n", cpu_info->id, cpu_info->nr_waiting_tasks); if (!cpu_info->nr_waiting_tasks) return; @@ -646,12 +646,12 @@ int check_starving_tasks(struct cpu_info *cpu) task = &tasks[i]; /* Skip tasks that haven't been starving long enough */ - if ((time(NULL) - task->since) < config_starving_threshold) + if ((get_monotonic_time() - task->since) < config_starving_threshold) continue; log_msg("%s-%d starved on CPU %d for %d seconds\n", task->comm, task->pid, cpu->id, - (time(NULL) - task->since)); + (get_monotonic_time() - task->since)); /* * Check if this task needs to be ignored from being boosted @@ -659,7 +659,7 @@ int check_starving_tasks(struct cpu_info *cpu) * getting reported as being starved. */ if (config_ignore && !(check_task_ignore(task))) { - task->since = time(NULL); + task->since = get_monotonic_time(); continue; } @@ -670,7 +670,7 @@ int check_starving_tasks(struct cpu_info *cpu) * after logging. */ if (config_log_only) { - task->since = time(NULL); + task->since = get_monotonic_time(); continue; } @@ -693,11 +693,11 @@ int check_might_starve_tasks(struct cpu_info *cpu) for (i = 0; i < cpu->nr_waiting_tasks; i++) { task = &tasks[i]; - if ((time(NULL) - task->since) >= config_starving_threshold/2) { + if ((get_monotonic_time() - task->since) >= config_starving_threshold/2) { log_msg("%s-%d might starve on CPU %d (waiting for %d seconds)\n", task->comm, task->pid, cpu->id, - (time(NULL) - task->since)); + (get_monotonic_time() - task->since)); starving = 1; } @@ -933,7 +933,7 @@ int boost_cpu_starving_vector(struct cpu_starving_task_info *vector, int nr_cpus int ret; int i; - now = time(NULL); + now = get_monotonic_time(); /* Boost phase. */ for (i = 0; i < nr_cpus; i++) { diff --git a/src/stalld.h b/src/stalld.h index 8b6ab8b..2df6f94 100644 --- a/src/stalld.h +++ b/src/stalld.h @@ -13,6 +13,7 @@ #include <sched.h> #include <stdatomic.h> #include <signal.h> +#include <time.h> #define BUFFER_PAGES 10 #define MAX_WAITING_PIDS 30 @@ -49,6 +50,13 @@ */ #define DAEMON_UMASK 0022 +static inline time_t get_monotonic_time(void) +{ + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec; +} + /* * Informnation about running tasks on a CPU. */ -- 2.54.0