summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_witness.c
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2010-05-11 18:24:22 +0000
committerattilio <attilio@FreeBSD.org>2010-05-11 18:24:22 +0000
commit4d95c325ddc0a2cee03abd4ff6cf7eaf0e75e888 (patch)
tree1ff93cd2b53115def1f3b62d662c860d7c6138af /sys/kern/subr_witness.c
parentfd4782d957bea021cedbc136b2a46eeec97e379d (diff)
downloadFreeBSD-src-4d95c325ddc0a2cee03abd4ff6cf7eaf0e75e888.zip
FreeBSD-src-4d95c325ddc0a2cee03abd4ff6cf7eaf0e75e888.tar.gz
Right now, WITNESS just blindly pipes all the output to the
(TOCONS | TOLOG) mask even when called from DDB points. That breaks several output, where the most notable is textdump output. Fix this by having configurable callbacks passed to witness_list_locks() and witness_display_spinlock() for printing out datas. Reported by: several broken textdump outputs Tested by: Giovanni Trematerra <giovanni dot trematerra at gmail dot com> MFC after: 7 days X-MFC: r207922
Diffstat (limited to 'sys/kern/subr_witness.c')
-rw-r--r--sys/kern/subr_witness.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 02e2da4..30e971b 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -367,7 +367,8 @@ static int witness_lock_order_check(struct witness *parent,
static struct witness_lock_order_data *witness_lock_order_get(
struct witness *parent,
struct witness *child);
-static void witness_list_lock(struct lock_instance *instance);
+static void witness_list_lock(struct lock_instance *instance,
+ int (*prnt)(const char *fmt, ...));
static void witness_setflag(struct lock_object *lock, int flag, int set);
#ifdef KDB
@@ -1597,7 +1598,7 @@ witness_thread_exit(struct thread *td)
printf("Thread %p exiting with the following locks held:\n",
td);
n++;
- witness_list_lock(&lle->ll_children[i]);
+ witness_list_lock(&lle->ll_children[i], printf);
}
panic("Thread %p cannot exit while holding sleeplocks\n", td);
@@ -1646,7 +1647,7 @@ witness_warn(int flags, struct lock_object *lock, const char *fmt, ...)
printf(" locks held:\n");
}
n++;
- witness_list_lock(lock1);
+ witness_list_lock(lock1, printf);
}
/*
@@ -1677,7 +1678,7 @@ witness_warn(int flags, struct lock_object *lock, const char *fmt, ...)
if (flags & WARN_SLEEPOK)
printf(" non-sleepable");
printf(" locks held:\n");
- n += witness_list_locks(&lock_list);
+ n += witness_list_locks(&lock_list, printf);
} else
sched_unpin();
if (flags & WARN_PANIC && n)
@@ -2063,16 +2064,17 @@ find_instance(struct lock_list_entry *list, struct lock_object *lock)
}
static void
-witness_list_lock(struct lock_instance *instance)
+witness_list_lock(struct lock_instance *instance,
+ int (*prnt)(const char *fmt, ...))
{
struct lock_object *lock;
lock = instance->li_lock;
- printf("%s %s %s", (instance->li_flags & LI_EXCLUSIVE) != 0 ?
+ prnt("%s %s %s", (instance->li_flags & LI_EXCLUSIVE) != 0 ?
"exclusive" : "shared", LOCK_CLASS(lock)->lc_name, lock->lo_name);
if (lock->lo_witness->w_name != lock->lo_name)
- printf(" (%s)", lock->lo_witness->w_name);
- printf(" r = %d (%p) locked @ %s:%d\n",
+ prnt(" (%s)", lock->lo_witness->w_name);
+ prnt(" r = %d (%p) locked @ %s:%d\n",
instance->li_flags & LI_RECURSEMASK, lock, instance->li_file,
instance->li_line);
}
@@ -2101,7 +2103,8 @@ witness_proc_has_locks(struct proc *p)
#endif
int
-witness_list_locks(struct lock_list_entry **lock_list)
+witness_list_locks(struct lock_list_entry **lock_list,
+ int (*prnt)(const char *fmt, ...))
{
struct lock_list_entry *lle;
int i, nheld;
@@ -2109,7 +2112,7 @@ witness_list_locks(struct lock_list_entry **lock_list)
nheld = 0;
for (lle = *lock_list; lle != NULL; lle = lle->ll_next)
for (i = lle->ll_count - 1; i >= 0; i--) {
- witness_list_lock(&lle->ll_children[i]);
+ witness_list_lock(&lle->ll_children[i], prnt);
nheld++;
}
return (nheld);
@@ -2123,7 +2126,8 @@ witness_list_locks(struct lock_list_entry **lock_list)
* see when it was last acquired.
*/
void
-witness_display_spinlock(struct lock_object *lock, struct thread *owner)
+witness_display_spinlock(struct lock_object *lock, struct thread *owner,
+ int (*prnt)(const char *fmt, ...))
{
struct lock_instance *instance;
struct pcpu *pc;
@@ -2133,7 +2137,7 @@ witness_display_spinlock(struct lock_object *lock, struct thread *owner)
pc = pcpu_find(owner->td_oncpu);
instance = find_instance(pc->pc_spinlocks, lock);
if (instance != NULL)
- witness_list_lock(instance);
+ witness_list_lock(instance, prnt);
}
void
@@ -2306,7 +2310,7 @@ witness_ddb_list(struct thread *td)
if (witness_watch < 1)
return;
- witness_list_locks(&td->td_sleeplocks);
+ witness_list_locks(&td->td_sleeplocks, db_printf);
/*
* We only handle spinlocks if td == curthread. This is somewhat broken
@@ -2322,7 +2326,7 @@ witness_ddb_list(struct thread *td)
* handle threads on other CPU's for now.
*/
if (td == curthread && PCPU_GET(spinlocks) != NULL)
- witness_list_locks(PCPU_PTR(spinlocks));
+ witness_list_locks(PCPU_PTR(spinlocks), db_printf);
}
DB_SHOW_COMMAND(locks, db_witness_list)
OpenPOWER on IntegriCloud