Message ID | 20230221144803.2216876-1-tero.kristo@linux.intel.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | bpf: Add support for absolute value BPF timers | expand |
Hi, Please ignore this, I added a broken mailing list to CC. Re-sending in a bit. -Tero On 21/02/2023 16:48, Tero Kristo wrote: > Add a new flag BPF_F_TIMER_ABS that can be passed to bpf_timer_start() > to start an absolute value timer instead of the default relative value. > This makes the timer expire at an exact point in time, instead of a time > with latencies and jitter induced by both the BPF and timer subsystems. > This is useful e.g. in certain time sensitive profiling cases, where we > need a timer to expire at an exact point in time. > > Signed-off-by: Tero Kristo <tero.kristo@linux.intel.com> > --- > include/uapi/linux/bpf.h | 15 +++++++++++++++ > kernel/bpf/helpers.c | 11 +++++++++-- > 2 files changed, 24 insertions(+), 2 deletions(-) > > diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h > index 464ca3f01fe7..7f5b71847984 100644 > --- a/include/uapi/linux/bpf.h > +++ b/include/uapi/linux/bpf.h > @@ -4951,6 +4951,12 @@ union bpf_attr { > * different maps if key/value layout matches across maps. > * Every bpf_timer_set_callback() can have different callback_fn. > * > + * *flags* can be one of: > + * > + * **BPF_F_TIMER_ABS** > + * Start the timer in absolute expire value instead of the > + * default relative one. > + * > * Return > * 0 on success. > * **-EINVAL** if *timer* was not initialized with bpf_timer_init() earlier > @@ -7050,4 +7056,13 @@ struct bpf_core_relo { > enum bpf_core_relo_kind kind; > }; > > +/* > + * Flags to control bpf_timer_start() behaviour. > + * - BPF_F_TIMER_ABS: Timeout passed is absolute time, by default it is > + * relative to current time. > + */ > +enum { > + BPF_F_TIMER_ABS = (1ULL << 0), > +}; > + > #endif /* _UAPI__LINUX_BPF_H__ */ > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c > index af30c6cbd65d..924849d89828 100644 > --- a/kernel/bpf/helpers.c > +++ b/kernel/bpf/helpers.c > @@ -1253,10 +1253,11 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, timer, u64, nsecs, u64, fla > { > struct bpf_hrtimer *t; > int ret = 0; > + enum hrtimer_mode mode; > > if (in_nmi()) > return -EOPNOTSUPP; > - if (flags) > + if (flags > BPF_F_TIMER_ABS) > return -EINVAL; > __bpf_spin_lock_irqsave(&timer->lock); > t = timer->timer; > @@ -1264,7 +1265,13 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, timer, u64, nsecs, u64, fla > ret = -EINVAL; > goto out; > } > - hrtimer_start(&t->timer, ns_to_ktime(nsecs), HRTIMER_MODE_REL_SOFT); > + > + if (flags & BPF_F_TIMER_ABS) > + mode = HRTIMER_MODE_ABS_SOFT; > + else > + mode = HRTIMER_MODE_REL_SOFT; > + > + hrtimer_start(&t->timer, ns_to_ktime(nsecs), mode); > out: > __bpf_spin_unlock_irqrestore(&timer->lock); > return ret;
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 464ca3f01fe7..7f5b71847984 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -4951,6 +4951,12 @@ union bpf_attr { * different maps if key/value layout matches across maps. * Every bpf_timer_set_callback() can have different callback_fn. * + * *flags* can be one of: + * + * **BPF_F_TIMER_ABS** + * Start the timer in absolute expire value instead of the + * default relative one. + * * Return * 0 on success. * **-EINVAL** if *timer* was not initialized with bpf_timer_init() earlier @@ -7050,4 +7056,13 @@ struct bpf_core_relo { enum bpf_core_relo_kind kind; }; +/* + * Flags to control bpf_timer_start() behaviour. + * - BPF_F_TIMER_ABS: Timeout passed is absolute time, by default it is + * relative to current time. + */ +enum { + BPF_F_TIMER_ABS = (1ULL << 0), +}; + #endif /* _UAPI__LINUX_BPF_H__ */ diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index af30c6cbd65d..924849d89828 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -1253,10 +1253,11 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, timer, u64, nsecs, u64, fla { struct bpf_hrtimer *t; int ret = 0; + enum hrtimer_mode mode; if (in_nmi()) return -EOPNOTSUPP; - if (flags) + if (flags > BPF_F_TIMER_ABS) return -EINVAL; __bpf_spin_lock_irqsave(&timer->lock); t = timer->timer; @@ -1264,7 +1265,13 @@ BPF_CALL_3(bpf_timer_start, struct bpf_timer_kern *, timer, u64, nsecs, u64, fla ret = -EINVAL; goto out; } - hrtimer_start(&t->timer, ns_to_ktime(nsecs), HRTIMER_MODE_REL_SOFT); + + if (flags & BPF_F_TIMER_ABS) + mode = HRTIMER_MODE_ABS_SOFT; + else + mode = HRTIMER_MODE_REL_SOFT; + + hrtimer_start(&t->timer, ns_to_ktime(nsecs), mode); out: __bpf_spin_unlock_irqrestore(&timer->lock); return ret;
Add a new flag BPF_F_TIMER_ABS that can be passed to bpf_timer_start() to start an absolute value timer instead of the default relative value. This makes the timer expire at an exact point in time, instead of a time with latencies and jitter induced by both the BPF and timer subsystems. This is useful e.g. in certain time sensitive profiling cases, where we need a timer to expire at an exact point in time. Signed-off-by: Tero Kristo <tero.kristo@linux.intel.com> --- include/uapi/linux/bpf.h | 15 +++++++++++++++ kernel/bpf/helpers.c | 11 +++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-)