Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 16 Jun 2013 09:30:35 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251803 - head/sys/kern
Message-ID:  <201306160930.r5G9UZfE059294@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Sun Jun 16 09:30:35 2013
New Revision: 251803
URL: http://svnweb.freebsd.org/changeset/base/251803

Log:
  Change callout use counter to use C11 atomics.
  
  In order to get some coverage of C11 atomics in kernelspace, switch at
  least one piece of code in kernelspace to use C11 atomics instead of
  <machine/atomic.h>.
  
  While there, slightly improve the code by adding an assertion to prevent
  the use count from going negative.

Modified:
  head/sys/kern/kern_event.c

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c	Sun Jun 16 07:18:07 2013	(r251802)
+++ head/sys/kern/kern_event.c	Sun Jun 16 09:30:35 2013	(r251803)
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/fcntl.h>
 #include <sys/kthread.h>
 #include <sys/selinfo.h>
+#include <sys/stdatomic.h>
 #include <sys/queue.h>
 #include <sys/event.h>
 #include <sys/eventvar.h>
@@ -182,9 +183,9 @@ static struct filterops user_filtops = {
 };
 
 static uma_zone_t	knote_zone;
-static int 		kq_ncallouts = 0;
-static int 		kq_calloutmax = (4 * 1024);
-SYSCTL_INT(_kern, OID_AUTO, kq_calloutmax, CTLFLAG_RW,
+static atomic_uint	kq_ncallouts = ATOMIC_VAR_INIT(0);
+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");
 
 /* XXX - ensure not KN_INFLUX?? */
@@ -549,13 +550,15 @@ static int
 filt_timerattach(struct knote *kn)
 {
 	struct callout *calloutp;
+	unsigned int ncallouts;
 
-	atomic_add_int(&kq_ncallouts, 1);
-
-	if (kq_ncallouts >= kq_calloutmax) {
-		atomic_add_int(&kq_ncallouts, -1);
-		return (ENOMEM);
-	}
+	ncallouts = atomic_load_explicit(&kq_ncallouts, memory_order_relaxed);
+	do {
+		if (ncallouts >= kq_calloutmax)
+			return (ENOMEM);
+	} while (!atomic_compare_exchange_weak_explicit(&kq_ncallouts,
+	    &ncallouts, ncallouts + 1, memory_order_relaxed,
+	    memory_order_relaxed));
 
 	kn->kn_flags |= EV_CLEAR;		/* automatically set */
 	kn->kn_status &= ~KN_DETACHED;		/* knlist_add usually sets it */
@@ -573,11 +576,13 @@ static void
 filt_timerdetach(struct knote *kn)
 {
 	struct callout *calloutp;
+	unsigned int old;
 
 	calloutp = (struct callout *)kn->kn_hook;
 	callout_drain(calloutp);
 	free(calloutp, M_KQUEUE);
-	atomic_add_int(&kq_ncallouts, -1);
+	old = atomic_fetch_sub_explicit(&kq_ncallouts, 1, memory_order_relaxed);
+	KASSERT(old > 0, ("Number of callouts cannot become negative"));
 	kn->kn_status |= KN_DETACHED;	/* knlist_remove usually clears it */
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306160930.r5G9UZfE059294>