From owner-svn-src-user@FreeBSD.ORG Mon Dec 22 20:38:00 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C7516106564A; Mon, 22 Dec 2008 20:38:00 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B494B8FC21; Mon, 22 Dec 2008 20:38:00 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mBMKc0Ex070430; Mon, 22 Dec 2008 20:38:00 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mBMKc0EK070427; Mon, 22 Dec 2008 20:38:00 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200812222038.mBMKc0EK070427@svn.freebsd.org> From: Andrew Thompson Date: Mon, 22 Dec 2008 20:38:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186400 - in user/thompsa/vaptq/sys: kern net80211 sys X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 22 Dec 2008 20:38:00 -0000 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 */