git: c0e70e7b97dc - main - kern_event.c: support copy for timer events

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sat, 18 Oct 2025 05:14:15 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0e70e7b97dcfcbeedfdfbacf1543b756a616a18

commit c0e70e7b97dcfcbeedfdfbacf1543b756a616a18
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-08-20 19:06:05 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-10-18 05:12:36 +0000

    kern_event.c: support copy for timer events
    
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      2 weeks
    Differential revision:  https://reviews.freebsd.org/D52045
---
 sys/kern/kern_event.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 1f3030995ec6..4fd495fa1ec8 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -179,6 +179,7 @@ static void	filt_timerdetach(struct knote *kn);
 static void	filt_timerstart(struct knote *kn, sbintime_t to);
 static void	filt_timertouch(struct knote *kn, struct kevent *kev,
 		    u_long type);
+static int	filt_timercopy(struct knote *kn, struct proc *p1);
 static int	filt_timervalidate(struct knote *kn, sbintime_t *to);
 static int	filt_timer(struct knote *kn, long hint);
 static int	filt_userattach(struct knote *kn);
@@ -215,6 +216,7 @@ static const struct filterops timer_filtops = {
 	.f_detach = filt_timerdetach,
 	.f_event = filt_timer,
 	.f_touch = filt_timertouch,
+	.f_copy =  filt_timercopy,
 };
 static const struct filterops user_filtops = {
 	.f_attach = filt_userattach,
@@ -943,6 +945,30 @@ filt_timerattach(struct knote *kn)
 	return (0);
 }
 
+static int
+filt_timercopy(struct knote *kn, struct proc *p)
+{
+	struct kq_timer_cb_data *kc_src, *kc;
+
+	if (atomic_fetchadd_int(&kq_ncallouts, 1) + 1 > kq_calloutmax) {
+		atomic_subtract_int(&kq_ncallouts, 1);
+		return (ENOMEM);
+	}
+
+	kn->kn_status &= ~KN_DETACHED;
+	kc_src = kn->kn_ptr.p_v;
+	kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK);
+	kc->kn = kn;
+	kc->p = p;
+	kc->flags = kc_src->flags & ~KQ_TIMER_CB_ENQUEUED;
+	kc->next = kc_src->next;
+	kc->to = kc_src->to;
+	kc->cpuid = PCPU_GET(cpuid);
+	callout_init(&kc->c, 1);
+	kqtimer_sched_callout(kc);
+	return (0);
+}
+
 static void
 filt_timerstart(struct knote *kn, sbintime_t to)
 {