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