From owner-svn-src-all@FreeBSD.ORG Wed Jan 21 04:19:18 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 6FFFB10656E1; Wed, 21 Jan 2009 04:19:18 +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 5DAAC8FC23; Wed, 21 Jan 2009 04:19:18 +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 n0L4JIRS066136; Wed, 21 Jan 2009 04:19:18 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0L4JIG7066134; Wed, 21 Jan 2009 04:19:18 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <200901210419.n0L4JIG7066134@svn.freebsd.org> From: Andrew Thompson Date: Wed, 21 Jan 2009 04:19:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187511 - in head/sys: kern sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 21 Jan 2009 04:19:19 -0000 Author: thompsa Date: Wed Jan 21 04:19:18 2009 New Revision: 187511 URL: http://svn.freebsd.org/changeset/base/187511 Log: Add functions WITNESS so it can be asserted that the lock is not released for a section of code, this uses WITNESS_NORELEASE() and WITNESS_RELEASEOK() to mark the boundaries. Both functions require the lock to be held when calling. This is intended for scenarios like a bus asserting that the bus lock is not dropped during a driver call. There doesn't appear to be a man page to document this in. Reviewed by: jhb Modified: head/sys/kern/subr_witness.c head/sys/sys/lock.h Modified: head/sys/kern/subr_witness.c ============================================================================== --- head/sys/kern/subr_witness.c Wed Jan 21 02:53:00 2009 (r187510) +++ head/sys/kern/subr_witness.c Wed Jan 21 04:19:18 2009 (r187511) @@ -127,6 +127,7 @@ __FBSDID("$FreeBSD$"); #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. */ /* Define this to check for blessed mutexes */ #undef BLESSING @@ -367,6 +368,7 @@ static struct witness_lock_order_data *w struct witness *parent, struct witness *child); static void witness_list_lock(struct lock_instance *instance); +static void witness_setflag(struct lock_object *lock, int flag, int set); #ifdef KDB #define witness_debugger(c) _witness_debugger(c, __func__) @@ -1509,6 +1511,11 @@ 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); + panic("lock marked norelease"); + } /* If we are recursed, unrecurse. */ if ((instance->li_flags & LI_RECURSEMASK) > 0) { @@ -2224,6 +2231,48 @@ witness_assert(struct lock_object *lock, #endif /* INVARIANT_SUPPORT */ } +static 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; +} + +void +witness_norelease(struct lock_object *lock) +{ + + witness_setflag(lock, LI_NORELEASE, 1); +} + +void +witness_releaseok(struct lock_object *lock) +{ + + witness_setflag(lock, LI_NORELEASE, 0); +} + #ifdef DDB static void witness_ddb_list(struct thread *td) Modified: head/sys/sys/lock.h ============================================================================== --- head/sys/sys/lock.h Wed Jan 21 02:53:00 2009 (r187510) +++ head/sys/sys/lock.h Wed Jan 21 04:19:18 2009 (r187511) @@ -216,6 +216,8 @@ 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_norelease(struct lock_object *); +void witness_releaseok(struct lock_object *); const char *witness_file(struct lock_object *); void witness_thread_exit(struct thread *); @@ -267,6 +269,12 @@ void witness_thread_exit(struct thread * #define WITNESS_RESTORE(lock, n) \ witness_restore((lock), __CONCAT(n, __wf), __CONCAT(n, __wl)) +#define WITNESS_NORELEASE(lock) \ + witness_norelease(&(lock)->lock_object) + +#define WITNESS_RELEASEOK(lock) \ + witness_releaseok(&(lock)->lock_object) + #define WITNESS_FILE(lock) \ witness_file(lock) @@ -287,6 +295,8 @@ void witness_thread_exit(struct thread * #define WITNESS_SAVE_DECL(n) #define WITNESS_SAVE(lock, n) #define WITNESS_RESTORE(lock, n) +#define WITNESS_NORELEASE(lock) +#define WITNESS_RELEASEOK(lock) #define WITNESS_FILE(lock) ("?") #define WITNESS_LINE(lock) (0) #endif /* WITNESS */