From owner-p4-projects Mon Nov 11 11:33: 7 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 8DA2C37B404; Mon, 11 Nov 2002 11:33:00 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3C12737B401 for ; Mon, 11 Nov 2002 11:33:00 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id CEA0443E6E for ; Mon, 11 Nov 2002 11:32:59 -0800 (PST) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id gABJUgmV085590 for ; Mon, 11 Nov 2002 11:30:42 -0800 (PST) (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id gABJUfUF085587 for perforce@freebsd.org; Mon, 11 Nov 2002 11:30:41 -0800 (PST) Date: Mon, 11 Nov 2002 11:30:41 -0800 (PST) Message-Id: <200211111930.gABJUfUF085587@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin Subject: PERFORCE change 20970 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://perforce.freebsd.org/chv.cgi?CH=20970 Change 20970 by jhb@jhb_laptop on 2002/11/11 11:30:27 Rename witness_sleep() to witness_warn() and make it a bit more extensible so it can handle more arbitrary messages, etc. Also, add a function to display a single lock instance and share this code between witness_warn() and witness_list_locks(). Affected files ... .. //depot/projects/smpng/sys/kern/subr_witness.c#62 edit .. //depot/projects/smpng/sys/sys/lock.h#18 edit Differences ... ==== //depot/projects/smpng/sys/kern/subr_witness.c#62 (text+ko) ==== @@ -145,6 +145,7 @@ static void witness_lock_list_free(struct lock_list_entry *lle); static struct lock_instance *find_instance(struct lock_list_entry *lock_list, struct lock_object *lock); +static int witness_list_lock(struct lock_instance *instance); #if defined(DDB) static void witness_display_list(void(*prnt)(const char *fmt, ...), struct witness_list *list); @@ -912,60 +913,71 @@ } /* - * Warn if any held locks are not sleepable. Note that Giant and the lock - * passed in are both special cases since they are both released during the - * sleep process and aren't actually held while the thread is asleep. + * Warn if any locks other than 'lock' are held. Flags can be passed in to + * exempt Giant and sleepable locks from the checks as well. If any + * non-exempt locks are held, then a supplied message is printed to the + * console along with a list of the offending locks. If indicated in the + * flags then a failure results in a panic as well. */ int -witness_sleep(int check_only, struct lock_object *lock, const char *file, - int line) +witness_warn(int flags, struct lock_object *lock, const char *file, int line, + const char *fmt, ...) { - struct lock_list_entry **lock_list, *lle; + struct lock_list_entry *lle; struct lock_instance *lock1; struct thread *td; + va_list ap; int i, n; if (witness_cold || witness_dead || panicstr != NULL) return (0); n = 0; td = curthread; - lock_list = &td->td_sleeplocks; -again: - for (lle = *lock_list; lle != NULL; lle = lle->ll_next) + for (lle = td->td_sleeplocks; lle != NULL; lle = lle->ll_next) for (i = lle->ll_count - 1; i >= 0; i--) { lock1 = &lle->ll_children[i]; - if (lock1->li_lock == lock || + if (lock1->li_lock == lock) + continue; + if (flags & WARN_GIANTOK && lock1->li_lock == &Giant.mtx_object) continue; - if ((lock1->li_lock->lo_flags & LO_SLEEPABLE) != 0) { - if (check_only == 0) { - CTR3(KTR_WITNESS, - "pid %d: sleeping with lock (%s) %s held", - td->td_proc->p_pid, - lock1->li_lock->lo_class->lc_name, - lock1->li_lock->lo_name); - lock1->li_flags |= LI_SLEPT; - } + if (flags & WARN_SLEEPOK && + (lock1->li_lock->lo_flags & LO_SLEEPABLE) != 0) continue; + if (n == 0) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf(" with the following"); + if (flags & WARN_SLEEPOK) + printf(" non-sleepable"); + printf("locks held at %s:%d:\n", file, line); } n++; - printf("%s:%d: %s with \"%s\" locked from %s:%d\n", - file, line, check_only ? "could sleep" : "sleeping", - lock1->li_lock->lo_name, lock1->li_file, - lock1->li_line); + witness_list_lock(lock1); } - if (lock_list == &td->td_sleeplocks && PCPU_GET(spinlocks) != NULL) { + if (PCPU_GET(spinlocks) != NULL) { /* * Since we already hold a spinlock preemption is * already blocked. */ - lock_list = PCPU_PTR(spinlocks); - goto again; + if (n == 0) { + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf(" with the following"); + if (flags & WARN_SLEEPOK) + printf(" non-sleepable"); + printf("locks held at %s:%d:\n", file, line); + } + n += witness_list_locks(PCPU_PTR(spinlocks)); } + if (flags & WARN_PANIC && n) + panic("witness_warn"); #ifdef DDB - if (witness_ddb && n) + else if (witness_ddb && n) Debugger(__func__); -#endif /* DDB */ +#endif return (n); } @@ -1354,28 +1366,31 @@ return (NULL); } +static int +witness_list_lock(struct lock_instance *instance) +{ + struct lock_object *lock; + + lock = instance->li_lock; + printf("%s %s %s", (instance->li_flags & LI_EXCLUSIVE) != 0 ? + "exclusive" : "shared", lock->lo_class->lc_name, lock->lo_name); + if (lock->lo_type != lock->lo_name) + printf(" (%s)", lock->lo_type); + printf(" r = %d (%p) locked @ %s:%d\n", + instance->li_flags & LI_RECURSEMASK, lock, instance->li_file, + instance->li_line); +} + int witness_list_locks(struct lock_list_entry **lock_list) { struct lock_list_entry *lle; - struct lock_instance *instance; - struct lock_object *lock; int i, nheld; nheld = 0; for (lle = *lock_list; lle != NULL; lle = lle->ll_next) for (i = lle->ll_count - 1; i >= 0; i--) { - instance = &lle->ll_children[i]; - lock = instance->li_lock; - printf("%s %s %s", - (instance->li_flags & LI_EXCLUSIVE) != 0 ? - "exclusive" : "shared", - lock->lo_class->lc_name, lock->lo_name); - if (lock->lo_type != lock->lo_name) - printf(" (%s)", lock->lo_type); - printf(" r = %d (%p) locked @ %s:%d\n", - instance->li_flags & LI_RECURSEMASK, lock, - instance->li_file, instance->li_line); + witness_list_lock(&lle->ll_children[i]); nheld++; } return (nheld); ==== //depot/projects/smpng/sys/sys/lock.h#18 (text+ko) ==== @@ -212,6 +212,12 @@ const char *witness_file(struct lock_object *); #ifdef WITNESS + +/* Flags for witness_warn(). */ +#define WARN_GIANTOK 0x01 /* Giant is exempt from this check. */ +#define WARN_PANIC 0x02 /* Panic if check fails. */ +#define WARN_SLEEPOK 0x04 /* Sleepable locks are exempt from check. */ + #define WITNESS_INIT(lock) \ witness_init((lock)) @@ -230,8 +236,8 @@ #define WITNESS_UNLOCK(lock, flags, file, line) \ witness_unlock((lock), (flags), (file), (line)) -#define WITNESS_SLEEP(check, lock) \ - witness_sleep((check), (lock), __FILE__, __LINE__) +#define WITNESS_WARN(flags, lock, fmt, ...) \ + witness_warn((flags), (lock), __FILE__, __LINE__, (fmt), __VA_ARGS__) #define WITNESS_SAVE_DECL(n) \ const char * __CONCAT(n, __wf); \ @@ -256,7 +262,7 @@ #define WITNESS_UPGRADE(lock, flags, file, line) #define WITNESS_DOWNGRADE(lock, flags, file, line) #define WITNESS_UNLOCK(lock, flags, file, line) -#define WITNESS_SLEEP(check, lock) +#define WITNESS_WARN(flags, lock, fmt, ...) #define WITNESS_SAVE_DECL(n) #define WITNESS_SAVE(lock, n) #define WITNESS_RESTORE(lock, n) @@ -264,5 +270,15 @@ #define WITNESS_LINE(lock) (0) #endif /* WITNESS */ +/* XXX */ +#define WITNESS_SLEEP(check, lock) do { \ + if ((check)) \ + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, \ + "Could Sleep"); \ + else \ + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, \ + "Sleeping"); \ +} while (0) + #endif /* _KERNEL */ #endif /* _SYS_LOCK_H_ */ To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message