All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai-core] [PATCH] xnpipe: Fix minor number management
@ 2009-01-27 17:02 Jan Kiszka
  2009-01-27 17:14 ` Gilles Chanteperdrix
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Kiszka @ 2009-01-27 17:02 UTC (permalink / raw)
  To: xenomai-core

This is an attempt to fix the bugs found in the minor number management:
- changing the bitmap requires atomic operations
- clrbits/setbits work against xnarch_atomic_t, and that is only 32 bit
  wide on x86-64

The approach taken here is building the bitmap as an array of
xnarch_atomic_t variables, defining in asm/atomic.h how many bits of
xnarch_atomic_t are usable, and open-coding the bitmap search.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---

 include/asm-arm/atomic.h      |    3 +++
 include/asm-blackfin/atomic.h |    3 +++
 include/asm-powerpc/atomic.h  |    6 ++++++
 include/asm-sim/system.h      |    3 +++
 include/asm-x86/atomic.h      |    3 +++
 ksrc/nucleus/pipe.c           |   35 +++++++++++++++++++++++++----------
 6 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index 0b5e7de..df068c8 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -36,6 +36,9 @@ typedef atomic_t xnarch_atomic_t;
 #define xnarch_atomic_xchg(ptr,v)       xchg(ptr,v)
 #define xnarch_memory_barrier()  	smp_mb()
 
+#define BITS_PER_XNARCH_ATOMIC	32
+#define XNARCH_ATOMIC_MASK	((unsigned long)-1)
+
 #if __LINUX_ARM_ARCH__ >= 6
 
 static inline void
diff --git a/include/asm-blackfin/atomic.h b/include/asm-blackfin/atomic.h
index a6f03dd..4eb2bad 100644
--- a/include/asm-blackfin/atomic.h
+++ b/include/asm-blackfin/atomic.h
@@ -42,6 +42,9 @@
 typedef atomic_t atomic_counter_t;
 typedef atomic_t xnarch_atomic_t;
 
+#define BITS_PER_XNARCH_ATOMIC	32
+#define XNARCH_ATOMIC_MASK	((unsigned long)-1)
+
 #else /* !__KERNEL__ */
 
 #include <asm/xenomai/features.h>
diff --git a/include/asm-powerpc/atomic.h b/include/asm-powerpc/atomic.h
index 7b13142..ca956af 100644
--- a/include/asm-powerpc/atomic.h
+++ b/include/asm-powerpc/atomic.h
@@ -74,6 +74,9 @@ static __inline__ void atomic64_set_mask(unsigned long mask,
 typedef atomic64_t atomic_counter_t;
 typedef atomic64_t xnarch_atomic_t;
 
+#define BITS_PER_XNARCH_ATOMIC	64
+#define XNARCH_ATOMIC_MASK	((unsigned long)-1)
+
 #else /* !CONFIG_PPC64 */
  /* These are defined in arch/{ppc,powerpc}/kernel/misc[_32].S on 32-bit PowerPC */
 void atomic_set_mask(unsigned long mask, unsigned long *ptr);
@@ -93,6 +96,9 @@ void atomic_clear_mask(unsigned long mask, unsigned long *ptr);
 typedef atomic_t atomic_counter_t;
 typedef atomic_t xnarch_atomic_t;
 
+#define BITS_PER_XNARCH_ATOMIC	32
+#define XNARCH_ATOMIC_MASK	((unsigned long)-1)
+
 #endif /* !CONFIG_PPC64 */
 
 #else /* !__KERNEL__ */
diff --git a/include/asm-sim/system.h b/include/asm-sim/system.h
index cf3bee6..c889716 100644
--- a/include/asm-sim/system.h
+++ b/include/asm-sim/system.h
@@ -205,6 +205,9 @@ static inline unsigned long ffnz(unsigned long word)
 typedef int atomic_counter_t;
 typedef unsigned long atomic_flags_t;
 
+#define BITS_PER_XNARCH_ATOMIC	32
+#define XNARCH_ATOMIC_MASK	0xffffffff
+
 #define xnarch_memory_barrier()
 #define xnarch_atomic_set(pcounter,i)          (*(pcounter) = (i))
 #define xnarch_atomic_get(pcounter)            (*(pcounter))
diff --git a/include/asm-x86/atomic.h b/include/asm-x86/atomic.h
index c29b33a..7037ad2 100644
--- a/include/asm-x86/atomic.h
+++ b/include/asm-x86/atomic.h
@@ -44,6 +44,9 @@ typedef unsigned long atomic_flags_t;
 typedef atomic_long_t atomic_counter_t;
 typedef atomic_long_t xnarch_atomic_t;
 
+#define BITS_PER_XNARCH_ATOMIC	32
+#define XNARCH_ATOMIC_MASK	((unsigned int)-1)
+
 #define xnarch_atomic_set_mask(pflags,mask) \
 	atomic_set_mask((mask),(unsigned *)(pflags))
 #define xnarch_atomic_clear_mask(pflags,mask) \
diff --git a/ksrc/nucleus/pipe.c b/ksrc/nucleus/pipe.c
index d7409da..024e83c 100644
--- a/ksrc/nucleus/pipe.c
+++ b/ksrc/nucleus/pipe.c
@@ -39,8 +39,9 @@ static int xnpipe_asyncsig = SIGIO;
 
 struct xnpipe_state xnpipe_states[XNPIPE_NDEVS];
 
-#define XNPIPE_BITMAP_SIZE	((XNPIPE_NDEVS + BITS_PER_LONG - 1) / BITS_PER_LONG)
-static unsigned long xnpipe_bitmap[XNPIPE_BITMAP_SIZE];
+#define XNPIPE_BITMAP_SIZE 	((XNPIPE_NDEVS + BITS_PER_XNARCH_ATOMIC - 1) \
+				 / BITS_PER_XNARCH_ATOMIC)
+static xnarch_atomic_t xnpipe_bitmap[XNPIPE_BITMAP_SIZE];
 
 struct xnqueue xnpipe_sleepq, xnpipe_asyncq;
 
@@ -52,23 +53,36 @@ static DECLARE_DEVCLASS(xnpipe_class);
 
 static inline int xnpipe_minor_alloc(int minor)
 {
+	unsigned long val;
 	spl_t s;
+	int i;
 
 	if ((minor < 0 && minor != XNPIPE_MINOR_AUTO) || minor >= XNPIPE_NDEVS)
 		return -ENODEV;
 
 	xnlock_get_irqsave(&nklock, s);
 
-	if (minor == XNPIPE_MINOR_AUTO)
-		minor = find_first_zero_bit(xnpipe_bitmap, XNPIPE_NDEVS);
+	if (minor == XNPIPE_MINOR_AUTO) {
+		for (i = 0; i < XNPIPE_BITMAP_SIZE; i++) {
+			val = xnarch_atomic_get(&xnpipe_bitmap[i]);
+			if (val == XNARCH_ATOMIC_MASK)
+				continue;
+			minor = ffz(val) + i * BITS_PER_XNARCH_ATOMIC;
+			break;
+		}
+		if (i == XNPIPE_BITMAP_SIZE)
+			minor = XNPIPE_NDEVS;
+	}
 
 	if (minor == XNPIPE_NDEVS ||
-	    testbits(xnpipe_bitmap[minor / BITS_PER_LONG],
-		     1UL << (minor % BITS_PER_LONG)))
+	    (xnarch_atomic_get
+		(&xnpipe_bitmap[minor / BITS_PER_XNARCH_ATOMIC]) &
+	     (1 << (minor % BITS_PER_XNARCH_ATOMIC))))
 		minor = -EBUSY;
 	else
-		__setbits(xnpipe_bitmap[minor / BITS_PER_LONG],
-			  1UL << (minor % BITS_PER_LONG));
+		xnarch_atomic_set_mask
+			(&xnpipe_bitmap[minor / BITS_PER_XNARCH_ATOMIC],
+			 1 << (minor % BITS_PER_XNARCH_ATOMIC));
 
 	xnlock_put_irqrestore(&nklock, s);
 
@@ -78,8 +92,9 @@ static inline int xnpipe_minor_alloc(int minor)
 static inline void xnpipe_minor_free(int minor)
 {
 	/* May be called with nklock free. */
-	clrbits(xnpipe_bitmap[minor / BITS_PER_LONG],
-		1UL << (minor % BITS_PER_LONG));
+	xnarch_atomic_clear_mask
+		(&xnpipe_bitmap[minor / BITS_PER_XNARCH_ATOMIC],
+		 1 << (minor % BITS_PER_XNARCH_ATOMIC));
 	xnarch_memory_barrier();
 }
 


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Xenomai-core] [PATCH] xnpipe: Fix minor number management
  2009-01-27 17:02 [Xenomai-core] [PATCH] xnpipe: Fix minor number management Jan Kiszka
@ 2009-01-27 17:14 ` Gilles Chanteperdrix
  2009-01-27 17:19   ` Gilles Chanteperdrix
  2009-01-27 17:27   ` Jan Kiszka
  0 siblings, 2 replies; 4+ messages in thread
