Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Feb 2006 21:51:18 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 92144 for review
Message-ID:  <200602212151.k1LLpHPr078269@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=92144

Change 92144 by jhb@jhb_slimer on 2006/02/21 21:51:15

	Axe the callout_wait mutex and instead just use msleep_spin with
	the callout_lock spin lock directly.

Affected files ...

.. //depot/projects/smpng/sys/kern/kern_timeout.c#27 edit

Differences ...

==== //depot/projects/smpng/sys/kern/kern_timeout.c#27 (text+ko) ====

@@ -85,31 +85,18 @@
  *                     guarantees that the current callout will not run.
  *                     The softclock() function sets this to 0 before it
  *                     drops callout_lock to acquire c_mtx, and it calls
- *                     the handler only if curr_cancelled still 0 when
+ *                     the handler only if curr_cancelled is still 0 after
  *                     c_mtx is successfully acquired.
- *   wakeup_ctr      - Incremented every time a thread wants to wait
- *                     for a callout to complete.  Modified only when
+ *   wakeup_needed   - If a thread is waiting on callout_wait, then
+ *                     wakeup_needed is nonzero.  Set only when
  *                     curr_callout is non-NULL.
- *   wakeup_needed   - If a thread is waiting on callout_wait, then
- *                     wakeup_needed is nonzero.  Increased only when
- *                     cutt_callout is non-NULL.
+ *   callout_wait    - Placeholder for a wait channel.
  */
 static struct callout *curr_callout;
 static int curr_cancelled;
-static int wakeup_ctr;
 static int wakeup_needed;
+static int callout_wait;
 
-/**
- * Locked by callout_wait_lock:
- *   callout_wait    - If wakeup_needed is set, callout_wait will be
- *                     triggered after the current callout finishes.
- *   wakeup_done_ctr - Set to the current value of wakeup_ctr after
- *                     callout_wait is triggered.
- */
-static struct mtx callout_wait_lock;
-static struct cv callout_wait;
-static int wakeup_done_ctr;
-
 /*
  * kern_timeout_callwheel_alloc() - kernel low level callwheel initialization 
  *
@@ -157,8 +144,6 @@
 		TAILQ_INIT(&callwheel[i]);
 	}
 	mtx_init(&callout_lock, "callout", NULL, MTX_SPIN | MTX_RECURSE);
-	mtx_init(&callout_wait_lock, "callout_wait_lock", NULL, MTX_DEF);
-	cv_init(&callout_wait, "callout_wait");
 }
 
 /*
@@ -188,7 +173,6 @@
 	int mpcalls;
 	int mtxcalls;
 	int gcalls;
-	int wakeup_cookie;
 #ifdef DIAGNOSTIC
 	struct bintime bt1, bt2;
 	struct timespec ts2;
@@ -316,13 +300,7 @@
 					 * There might be someone waiting
 					 * for the callout to complete.
 					 */
-					wakeup_cookie = wakeup_ctr;
-					mtx_unlock_spin(&callout_lock);
-					mtx_lock(&callout_wait_lock);
-					cv_broadcast(&callout_wait);
-					wakeup_done_ctr = wakeup_cookie;
-					mtx_unlock(&callout_wait_lock);
-					mtx_lock_spin(&callout_lock);
+					wakeup(&callout_wait);
 					wakeup_needed = 0;
 				}
 				steps = 0;
@@ -497,7 +475,7 @@
 	struct	callout *c;
 	int	safe;
 {
-	int use_mtx, wakeup_cookie;
+	int rval, use_mtx;
 
 	if (!safe && c->c_mtx != NULL) {
 #ifdef notyet /* Some callers do not hold Giant for Giant-locked callouts. */
@@ -520,30 +498,21 @@
 			mtx_unlock_spin(&callout_lock);
 			return (0);
 		}
+		rval = 0;
 		if (safe) {
 			/* We need to wait until the callout is finished. */
-			wakeup_needed = 1;
-			wakeup_cookie = wakeup_ctr++;
-			mtx_unlock_spin(&callout_lock);
-			mtx_lock(&callout_wait_lock);
-
-			/*
-			 * Check to make sure that softclock() didn't
-			 * do the wakeup in between our dropping
-			 * callout_lock and picking up callout_wait_lock
-			 */
-			if (wakeup_cookie - wakeup_done_ctr > 0)
-				cv_wait(&callout_wait, &callout_wait_lock);
-
-			mtx_unlock(&callout_wait_lock);
+			while (c == curr_callout) {
+				wakeup_needed = 1;
+				msleep_spin(&callout_wait, &callout_lock,
+				    "costop", 0);
+			}
 		} else if (use_mtx && !curr_cancelled) {
 			/* We can stop the callout before it runs. */
 			curr_cancelled = 1;
-			mtx_unlock_spin(&callout_lock);
-			return (1);
-		} else
-			mtx_unlock_spin(&callout_lock);
-		return (0);
+			rval = 1;
+		}
+		mtx_unlock_spin(&callout_lock);
+		return (rval);
 	}
 	c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING);
 



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