FreeBSD/sys/kern/subr_witness.c
/*
 * 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
 * output channel along with a list of the offending locks.  If indicated in the
 * flags then a failure results in a panic as well.
 */
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
output channel along with a list of the offending locks.  If indicated in the
flags then a failure results in a panic as well.
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 output channel along with a list of the offending locks . If indicated in the flags then a failure results in a panic as well .
int
witness_warn(int flags, struct lock_object *lock, const char *fmt, ...)
{
	struct lock_list_entry *lock_list, *lle;
	struct lock_instance *lock1;
	struct thread *td;
	va_list ap;
	int i, n;
	if (witness_cold || witness_watch < 1 || panicstr != NULL)
		return (0);
	n = 0;
	td = curthread;
	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)
				continue;
			if (flags & WARN_GIANTOK &&
			    lock1->li_lock == &Giant.lock_object)
				continue;
			if (flags & WARN_SLEEPOK &&
			    (lock1->li_lock->lo_flags & LO_SLEEPABLE) != 0)
				continue;
			if (n == 0) {
				va_start(ap, fmt);
				witness_voutput(fmt, ap);
				va_end(ap);
				witness_output(
				    " with the following %slocks held:\n",
				    (flags & WARN_SLEEPOK) != 0 ?
				    "non-sleepable " : "");
			}
			n++;
			witness_list_lock(lock1, witness_output);
		}
	sched_pin();
	lock_list = PCPU_GET(spinlocks);
	if (lock_list != NULL && lock_list->ll_count != 0) {
		sched_unpin();
		lock1 = &lock_list->ll_children[lock_list->ll_count - 1];
		if (lock_list->ll_count == 1 && lock_list->ll_next == NULL &&
		    lock1->li_lock == lock && n == 0)
			return (0);
		va_start(ap, fmt);
		witness_voutput(fmt, ap);
		va_end(ap);
		witness_output(" with the following %slocks held:\n",
		    (flags & WARN_SLEEPOK) != 0 ?  "non-sleepable " : "");
		n += witness_list_locks(&lock_list, witness_output);
	} else
		sched_unpin();
	if (flags & WARN_PANIC && n)
		kassert_panic("%s", __func__);
	else
		witness_debugger(n, __func__);
	return (n);
}
int witness_warn ( int flags , struct lock_object * lock , const char * fmt , ... ) { struct lock_list_entry * lock_list , * lle ; struct lock_instance * lock1 ; struct thread * td ; va_list ap ; int i , n ; if ( witness_cold || witness_watch < 1 || panicstr != NULL ) return ( 0 ) ; n = 0 ; td = curthread ; 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 ) continue ; if ( flags & WARN_GIANTOK && lock1 -> li_lock == & Giant . lock_object ) continue ; if ( flags & WARN_SLEEPOK && ( lock1 -> li_lock -> lo_flags & LO_SLEEPABLE ) != 0 ) continue ; if ( n == 0 ) { va_start ( ap , fmt ) ; witness_voutput ( fmt , ap ) ; va_end ( ap ) ; witness_output ( " \n " , ( flags & WARN_SLEEPOK ) != 0 ? " " : " " ) ; } n ++ ; witness_list_lock ( lock1 , witness_output ) ; } sched_pin ( ) ; lock_list = PCPU_GET ( spinlocks ) ; if ( lock_list != NULL && lock_list -> ll_count != 0 ) { sched_unpin ( ) ; lock1 = & lock_list -> ll_children [ lock_list -> ll_count - 1 ] ; if ( lock_list -> ll_count == 1 && lock_list -> ll_next == NULL && lock1 -> li_lock == lock && n == 0 ) return ( 0 ) ; va_start ( ap , fmt ) ; witness_voutput ( fmt , ap ) ; va_end ( ap ) ; witness_output ( " \n " , ( flags & WARN_SLEEPOK ) != 0 ? " " : " " ) ; n += witness_list_locks ( & lock_list , witness_output ) ; } else sched_unpin ( ) ; if ( flags & WARN_PANIC && n ) kassert_panic ( " " , __func__ ) ; else witness_debugger ( n , __func__ ) ; return ( n ) ; }
Warn if any locks other than 'lock' are held.
Warn if any locks other than ' lock ' are held .
/*
	 * Pin the thread in order to avoid problems with thread migration.
	 * Once that all verifies are passed about spinlocks ownership,
	 * the thread is in a safe path and it can be unpinned.
	 */ /*
		 * We should only have one spinlock and as long as
		 * the flags cannot match for this locks class,
		 * check if the first spinlock is the one curthread
		 * should hold.
		 */