diff options
author | jhb <jhb@FreeBSD.org> | 2001-04-06 21:37:52 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-04-06 21:37:52 +0000 |
commit | dd676bb0ec001a5bf3907ebe89abc84f49f55682 (patch) | |
tree | 9c703fba45f7cc201996d72e21aaebd1fe963823 | |
parent | 8c75c79c0f603f0b3952705516f66213ff379b7c (diff) | |
download | FreeBSD-src-dd676bb0ec001a5bf3907ebe89abc84f49f55682.zip FreeBSD-src-dd676bb0ec001a5bf3907ebe89abc84f49f55682.tar.gz |
- Split out the functionality of displaying the contents of a single lock
list into a public witness_list_locks() function. Call this function
twice in witness_list() instead of using an evil goto.
- Adjust the 'show locks' command to take an optional parameter which
specifies the pid of a process to list the locks of. By default the
locks held by the current process are displayed.
-rw-r--r-- | sys/kern/subr_witness.c | 73 | ||||
-rw-r--r-- | sys/sys/lock.h | 1 |
2 files changed, 53 insertions, 21 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index 846ac7e..87119a4 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -1081,27 +1081,14 @@ witness_lock_list_free(struct lock_list_entry *lle) mtx_unlock_spin(&w_mtx); } -/* - * Calling this on p != curproc is bad unless we are in ddb. - */ int -witness_list(struct proc *p) +witness_list_locks(struct lock_list_entry **lock_list) { - struct lock_list_entry **lock_list, *lle; + struct lock_list_entry *lle; struct lock_object *lock; - critical_t savecrit; int i, nheld; - KASSERT(p == curproc || db_active, - ("%s: p != curproc and we aren't in the debugger", __func__)); - KASSERT(!witness_cold, ("%s: witness_cold", __func__)); nheld = 0; - /* - * Preemption bad because we need PCPU_PTR(spinlocks) to not change. - */ - savecrit = critical_enter(); - lock_list = &p->p_sleeplocks; -again: for (lle = *lock_list; lle != NULL; lle = lle->ll_next) for (i = lle->ll_count - 1; i >= 0; i--) { lock = lle->ll_children[i]; @@ -1110,16 +1097,40 @@ again: lock->lo_file, lock->lo_line); nheld++; } + return (nheld); +} + +/* + * Calling this on p != curproc is bad unless we are in ddb. + */ +int +witness_list(struct proc *p) +{ + critical_t savecrit; + int nheld; + + KASSERT(p == curproc || db_active, + ("%s: p != curproc and we aren't in the debugger", __func__)); + KASSERT(!witness_cold, ("%s: witness_cold", __func__)); + + nheld = witness_list_locks(&p->p_sleeplocks); + /* * We only handle spinlocks if p == curproc. This is somewhat broken * if p is currently executing on some other CPU and holds spin locks - * as we won't display those locks. + * as we won't display those locks. If we had a MI way of getting + * the per-cpu data for a given cpu then we could use p->p_oncpu to + * get the list of spinlocks for this process and "fix" this. */ - if (lock_list == &p->p_sleeplocks && p == curproc) { - lock_list = PCPU_PTR(spinlocks); - goto again; + if (p == curproc) { + /* + * Preemption bad because we need PCPU_PTR(spinlocks) to not + * change. + */ + savecrit = critical_enter(); + nheld += witness_list_locks(PCPU_PTR(spinlocks)); + critical_exit(savecrit); } - critical_exit(savecrit); return (nheld); } @@ -1154,8 +1165,28 @@ witness_restore(struct lock_object *lock, const char *file, int line) DB_SHOW_COMMAND(locks, db_witness_list) { + struct proc *p; + pid_t pid; + + if (have_addr) { + pid = (addr % 16) + ((addr >> 4) % 16) * 10 + + ((addr >> 8) % 16) * 100 + ((addr >> 12) % 16) * 1000 + + ((addr >> 16) % 16) * 10000; - witness_list(curproc); + /* sx_slock(&allproc_lock); */ + LIST_FOREACH(p, &allproc, p_list) { + if (p->p_pid == pid) + break; + } + /* sx_sunlock(&allproc_lock); */ + if (p == NULL) { + db_printf("pid %d not found\n", pid); + return; + } + } else + p = curproc; + + witness_list(p); } DB_SHOW_COMMAND(witness, db_witness_display) diff --git a/sys/sys/lock.h b/sys/sys/lock.h index ed9cac6..ca3404b 100644 --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -164,6 +164,7 @@ void witness_lock(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(struct proc *); int witness_sleep(int, struct lock_object *, const char *, int); |