Understanding the FreeBSD locking mechanism

Julian Elischer julian at freebsd.org
Mon Apr 10 14:44:36 UTC 2017


On 9/4/17 6:13 pm, Yubin Ruan wrote:
> On 2017/4/6 17:31, Ed Schouten wrote:
>> Hi Yubin,
>>
>> 2017-04-06 11:16 GMT+02:00 Yubin Ruan <ablacktshirt at gmail.com>:
>>> Does this function provides the ordinary "spinlock" functionality? 
>>> There
>>> is no special "test-and-set" instruction, and neither any extra 
>>> locking
>>> to protect internal data structure manipulation. Isn't this 
>>> subjected to
>>> race condition?
>>
>> Locking a spinlock is done through macro mtx_lock_spin(), which
>> expands to __mtx_lock_spin() in sys/sys/mutex.h. That macro first
>> calls into the function you looked at, spinlock_enter(), to disable
>> interrupts. It then calls into the _mtx_obtain_lock_fetch() to do the
>> test-and-set operation you were looking for.
>
> Thanks for replying. I have read some of those codes.
just in case it somehow slipped your attention or has not yet been 
brought up there is the following overview:

https://www.freebsd.org/cgi/man.cgi?locking(9)
>
> Just a few more questions, if you don't mind:
>
> (1) why are spinlocks forced to disable interrupt in FreeBSD?
>
> From the book "The design and implementation of the FreeBSD Operating
> System", the authors say "spinning can result in deadlock if a 
> thread interrupted the thread that held a mutex and then tried to 
> acquire the mutex"...(section 4.3, Mutex Synchronization, paragraph 4)
>
> I don't get the point why a spinlock(or *spin mutex* in the FreeBSD
> world) has to disable interrupt. Being interrupted does not necessarily
> mean a deadlock. Assume that thread A holding a lock T gets interrupted
> by another thread B(context switch here) and thread B try to acquire
> the lock T. After finding out that lock T has already been acquired,
> thread B will just spin until it gets preempted, after which thread A
> gets waken up and run and release the lock T. So, you see there is not
> necessarily any deadlock even if thread A get interrupted.
>
> I can only remember two conditions where using spinlock without
> disabling interrupts will cause deadlock:
>
> #######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 */
>
>
> #######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?)
>
> thanks,
> Yubin Ruan
> _______________________________________________
> freebsd-hackers at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to 
> "freebsd-hackers-unsubscribe at freebsd.org"
>



More information about the freebsd-hackers mailing list