summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-04-06 21:37:52 +0000
committerjhb <jhb@FreeBSD.org>2001-04-06 21:37:52 +0000
commitdd676bb0ec001a5bf3907ebe89abc84f49f55682 (patch)
tree9c703fba45f7cc201996d72e21aaebd1fe963823
parent8c75c79c0f603f0b3952705516f66213ff379b7c (diff)
downloadFreeBSD-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.c73
-rw-r--r--sys/sys/lock.h1
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);
OpenPOWER on IntegriCloud