aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2021-06-02 15:14:58 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2021-06-02 15:14:58 +0000
commitc9f8dcda856c50325190326a618dc251311bc43a (patch)
treed42bac58e46ca45e15eeacb975201bfa3cc03752
parenta19ae1b099ad4d43588f15ef19b8506f606b27cb (diff)
downloadsrc-c9f8dcda856c50325190326a618dc251311bc43a.tar.gz
src-c9f8dcda856c50325190326a618dc251311bc43a.zip
kqueue: replace kq_ncallouts loop with atomic_fetchadd
-rw-r--r--sys/kern/kern_event.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index b224ce87087e..63b28cd6024f 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -206,7 +206,7 @@ static struct filterops user_filtops = {
};
static uma_zone_t knote_zone;
-static unsigned int kq_ncallouts = 0;
+static unsigned int __exclusive_cache_line kq_ncallouts;
static unsigned int kq_calloutmax = 4 * 1024;
SYSCTL_UINT(_kern, OID_AUTO, kq_calloutmax, CTLFLAG_RW,
&kq_calloutmax, 0, "Maximum number of callouts allocated for kqueue");
@@ -813,18 +813,16 @@ filt_timerattach(struct knote *kn)
{
struct kq_timer_cb_data *kc;
sbintime_t to;
- unsigned int ncallouts;
int error;
error = filt_timervalidate(kn, &to);
if (error != 0)
return (error);
- do {
- ncallouts = kq_ncallouts;
- if (ncallouts >= kq_calloutmax)
- return (ENOMEM);
- } while (!atomic_cmpset_int(&kq_ncallouts, ncallouts, ncallouts + 1));
+ if (atomic_fetchadd_int(&kq_ncallouts, 1) + 1 > kq_calloutmax) {
+ atomic_subtract_int(&kq_ncallouts, 1);
+ return (ENOMEM);
+ }
if ((kn->kn_sfflags & NOTE_ABSTIME) == 0)
kn->kn_flags |= EV_CLEAR; /* automatically set */