From: Gilles Chanteperdrix @ 2009-01-27 17:14 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

Jan Kiszka wrote:
> This is an attempt to fix the bugs found in the minor number management:
> - changing the bitmap requires atomic operations
> - clrbits/setbits work against xnarch_atomic_t, and that is only 32 bit
>   wide on x86-64

I think we should rather fix xnarch_atomic_t to be the size of a long on
x86-64, than having to cope with xnarch_atomic_t of various sizes in the
code (there are probably other places where we depend on the size of
xnarch_atomic_t).

As for the find_first_bit, why not simply taking the nklock
xnpipe_minor_free ? This is a first masking section, so this should not
matter a lot.

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Xenomai-core] [PATCH] xnpipe: Fix minor number management
  2009-01-27 17:14 ` Gilles Chanteperdrix
@ 2009-01-27 17:19   ` Gilles Chanteperdrix
  2009-01-27 17:27   ` Jan Kiszka
  1 sibling, 0 replies; 4+ messages in thread
From: Gilles Chanteperdrix @ 2009-01-27 17:19 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai-core

Gilles Chanteperdrix wrote:
> As for the find_first_bit, why not simply taking the nklock

in

> xnpipe_minor_free ? This is a first masking section, so this should not
> matter a lot.

a short masking section

-- 
                                                 Gilles.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Xenomai-core] [PATCH] xnpipe: Fix minor number management
  2009-01-27 17:14 ` Gilles Chanteperdrix
  2009-01-27 17:19   ` Gilles Chanteperdrix
@ 2009-01-27 17:27   ` Jan Kiszka
  1 sibling, 0 replies; 4+ messages in thread
