scx_layered: Add timer helpers

Add registry of timers and a helper for running timers.

Signed-off-by: Daniel Hodges <hodges.daniel.scott@gmail.com>
This commit is contained in:
Daniel Hodges 2024-10-22 05:00:36 -07:00
parent d5b8aafa1a
commit 4898f5082a
4 changed files with 118 additions and 1 deletions

View File

@ -47,7 +47,7 @@ enum consts {
LO_FALLBACK_DSQ = (MAX_LAYERS * MAX_LLCS) + MAX_LLCS + 1,
/* XXX remove */
MAX_CGRP_PREFIXES = 32
MAX_CGRP_PREFIXES = 32
};
enum layer_kind {

View File

@ -10,6 +10,7 @@
#endif
#include "intf.h"
#include "timer.bpf.h"
#include <errno.h>
#include <stdbool.h>
@ -49,6 +50,23 @@ static u32 preempt_cursor;
#include "util.bpf.c"
static __always_inline bool run_timer_cb(int key)
{
switch (key) {
case NOOP_TIMER:
case MAX_TIMERS:
default:
return false;
}
}
struct layered_timer layered_timers[MAX_TIMERS] = {
{0, CLOCK_BOOTTIME, 0},
};
#include "timer.bpf.c"
UEI_DEFINE(uei);
static inline bool vtime_before(u64 a, u64 b)
@ -2245,6 +2263,7 @@ s32 BPF_STRUCT_OPS_SLEEPABLE(layered_init)
}
}
}
start_layered_timers();
return 0;
}

View File

@ -0,0 +1,74 @@
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
struct timer_wrapper {
struct bpf_timer timer;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, MAX_TIMERS);
__type(key, int);
__type(value, struct timer_wrapper);
} layered_timer_data SEC(".maps");
static int layered_timer_cb(void *map, int key, struct timer_wrapper *timerw)
{
struct layered_timer *cb_timer = MEMBER_VPTR(layered_timers, [key]);
bool resched = run_timer_cb(key);
if (!resched || cb_timer->interval_ns == 0) {
return 0;
}
return bpf_timer_start(&timerw->timer,
cb_timer->interval_ns,
cb_timer->start_flags);
}
static int start_layered_timers(void)
{
struct timer_wrapper *timerw;
int timer_id, err;
bpf_for(timer_id, 0, MAX_TIMERS) {
timerw = bpf_map_lookup_elem(&layered_timer_data, &timer_id);
if (!timerw) {
scx_bpf_error("Failed to lookup layered timer");
return -ENOENT;
}
struct layered_timer *new_timer = MEMBER_VPTR(layered_timers, [timer_id]);
if (!new_timer) {
scx_bpf_error("can't happen");
return -ENOENT;
}
err = bpf_timer_init(&timerw->timer,
&layered_timer_data, new_timer->init_flags);
if (err) {
scx_bpf_error("can't happen");
return -ENOENT;
}
err = bpf_timer_set_callback(&timerw->timer, &layered_timer_cb);
if (err) {
scx_bpf_error("can't happen");
return -ENOENT;
}
err = bpf_timer_start(&timerw->timer,
new_timer->interval_ns,
new_timer->start_flags);
if (err) {
scx_bpf_error("can't happen");
return -ENOENT;
}
}
return 0;
}

View File

@ -0,0 +1,24 @@
/* Copyright (c) Meta Platforms, Inc. and affiliates. */
#ifndef __LAYERED_TIMER_H
#define __LAYERED_TIMER_H
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
enum timer_consts {
// kernel definitions
CLOCK_BOOTTIME = 7,
};
struct layered_timer {
// if set to 0 the timer will only be scheduled once
int interval_ns;
u64 init_flags;
u64 start_flags;
};
enum layer_timer_callbacks {
NOOP_TIMER,
MAX_TIMERS,
};
#endif /* __LAYERED_TIMER_H */