Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 10 Apr 2017 12:01:51 +0800
From:      Yubin Ruan <ablacktshirt@gmail.com>
To:        Warner Losh <imp@bsdimp.com>
Cc:        Ryan Stone <rysto32@gmail.com>, "freebsd-hackers@freebsd.org" <freebsd-hackers@freebsd.org>, Ed Schouten <ed@nuxi.nl>
Subject:   Re: Understanding the FreeBSD locking mechanism
Message-ID:  <b69597cd-fab6-7ef8-7dfe-d097283c4064@gmail.com>
In-Reply-To: <CANCZdfoyjcSU%2BNHEVJF=bd8xz-Q-H1EupMPX%2BJk45r3DKZ9F9Q@mail.gmail.com>
References:  <e99b6366-7d30-a889-b7db-4a3b3133ff5e@gmail.com> <CABh_MKkbVVi%2BgTkaBVDvVfRggS6pbHKJE_VbYBZpAaTCZ81b7Q@mail.gmail.com> <c72c0ee3-328d-3efc-e8a0-4d6c0d5c8cee@gmail.com> <CAFMmRNwWnaq-4vEDCByqdUzWfoiZeN0nM_M5rt8ST0P8xnUTsA@mail.gmail.com> <3f93930c-7f10-4d0b-35f2-2b07d64081f0@gmail.com> <CANCZdfoyjcSU%2BNHEVJF=bd8xz-Q-H1EupMPX%2BJk45r3DKZ9F9Q@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2017/4/10 9:51, Warner Losh wrote:
> On Sun, Apr 9, 2017 at 7:28 PM, Yubin Ruan <ablacktshirt@gmail.com> wrote:
>> On 2017/4/10 0:24, Ryan Stone wrote:
>>>
>>>
>>>
>>> On Sun, Apr 9, 2017 at 6:13 AM, Yubin Ruan <ablacktshirt@gmail.com
>>> <mailto:ablacktshirt@gmail.com>> wrote:
>>>
>>>
>>>     #######1, spinlock used in an interrupt handler
>>>     If a thread A holding a spinlock T get interrupted and the interrupt
>>>     handler responsible for this interrupt try to acquire T, then we have
>>>     deadlock, because A would never have a chance to run before the
>>>     interrupt handler return, and the interrupt handler, unfortunately,
>>>     will continue to spin ... so in this situation, one has to disable
>>>     interrupt before spinning.
>>>
>>>     As far as I know, in Linux, they provide two kinds of spinlocks:
>>>
>>>       spin_lock(..);   /* spinlock that does not disable interrupts */
>>>       spin_lock_irqsave(...); /* spinlock that disable local interrupt *
>>>
>>>
>>> In the FreeBSD locking style, a spinlock is only used in the case where
>>> one needs to synchronize with an interrupt handler.  This is why spinlocks
>>> always disable local interrupts in FreeBSD.
>>>
>>> FreeBSD's lock for the first case is the MTX_DEF mutex, which is
>>> adaptively-spinning blocking mutex implementation.  In short, the MTX_DEF
>>> mutex will spin waiting for the lock if the owner is running, but will
>>> block if the owner is deschedules.  This prevents expensive trips through
>>> the scheduler for the common case where the mutex is only held for short
>>> periods, without wasting CPU cycles spinning in cases where the owner
>>> thread
>>> is descheduled and therefore will not be completing soon.
>>
>>
>> Great explanation! I read the man page at:
>>
>>>
>>> https://www.freebsd.org/cgi/man.cgi?query=mutex&sektion=9&apropos=0&manpath=FreeBSD+11.0-RELEASE+and+Ports
>>
>> and now clear about MTX_DEF and MTX_SPIN mutexs. But, still a few more
>> question, if you don't mind:
>>
>> Is it true that a thread holding a MTX_DEF mutex can be descheduled?
>> (shouldn't it disable interrupt like a MTX_SPIN mutex?) It is said on
>> the main page that MTX_DEF mutex is used by default in FreeBSD, so its
>> usecase must be very common. If a thread holding a MTX_DEF mutex can be
>> descheduled, which means that it did not disable interrupt, then we may
>> have lots of deadlock here, right?
>
> Yes, they can be descheduled. But that's not a problem. No other
> thread can acquire the MTX_DEF lock. If another thread tries, it will
> sleep and wait for the thread that holds the MTX_DEF lock to release
> it. Eventually, the thread will get time to run again, and then
> release the lock. Threads that just hold a MTX_DEF lock may also
> migrate from CPU to CPU too.
>
> Warner
>

Does that imply that MTX_DEF should not be used in something like
interrupt handler? Putting an interrupt handler into sleep doesn't
make so much sense.

Yubin

>>>     #######2, priority inversion problem
>>>     If thread B with a higher priority get in and try to acquire the lock
>>>     that thread A currently holds, then thread B would spin, while at the
>>>     same time thread A has no chance to run because it has lower priority,
>>>     thus not being able to release the lock.
>>>     (I haven't investigate enough into the source code, so I don't know
>>>     how FreeBSD and Linux handle this priority inversion problem. Maybe
>>>     they use priority inheritance or random boosting?)
>>>
>>>
>>> FreeBSD's spin locks prevent priority inversion by preventing the holder
>>> thread from being descheduled.
>>>
>>> MTX_DEF locks implement priority inheritance.
>>
>>
>> Nice hints. Thanks!
>>
>> regards,
>> Yubin Ruan
>>
>>
>> _______________________________________________
>> freebsd-hackers@freebsd.org mailing list
>> https://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?b69597cd-fab6-7ef8-7dfe-d097283c4064>