svn commit: r186400 - in user/thompsa/vaptq/sys: kern net80211 sys

Andrew Thompson thompsa at FreeBSD.org
Mon Dec 22 12:38:00 PST 2008


Author: thompsa
Date: Mon Dec 22 20:38:00 2008
New Revision: 186400
URL: http://svn.freebsd.org/changeset/base/186400

Log:
  Add a local hack to WITNESS so it can be asserted that the lock is not released
  for a section of code, this uses WITNESS_NOREL() and WITNESS_RELOK() to mark
  the boundaries.
  
  This allows net80211 to assert that the com lock isnt dropped over driver calls.

Modified:
  user/thompsa/vaptq/sys/kern/subr_witness.c
  user/thompsa/vaptq/sys/net80211/ieee80211_proto.c
  user/thompsa/vaptq/sys/sys/lock.h

Modified: user/thompsa/vaptq/sys/kern/subr_witness.c
==============================================================================
--- user/thompsa/vaptq/sys/kern/subr_witness.c	Mon Dec 22 20:31:35 2008	(r186399)
+++ user/thompsa/vaptq/sys/kern/subr_witness.c	Mon Dec 22 20:38:00 2008	(r186400)
@@ -125,9 +125,6 @@ __FBSDID("$FreeBSD$");
 #define	KTR_WITNESS	0
 #endif
 
-#define	LI_RECURSEMASK	0x0000ffff	/* Recursion depth of lock instance. */
-#define	LI_EXCLUSIVE	0x00010000	/* Exclusive lock instance. */
-
 /* Define this to check for blessed mutexes */
 #undef BLESSING
 
@@ -1509,6 +1506,13 @@ found:
 		    instance->li_line);
 		panic("share->uexcl");
 	}
+	if ((instance->li_flags & LI_NORELEASE) != 0 && witness_watch > 0) {
+		printf("forbidden unlock of (%s) %s @ %s:%d\n", class->lc_name,
+		    lock->lo_name, file, line);
+		/* XXX notyet
+		panic("lock not allowed to be released");
+		*/
+	}
 
 	/* If we are recursed, unrecurse. */
 	if ((instance->li_flags & LI_RECURSEMASK) > 0) {
@@ -2224,6 +2228,34 @@ witness_assert(struct lock_object *lock,
 #endif	/* INVARIANT_SUPPORT */
 }
 
+void
+witness_setflag(struct lock_object *lock, int flag, int set)
+{
+	struct lock_list_entry *lock_list;
+	struct lock_instance *instance;
+	struct lock_class *class;
+
+	if (lock->lo_witness == NULL || witness_watch == -1 || panicstr != NULL)
+		return;
+	class = LOCK_CLASS(lock);
+	if (class->lc_flags & LC_SLEEPLOCK)
+		lock_list = curthread->td_sleeplocks;
+	else {
+		if (witness_skipspin)
+			return;
+		lock_list = PCPU_GET(spinlocks);
+	}
+	instance = find_instance(lock_list, lock);
+	if (instance == NULL)
+		panic("%s: lock (%s) %s not locked", __func__,
+		    class->lc_name, lock->lo_name);
+
+	if (set)
+		instance->li_flags |= flag;
+	else
+		instance->li_flags &= ~flag;
+}
+
 #ifdef DDB
 static void
 witness_ddb_list(struct thread *td)

Modified: user/thompsa/vaptq/sys/net80211/ieee80211_proto.c
==============================================================================
--- user/thompsa/vaptq/sys/net80211/ieee80211_proto.c	Mon Dec 22 20:31:35 2008	(r186399)
+++ user/thompsa/vaptq/sys/net80211/ieee80211_proto.c	Mon Dec 22 20:38:00 2008	(r186400)
@@ -98,6 +98,8 @@ const char *ieee80211_wme_acnames[] = {
 
 static void parent_updown(void *, int);
 static void ieee80211_newstate_cb(void *, int);
+static int ieee80211_newstate_cb_locked(struct ieee80211vap *,
+	enum ieee80211_state, int);
 static int ieee80211_new_state_locked(struct ieee80211vap *,
 	enum ieee80211_state, int);
 
@@ -1536,27 +1538,39 @@ ieee80211_newstate_cb(void *xvap, int np
 {
 	struct ieee80211vap *vap = xvap;
 	struct ieee80211com *ic = vap->iv_ic;
-	enum ieee80211_state ostate = vap->iv_state;
 	enum ieee80211_state nstate = vap->iv_nstate;
 	int arg = vap->iv_nstate_arg;
+
+	IEEE80211_LOCK(ic);
+	ieee80211_newstate_cb_locked(vap, nstate, arg);
+	IEEE80211_UNLOCK(ic);
+}
+
+static int
+ieee80211_newstate_cb_locked(struct ieee80211vap *vap,
+	enum ieee80211_state nstate, int arg)
+{
+	struct ieee80211com *ic = vap->iv_ic;
+	enum ieee80211_state ostate = vap->iv_state;
 	int rc;
 
+	IEEE80211_LOCK_ASSERT(ic);
+
 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
 	    "%s: %s arg %d\n", __func__, ieee80211_state_name[nstate], arg);
 
-	IEEE80211_LOCK(ic);
 	rc = vap->iv_newstate(vap, nstate, arg);
 	if (rc != 0 || vap->iv_state != nstate) {
 		if (rc == EINPROGRESS)
 			if_printf(ic->ic_ifp,
 			    "Warning, iv_newstate was deferred again\n");
 		/* State transition failed */
-		goto out;
+		return (rc);
 	}
 
 	/* No actual transition, skip post processing */
 	if (ostate == nstate)
-		goto out;
+		return (0);
 
 	if (nstate == IEEE80211_S_RUN) {
 		/*
@@ -1584,8 +1598,7 @@ ieee80211_newstate_cb(void *xvap, int np
 		/* XXX NB: cast for altq */
 		ieee80211_flush_ifq((struct ifqueue *)&ic->ic_ifp->if_snd, vap);
 	}
-out:
-	IEEE80211_UNLOCK(ic);
+	return (0);
 }
 
 /*
@@ -1623,6 +1636,7 @@ ieee80211_new_state_locked(struct ieee80
 	struct ieee80211vap *vp;
 	enum ieee80211_state ostate;
 	int nrunning, nscanning, rc;
+	int forcesync = 0;
 
 	IEEE80211_LOCK_ASSERT(ic);
 
@@ -1738,15 +1752,26 @@ ieee80211_new_state_locked(struct ieee80
 			/* INIT -> INIT. nothing to do */
 			vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANWAIT;
 		}
+		forcesync = 1;
 		/* fall thru... */
 	default:
 		break;
 	}
