aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2025-08-20 19:06:05 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2025-10-18 05:12:36 +0000
commitc0e70e7b97dcfcbeedfdfbacf1543b756a616a18 (patch)
tree999118d4a196d1996ae769ee65492b2b358a457a
parentb11289f87123f8ae06fc70bc70d26a25d4356a65 (diff)
-rw-r--r--sys/kern/kern_event.c26
1 files changed, 26 insertions, 0 deletions
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)
{