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 <[email protected]>
AuthorDate: 2022-01-18 20:14:12 +0000
Commit:     Vladimir Kondratyev <[email protected]>
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

Reply via email to