Add simple_lock_assert_locked/simple_lock_assert_unlocked to provide additional

useful information when panic'ing because the assertion fails.
Use these to define the SCHED_ASSERT_LOCKED/SCHED_ASSERT_UNLOCKED macros.
This commit is contained in:
erh 2006-03-26 20:19:52 +00:00
parent 625f1bbe61
commit e4412d2162
3 changed files with 69 additions and 13 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_lock.c,v 1.93 2006/03/16 00:52:32 erh Exp $ */
/* $NetBSD: kern_lock.c,v 1.94 2006/03/26 20:19:52 erh Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.93 2006/03/16 00:52:32 erh Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.94 2006/03/26 20:19:52 erh Exp $");
#include "opt_multiprocessor.h"
#include "opt_lockdebug.h"
@ -1367,6 +1367,45 @@ simple_lock_only_held(volatile struct simplelock *lp, const char *where)
SLOCK_DEBUGGER();
}
}
/*
* Set to 1 by simple_lock_assert_*().
* Can be cleared from ddb to avoid a panic.
*/
int slock_assert_will_panic;
/*
* If the lock isn't held, print a traceback, optionally drop into the
* debugger, then panic.
* The panic can be avoided by clearing slock_assert_with_panic from the
* debugger.
*/
void
_simple_lock_assert_locked(volatile struct simplelock *alp,
const char *lockname, const char *id, int l)
{
if (simple_lock_held(alp) == 0) {
slock_assert_will_panic = 1;
lock_printf("%s lock not held\n", lockname);
SLOCK_WHERE("lock not held", alp, id, l);
if (slock_assert_will_panic)
panic("%s: not locked", lockname);
}
}
void
_simple_lock_assert_unlocked(volatile struct simplelock *alp,
const char *lockname, const char *id, int l)
{
if (simple_lock_held(alp)) {
slock_assert_will_panic = 1;
lock_printf("%s lock held\n", lockname);
SLOCK_WHERE("lock held", alp, id, l);
if (slock_assert_will_panic)
panic("%s: locked", lockname);
}
}
#endif /* LOCKDEBUG */ /* } */
#if defined(MULTIPROCESSOR)
@ -1495,8 +1534,8 @@ _kernel_lock_acquire_count(int hold_count)
void
_kernel_lock_assert_locked()
{
LOCK_ASSERT(simple_lock_held(&kernel_lock));
_simple_lock_assert_locked(&kernel_lock, "kernel_lock");
}
#endif
#endif /* MULTIPROCESSOR */

View File

@ -1,4 +1,4 @@
/* $NetBSD: lock.h,v 1.63 2006/01/02 21:53:30 uwe Exp $ */
/* $NetBSD: lock.h,v 1.64 2006/03/26 20:19:52 erh Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
@ -327,22 +327,32 @@ void _spinlock_acquire_count(volatile struct lock *, int, const char *,
#define spinlock_release_all(l) _spinlock_release_all((l), __FILE__, __LINE__)
#define spinlock_acquire_count(l, c) _spinlock_acquire_count((l), (c), \
__FILE__, __LINE__)
#else
int spinlock_release_all(volatile struct lock *);
void spinlock_acquire_count(volatile struct lock *, int);
#endif
#if defined(LOCKDEBUG)
void _simple_lock(volatile struct simplelock *, const char *, int);
int _simple_lock_try(volatile struct simplelock *, const char *, int);
void _simple_unlock(volatile struct simplelock *, const char *, int);
int _simple_lock_held(volatile struct simplelock *);
void simple_lock_only_held(volatile struct simplelock *, const char *);
void _simple_lock_assert_locked(volatile struct simplelock *, const char *,
const char *, int l);
void _simple_lock_assert_unlocked(volatile struct simplelock *, const char *,
const char *, int l);
#define simple_lock(alp) _simple_lock((alp), __FILE__, __LINE__)
#define simple_lock_try(alp) _simple_lock_try((alp), __FILE__, __LINE__)
#define simple_unlock(alp) _simple_unlock((alp), __FILE__, __LINE__)
#define simple_lock_held(alp) _simple_lock_held((alp))
#define simple_lock_assert_locked(alp,lockname) \
_simple_lock_assert_locked((alp),(lockname), __FILE__, __LINE__)
#define simple_lock_assert_unlocked(alp,lockname) \
_simple_lock_assert_unlocked((alp),(lockname), __FILE__, __LINE__)
#define LOCK_ASSERT(x) KASSERT(x)
@ -357,17 +367,23 @@ void simple_lock_switchcheck(void);
#define simple_unlock(alp) __cpu_simple_unlock(&(alp)->lock_data)
#define LOCK_ASSERT(x) /* nothing */
#define simple_lock_only_held(x,y) /* nothing */
#define simple_lock_assert_locked(alp,lockname) /* nothing */
#define simple_lock_assert_unlocked(alp,lockname) /* nothing */
#else
#define simple_lock_try(alp) (1)
#ifndef __lint__
#define simple_lock_init(alp) (void)(alp)
#define simple_lock(alp) (void)(alp)
#define simple_unlock(alp) (void)(alp)
#define simple_lock_assert_locked(alp,lockname) (void)(alp)
#define simple_lock_assert_unlocked(alp,lockname) (void)(alp)
#else /* __lint__ */
#define simple_lock_init(alp) /* nothing */
#define simple_lock(alp) /* nothing */
#define simple_unlock(alp) /* nothing */
#define simple_lock_only_held(x,y) /* nothing */
#define simple_lock_assert_locked(alp,lockname) /* nothing */
#define simple_lock_assert_unlocked(alp,lockname) /* nothing */
#endif /* __lint__ */
#define LOCK_ASSERT(x) /* nothing */
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: sched.h,v 1.26 2005/12/26 18:41:36 perry Exp $ */
/* $NetBSD: sched.h,v 1.27 2006/03/26 20:19:52 erh Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc.
@ -201,8 +201,9 @@ void scheduler_wait_hook(struct proc *, struct proc *);
extern struct simplelock sched_lock;
#define SCHED_ASSERT_LOCKED() LOCK_ASSERT(simple_lock_held(&sched_lock))
#define SCHED_ASSERT_UNLOCKED() LOCK_ASSERT(simple_lock_held(&sched_lock) == 0)
#define SCHED_ASSERT_LOCKED() simple_lock_assert_locked(&sched_lock, "sched_lock")
#define SCHED_ASSERT_UNLOCKED() simple_lock_assert_unlocked(&sched_lock, "sched_lock")
#define SCHED_LOCK(s) \
do { \