-	/* The state change call to the driver runs in a thread */
-	vap->iv_nstate = nstate;
-	vap->iv_nstate_arg = arg;
-	taskqueue_enqueue(ic->ic_tq, &vap->iv_nstate_task);
-	return (EINPROGRESS);
+	if (forcesync) {
+		/*
+		 * Complete the state transition synchronously, asserting that
+		 * the lock is not dropped.
+		 */
+		WITNESS_NOREL(IEEE80211_LOCK_OBJ(ic));
+		rc = ieee80211_newstate_cb_locked(vap, nstate, arg);
+		WITNESS_RELOK(IEEE80211_LOCK_OBJ(ic));
+	} else {
+		/* defer the state change to a thread */
+		vap->iv_nstate = nstate;
+		vap->iv_nstate_arg = arg;
+		taskqueue_enqueue(ic->ic_tq, &vap->iv_nstate_task);
+		return (EINPROGRESS);
+	}
 done:
 	return rc;
 }

Modified: user/thompsa/vaptq/sys/sys/lock.h
==============================================================================
--- user/thompsa/vaptq/sys/sys/lock.h	Mon Dec 22 20:31:35 2008	(r186399)
+++ user/thompsa/vaptq/sys/sys/lock.h	Mon Dec 22 20:38:00 2008	(r186400)
@@ -110,6 +110,11 @@ struct lock_class {
 #define	LA_RECURSED	0x00000008	/* Lock is recursed. */
 #define	LA_NOTRECURSED	0x00000010	/* Lock is not recursed. */
 
+/* WITNESS lock instance flags */
+#define	LI_RECURSEMASK	0x0000ffff	/* Recursion depth of lock instance. */
+#define	LI_EXCLUSIVE	0x00010000	/* Exclusive lock instance. */
+#define	LI_NORELEASE	0x00020000	/* Lock not allowed to be released. */
+
 #ifdef _KERNEL
 /*
  * If any of WITNESS, INVARIANTS, or KTR_LOCK KTR tracing has been enabled,
@@ -216,6 +221,7 @@ int	witness_warn(int, struct lock_object
 void	witness_assert(struct lock_object *, int, const char *, int);
 void	witness_display_spinlock(struct lock_object *, struct thread *);
 int	witness_line(struct lock_object *);
+void	witness_setflag(struct lock_object *, int, int);
 const char *witness_file(struct lock_object *);
 void	witness_thread_exit(struct thread *);
 
@@ -267,6 +273,12 @@ void	witness_thread_exit(struct thread *
 #define	WITNESS_RESTORE(lock, n) 					\
 	witness_restore((lock), __CONCAT(n, __wf), __CONCAT(n, __wl))
 
+#define	WITNESS_NOREL(lock)						\
+	witness_setflag(&(lock)->lock_object, LI_NORELEASE, 1)
+
+#define	WITNESS_RELOK(lock)						\
+	witness_setflag(&(lock)->lock_object, LI_NORELEASE, 0)
+
 #define	WITNESS_FILE(lock) 						\
 	witness_file(lock)
 
@@ -287,6 +299,8 @@ void	witness_thread_exit(struct thread *
 #define	WITNESS_SAVE_DECL(n)
 #define	WITNESS_SAVE(lock, n)
 #define	WITNESS_RESTORE(lock, n)
+#define	WITNESS_NOREL(lock)
+#define	WITNESS_RELOK(lock)
 #define	WITNESS_FILE(lock) ("?")
 #define	WITNESS_LINE(lock) (0)
 #endif	/* WITNESS */


More information about the svn-src-user mailing list