Date: Mon, 10 Apr 2017 22:44:23 +0800 From: Julian Elischer <julian@freebsd.org> To: Yubin Ruan <ablacktshirt@gmail.com>, Ed Schouten <ed@nuxi.nl> Cc: freebsd-hackers@freebsd.org Subject: Re: Understanding the FreeBSD locking mechanism Message-ID: <56c36e41-e1cb-6e87-dc6e-922dd5abbccc@freebsd.org> In-Reply-To: <c72c0ee3-328d-3efc-e8a0-4d6c0d5c8cee@gmail.com> References: <e99b6366-7d30-a889-b7db-4a3b3133ff5e@gmail.com> <CABh_MKkbVVi%2BgTkaBVDvVfRggS6pbHKJE_VbYBZpAaTCZ81b7Q@mail.gmail.com> <c72c0ee3-328d-3efc-e8a0-4d6c0d5c8cee@gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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@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@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?56c36e41-e1cb-6e87-dc6e-922dd5abbccc>