Re: recursive spinlocks. Shoot.

From: Davide Libenzi (davidel@xmailserver.org)
Date: Sun May 18 2003 - 14:31:03 EST


On Sun, 18 May 2003, Peter T. Breuer wrote:

> In article <20030518182010$0541@gated-at.bofh.it> you wrote:
> > On Sun, 18 May 2003, Peter T. Breuer wrote:
> >> Here's a before-breakfast implementation of a recursive spinlock. That
>
> > A looong time ago I gave to someone a recursive spinlock implementation
> > that they integrated in the USB code. I don't see it in the latest
> > kernels, so I have to guess that they found a better solution to do their
> > things. I'm biased to say that it must not be necessary to have the thing
> > if you structure your code correctly.
>
> Well, you can get rid of anything that way. The question is if the
> interface is an appropriate one to use or not - i.e. if it makes for
> better code in general, or if it make errors of programming less
> likely.
>
> I would argue that the latter is undoubtedly true - merely that
> userspace flock/fcntl works that way would argue for it, but there
> are a couple of other reasons too.
>
> Going against is the point that it may be slower. Can you dig out your
> implementation and show me it? I wasn't going for assembler in my hasty
> example. I just wanted to establish that it's easy, so that it becomes
> known that its easy, and folks therefore aren't afraid of it. That both
> you and I have had to write it implies that it's not obvious code to
> everyone.

It was something like this. The real code should be in 2.2.x I believe.
The problem at the time was nested ( recursive ) spinlocks.

typedef struct s_nestlock {
        spinlock_t lock;
        void *uniq;
        atomic_t count;
} nestlock_t;

#define nestlock_init(snl) \
        do { \
                spin_lock_init(&(snl)->lock); \
                (snl)->uniq = NULL; \
                atomic_set(&(snl)->count, 0); \
        } while (0)

#define nestlock_irqlock(snl, flags) \
        do { \
                if ((snl)->uniq == current) { \
                        atomic_inc(&(snl)->count); \
                        flags = 0; /* No warnings */ \
                } else { \
                        spin_lock_irqsave(&(snl)->lock, flags); \
                        atomic_inc(&(snl)->count); \
                        (snl)->uniq = current; \
                } \
        } while (0)

#define nestlock_irqunlock(snl, flags) \
        do { \
                if (atomic_dec_and_test(&(snl)->count)) { \
                        (snl)->uniq = NULL; \
                        spin_unlock_irqrestore(&(snl)->lock, flags); \
                } \
        } while (0)

#define nestlock_lock(snl) \
        do { \
                if ((snl)->uniq == current) { \
                        atomic_inc(&(snl)->count); \
                } else { \
                        spin_lock(&(snl)->lock); \
                        atomic_inc(&(snl)->count); \
                        (snl)->uniq = current; \
                } \
        } while (0)

#define nestlock_unlock(snl) \
        do { \
                if (atomic_dec_and_test(&(snl)->count)) { \
                        (snl)->uniq = NULL; \
                        spin_unlock(&(snl)->lock); \
                } \
        } while (0)

- Davide

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri May 23 2003 - 22:00:31 EST