Re: git: 02ea6033020e - main - LinuxKPI: Allow spin_lock_irqsave to be called within a critical section
Date: Tue, 18 Jan 2022 22:11:12 UTC
On 19.01.2022 01:08, Konstantin Belousov wrote:
> On Wed, Jan 19, 2022 at 01:01:45AM +0300, Vladimir Kondratyev wrote:
>> On 19.01.2022 00:48, Konstantin Belousov wrote:
>>> On Wed, Jan 19, 2022 at 12:35:41AM +0300, Vladimir Kondratyev wrote:
>>>> On 18.01.2022 23:22, Konstantin Belousov wrote:
>>>>> On Tue, Jan 18, 2022 at 08:15:36PM +0000, Vladimir Kondratyev wrote:
>>>>>> The branch main has been updated by wulf:
>>>>>>
>>>>>> URL: https://cgit.FreeBSD.org/src/commit/?id=02ea6033020e11afec6472bf560b0ddebd0fa97a
>>>>>>
>>>>>> commit 02ea6033020e11afec6472bf560b0ddebd0fa97a
>>>>>> Author: Vladimir Kondratyev <wulf@FreeBSD.org>
>>>>>> AuthorDate: 2022-01-18 20:14:12 +0000
>>>>>> Commit: Vladimir Kondratyev <wulf@FreeBSD.org>
>>>>>> CommitDate: 2022-01-18 20:14:12 +0000
>>>>>>
>>>>>> LinuxKPI: Allow spin_lock_irqsave to be called within a critical section
>>>>>> with spinning on spin_trylock. dma-buf part of drm-kmod depends on this
>>>>>> property and absence of it support results in "mi_switch: switch in a
>>>>>> critical section" assertions [1][2].
>>>>>> [1] https://github.com/freebsd/drm-kmod/issues/116
>>>>>> [2] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=261166
>>>>>> MFC after: 1 week
>>>>>> Reviewed by: manu
>>>>>> Differential Revision: https://reviews.freebsd.org/D33887
>>>>>> ---
>>>>>> .../linuxkpi/common/include/linux/spinlock.h | 27 ++++++++++++++++++----
>>>>>> 1 file changed, 23 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/sys/compat/linuxkpi/common/include/linux/spinlock.h b/sys/compat/linuxkpi/common/include/linux/spinlock.h
>>>>>> index a87cb7180b28..31d47fa73986 100644
>>>>>> --- a/sys/compat/linuxkpi/common/include/linux/spinlock.h
>>>>>> +++ b/sys/compat/linuxkpi/common/include/linux/spinlock.h
>>>>>> @@ -37,6 +37,7 @@
>>>>>> #include <sys/lock.h>
>>>>>> #include <sys/mutex.h>
>>>>>> #include <sys/kdb.h>
>>>>>> +#include <sys/proc.h>
>>>>>> #include <linux/compiler.h>
>>>>>> #include <linux/rwlock.h>
>>>>>> @@ -117,14 +118,32 @@ typedef struct {
>>>>>> local_bh_disable(); \
>>>>>> } while (0)
>>>>>> -#define spin_lock_irqsave(_l, flags) do { \
>>>>>> - (flags) = 0; \
>>>>>> - spin_lock(_l); \
>>>>>> +#define __spin_trylock_nested(_l, _n) ({ \
>>>>>> + int __ret; \
>>>>>> + if (SPIN_SKIP()) { \
>>>>>> + __ret = 1; \
>>>>>> + } else { \
>>>>>> + __ret = mtx_trylock_flags(&(_l)->m, MTX_DUPOK); \
>>>>>> + if (likely(__ret != 0)) \
>>>>>> + local_bh_disable(); \
>>>>>> + } \
>>>>>> + __ret; \
>>>>>> +})
>>>>>> +
>>>>>> +#define spin_lock_irqsave(_l, flags) do { \
>>>>>> + (flags) = 0; \
>>>>>> + if (unlikely(curthread->td_critnest != 0)) \
>>>>>> + while (!spin_trylock(_l)) {} \
>>>>>> + else \
>>>>>> + spin_lock(_l); \
>>>>>> } while (0)
>>>>>> #define spin_lock_irqsave_nested(_l, flags, _n) do { \
>>>>>> (flags) = 0; \
>>>>>> - spin_lock_nested(_l, _n); \
>>>>>> + if (unlikely(curthread->td_critnest != 0)) \
>>>>>> + while (!__spin_trylock_nested(_l, _n)) {} \
>>>>>> + else \
>>>>>> + spin_lock_nested(_l, _n); \
>>>>>> } while (0)
>>>>>> #define spin_unlock_irqrestore(_l, flags) do { \
>>>>> You are spin-waiting for blockable mutex, am I right?
>>>>
>>>> Both, yes and no. On Linux spin_lock_irqsave is generally unblockable as it
>>>> disables preemption and interrupts while our version does not do this as
>>>> LinuxKPI is not ready for such a tricks.
>>>> It seems that we should explicitly add critical_enter()/critical_exit calls
>>>> to related dma-buf parts to make it unblockable too.
>>> LinuxKPI does +1 to the level of locks comparing with Linux, so their spinlocks
>>> become our blockable mutexes.
>>>
>>> Can you please explain why dmabufs need critical section? What is
>>> achieved there by disabled preemption?
>>>
>>
>> dma-buf uses sequence locks for synchronization. If seqlock is taken for
>> write, than thread it holding enters in to critical section to not force
>> readers to spin if writer is preempted. Unfortunately, dma-buf writers
>> execute callbacks which requires locks and spin_lock_irqsave is used for
>> synchronize these callbacks.
>
> Then, it seems that locking should be changed either to rwlocks or rmlocks,
> not sure which.
>
> Do you mean our seqlocks as presented in sys/seqc.h, or something Linuxish?
LinuxKPI seqlocks wraps sys/seqc.h
--
WBR
Vladimir Kondratyev