From: Jan Kiszka @ 2009-01-27 17:27 UTC (permalink / raw)
  To: Gilles Chanteperdrix; +Cc: xenomai-core

Gilles Chanteperdrix wrote:
> Jan Kiszka wrote:
>> This is an attempt to fix the bugs found in the minor number management:
>> - changing the bitmap requires atomic operations
>> - clrbits/setbits work against xnarch_atomic_t, and that is only 32 bit
>>   wide on x86-64
> 
> I think we should rather fix xnarch_atomic_t to be the size of a long on
> x86-64, than having to cope with xnarch_atomic_t of various sizes in the
> code (there are probably other places where we depend on the size of
> xnarch_atomic_t).

IIRC, not all Linux atomic ops exits for atomic64_t, so we would have to
provide our own versions. Moreover, there might be a deeper reason for
Linux staying at 32 bit atomics on x86-64. Performance? Just speculating
now, but I wouldn't touch this for Xenomai without an urgent need.

> 
> As for the find_first_bit, why not simply taking the nklock
> xnpipe_minor_free ? This is a first masking section, so this should not
> matter a lot.

Yeah, probably the better approach - back to non-atomic ops:

--------->

Instead of trying to perform the minor release lockless (and failing due
to 32-bit atomic ops on x86-64), let's go back to nklock-protected
bitmap handling.

Signed-off-by: Jan Kiszka <jan.kiszka@domain.hid>
---

 ksrc/nucleus/pipe.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/ksrc/nucleus/pipe.c b/ksrc/nucleus/pipe.c
index d7409da..d201f5d 100644
--- a/ksrc/nucleus/pipe.c
+++ b/ksrc/nucleus/pipe.c
@@ -78,9 +78,8 @@ static inline int xnpipe_minor_alloc(int minor)
 static inline void xnpipe_minor_free(int minor)
 {
 	/* May be called with nklock free. */
-	clrbits(xnpipe_bitmap[minor / BITS_PER_LONG],
-		1UL << (minor % BITS_PER_LONG));
-	xnarch_memory_barrier();
+	__clrbits(xnpipe_bitmap[minor / BITS_PER_LONG],
+		  1UL << (minor % BITS_PER_LONG));
 }
 
 static inline void xnpipe_enqueue_wait(struct xnpipe_state *state, int mask)
@@ -414,7 +413,9 @@ cleanup:
 	} else {
 		xnlock_put_irqrestore(&nklock, s);
 		state->ops.release(state->xstate);
+		xnlock_get_irqsave(&nklock, s);
 		xnpipe_minor_free(minor);
+		xnlock_put_irqrestore(&nklock, s);
 	}
 
 	if (need_sched)
@@ -622,8 +623,8 @@ int xnpipe_flush(int minor, int mode)
 			clrbits((__state)->status, XNPIPE_KERN_LCLOSE);	\
 			xnlock_put_irqrestore(&nklock, (__s));		\
 			(__state)->ops.release((__state)->xstate);	\
-			xnpipe_minor_free(xnminor_from_state(__state));	\
 			xnlock_get_irqsave(&nklock, (__s));		\
+			xnpipe_minor_free(xnminor_from_state(__state));	\
 		}							\
 	} while(0)
 


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-01-27 17:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-27 17:02 [Xenomai-core] [PATCH] xnpipe: Fix minor number management Jan Kiszka
2009-01-27 17:14 ` Gilles Chanteperdrix
2009-01-27 17:19   ` Gilles Chanteperdrix
2009-01-27 17:27   ` Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.