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
This commit is contained in:
parent
227901e1a2
commit
98332c8c71
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=207929
@ -485,7 +485,7 @@ _mtx_lock_spin_failed(struct mtx *m)
|
||||
printf( "spin lock %p (%s) held by %p (tid %d) too long\n",
|
||||
m, m->lock_object.lo_name, td, td->td_tid);
|
||||
#ifdef WITNESS
|
||||
witness_display_spinlock(&m->lock_object, td);
|
||||
witness_display_spinlock(&m->lock_object, td, printf);
|
||||
#endif
|
||||
panic("spin lock held too long");
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ show_pcpu(struct pcpu *pc)
|
||||
|
||||
#ifdef WITNESS
|
||||
db_printf("spin locks held:\n");
|
||||
witness_list_locks(&pc->pc_spinlocks);
|
||||
witness_list_locks(&pc->pc_spinlocks, db_printf);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -212,10 +212,12 @@ void witness_downgrade(struct lock_object *, int, const char *, int);
|
||||
void witness_unlock(struct lock_object *, int, const char *, int);
|
||||
void witness_save(struct lock_object *, const char **, int *);
|
||||
void witness_restore(struct lock_object *, const char *, int);
|
||||
int witness_list_locks(struct lock_list_entry **);
|
||||
int witness_list_locks(struct lock_list_entry **,
|
||||
int (*)(const char *, ...));
|
||||
int witness_warn(int, struct lock_object *, const char *, ...);
|
||||
void witness_assert(struct lock_object *, int, const char *, int);
|
||||
void witness_display_spinlock(struct lock_object *, struct thread *);
|
||||
void witness_display_spinlock(struct lock_object *, struct thread *,
|
||||
int (*)(const char *, ...));
|
||||
int witness_line(struct lock_object *);
|
||||
void witness_norelease(struct lock_object *);
|
||||
void witness_releaseok(struct lock_object *);
|
||||
|
Loading…
Reference in New Issue
Block a user