Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Jan 2013 11:44:09 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-current@freebsd.org
Cc:        Ryan Stone <rysto32@gmail.com>
Subject:   Re: Spurious witness warning when destroying spin mtx
Message-ID:  <201301111144.10060.jhb@freebsd.org>
In-Reply-To: <CAFMmRNyYccyXFh0r2jC2Q5ynYQH09SiZNguLp8X4JWSX4Lua5w@mail.gmail.com>
References:  <CAFMmRNyYccyXFh0r2jC2Q5ynYQH09SiZNguLp8X4JWSX4Lua5w@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Friday, November 23, 2012 10:08:28 PM Ryan Stone wrote:
> Today I saw a spurious witness warning for "acquiring duplicate lock of
> same type".  The root cause is that when running mtx_destroy on a spinlock
> that is held by the current thread, mtx_destroy calls spinlock_exit()
> before calling WITNESS_UNLOCK, which opens up a window in which the CPU can
> be interrupted and attempt to acquire another spinlock of the same type as
> the one being destroyed.  This patch should fix it:
> 
> diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
> index 2f13863..96f43f8 100644
> --- a/sys/kern/kern_mutex.c
> +++ b/sys/kern/kern_mutex.c
> @@ -918,16 +918,16 @@ _mtx_destroy(volatile uintptr_t *c)
>         else {
>                 MPASS((m->mtx_lock & (MTX_RECURSED|MTX_CONTESTED)) == 0);
> 
> +               lock_profile_release_lock(&m->lock_object);
> +               /* Tell witness this isn't locked to make it happy. */
> +               WITNESS_UNLOCK(&m->lock_object, LOP_EXCLUSIVE, __FILE__,
> +                   __LINE__);
> +
>                 /* Perform the non-mtx related part of mtx_unlock_spin().
> */ if (LOCK_CLASS(&m->lock_object) == &lock_class_mtx_spin)
> spinlock_exit();
>                 else
>                         curthread->td_locks--;
> -
> -               lock_profile_release_lock(&m->lock_object);
> -               /* Tell witness this isn't locked to make it happy. */
> -               WITNESS_UNLOCK(&m->lock_object, LOP_EXCLUSIVE, __FILE__,
> -                   __LINE__);
>         }
> 
>         m->mtx_lock = MTX_DESTROYED

Ah, I would tweak this slightly perhaps to match mtx_unlock() and 
mtx_unlock_spin():

if (LOCK_CLASS() == &lock_class_mtx_sleep)
	curthread->td_locks--;

/* lock profile and witness stuff */

if (LOCK_CLASS() == &lock_class_mtx_spin)
	spinlock_exit();

You are correct that it is broken for the spin case.

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201301111144.10060.jhb>