Subject: Re: build aborts in regress/lib/libpthread/sem
To: None <port-dreamcast@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-dreamcast
Date: 02/23/2003 12:03:36
In article <yf93cmfzvl3.fsf@mc.pp.se>
marcus@mc.pp.se wrote:

> But which bus_space functions have conditional returns?  Is this
> really an issue?

No, it is not used at the moment. I'd be a bit paranoid :-)

> I'm fine with the DECL+LOCK+UNLOCK proposal too.

Ok, then how about the attached patch (with some cosmetic changes)?

I'm not sure if unrolling multi/region ops is really worth, though.
(it's optional in this patch for now)
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp

Index: g2bus_bus_mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c,v
retrieving revision 1.6
diff -u -r1.6 g2bus_bus_mem.c
--- g2bus_bus_mem.c	2002/12/27 11:34:05	1.6
+++ g2bus_bus_mem.c	2003/02/23 02:30:39
@@ -147,30 +147,35 @@
  * The following paired macros will take the necessary precautions.
  */
 
-#define G2_LOCK								\
+#define G2LOCK_DECL							\
+	int __s
+
+#define G2_LOCK()							\
 	do {								\
-		_cpu_exception_suspend();				\
+		__s = _cpu_intr_suspend();				\
 		/* suspend any G2 DMA here... */			\
-		while((*(volatile unsigned int *)0xa05f688c) & 32);	\
-	} while(/*CONSTCOND*/0)
+		while((*(volatile u_int32_t *)0xa05f688c) & 0x20);	\
+	} while (/*CONSTCOND*/0)
 
-#define G2_UNLOCK							\
+#define G2_UNLOCK()							\
 	do {								\
 		/* resume any G2 DMA here... */				\
-		_cpu_exception_resume(0);				\
-	} while(/*CONSTCOND*/0)
+		_cpu_intr_resume(__s);					\
+	} while (/*CONSTCOND*/0)
 
+/* #define G2BUSMEM_UNROLL_ITERATIONS */
 
 u_int8_t
 g2bus_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	G2LOCK_DECL;
 	u_int8_t rv;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	rv = *(__volatile u_int8_t *)(sh + off);
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 
 	return (rv);
 }
@@ -178,13 +183,14 @@
 u_int16_t
 g2bus_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	G2LOCK_DECL;
 	u_int16_t rv;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	rv = *(__volatile u_int16_t *)(sh + off);
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 
 	return (rv);
 }
@@ -192,13 +198,14 @@
 u_int32_t
 g2bus_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	G2LOCK_DECL;
 	u_int32_t rv;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	rv = *(__volatile u_int32_t *)(sh + off);
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 
 	return (rv);
 }
@@ -207,64 +214,115 @@
 g2bus_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int8_t val)
 {
+	G2LOCK_DECL;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	*(__volatile u_int8_t *)(sh + off) = val;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int16_t val)
 {
+	G2LOCK_DECL;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	*(__volatile u_int16_t *)(sh + off) = val;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int32_t val)
 {
+	G2LOCK_DECL;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	*(__volatile u_int32_t *)(sh + off) = val;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_bus_mem_read_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int8_t *addr, bus_size_t len)
 {
+	G2LOCK_DECL;
 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + off);
 
-	G2_LOCK;
+#ifdef G2BUSMEM_UNROLL_ITERATIONS
+	for (; len >= 16; len -= 16) {
+		G2_LOCK();
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		*addr++ = *baddr++;
+		G2_UNLOCK();
+	}
+#endif /* G2BUSMEM_UNROLL_ITERATIONS */
 
+	G2_LOCK();
+
 	while (len--)
 		*addr++ = *baddr++;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_bus_mem_write_region_1(void *v, bus_space_handle_t sh, bus_size_t off,
     const u_int8_t *addr, bus_size_t len)
 {
+	G2LOCK_DECL;
 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + off);
+
+#ifdef G2BUSMEM_UNROLL_ITERATIONS
+	for (; len >= 16; len -= 16) {
+		G2_LOCK();
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		*baddr++ = *addr++;
+		G2_UNLOCK();
+	}
+#endif /* G2BUSMEM_UNROLL_ITERATIONS */
 
-	G2_LOCK;
+	G2_LOCK();
 
 	while (len--)
 		*baddr++ = *addr++;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
@@ -291,13 +349,14 @@
 u_int8_t
 g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	G2LOCK_DECL;
 	u_int8_t rv;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	rv = *(__volatile u_int8_t *)(sh + (off * 4));
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 
 	return (rv);
 }
@@ -305,13 +364,14 @@
 u_int16_t
 g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	G2LOCK_DECL;
 	u_int16_t rv;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	rv = *(__volatile u_int16_t *)(sh + (off * 4));
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 
 	return (rv);
 }
@@ -319,13 +379,14 @@
 u_int32_t
 g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
 {
+	G2LOCK_DECL;
 	u_int32_t rv;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	rv = *(__volatile u_int32_t *)(sh + (off * 4));
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 
 	return (rv);
 }
@@ -334,94 +395,193 @@
 g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int8_t val)
 {
+	G2LOCK_DECL;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	*(__volatile u_int8_t *)(sh + (off * 4)) = val;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int16_t val)
 {
+	G2LOCK_DECL;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	*(__volatile u_int16_t *)(sh + (off * 4)) = val;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
     u_int32_t val)
 {
+	G2LOCK_DECL;
 
-	G2_LOCK;
+	G2_LOCK();
 
 	*(__volatile u_int32_t *)(sh + (off * 4)) = val;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
     bus_size_t off, u_int8_t *addr, bus_size_t len)
 {
+	G2LOCK_DECL;
 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
 
-	G2_LOCK;
+#ifdef G2BUSMEM_UNROLL_ITERATIONS
+	for (; len >= 8; len -= 8) {
+		G2_LOCK();
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		*addr++ = *baddr;
+		baddr += 4;
+		G2_UNLOCK();
+	}
+#endif /* G2BUSMEM_UNROLL_ITERATIONS */
+		
+	G2_LOCK();
 
 	while (len--) {
 		*addr++ = *baddr;
 		baddr += 4;
 	}
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
     bus_size_t off, const u_int8_t *addr, bus_size_t len)
 {
+	G2LOCK_DECL;
 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
 
-	G2_LOCK;
+#ifdef G2BUSMEM_UNROLL_ITERATIONS
+	for (; len >= 8; len -= 8) {
+		G2_LOCK();
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		*baddr = *addr++;
+		baddr += 4;
+		G2_UNLOCK();
+	}
+#endif /* G2BUSMEM_UNROLL_ITERATIONS */
+
+	G2_LOCK();
 
 	while (len--) {
 		*baddr = *addr++;
 		baddr += 4;
 	}
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
     bus_size_t off, u_int8_t *addr, bus_size_t len)
 {
+	G2LOCK_DECL;
 	__volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
+
+#ifdef G2BUSMEM_UNROLL_ITERATIONS
+	for (; len >= 16; len -= 16) {
+		G2_LOCK();
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		*addr++ = *baddr;
+		G2_UNLOCK();
+	}
+#endif /* G2BUSMEM_UNROLL_ITERATIONS */
 
-	G2_LOCK;
+	G2_LOCK();
 
 	while (len--)
 		*addr++ = *baddr;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }
 
 void
 g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
     bus_size_t off, const u_int8_t *addr, bus_size_t len)
 {
+	G2LOCK_DECL;
 	__volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
+
+#ifdef G2BUSMEM_UNROLL_ITERATIONS
+	for (; len >= 16; len -= 16) {
+		G2_LOCK();
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		*baddr = *addr++;
+		G2_UNLOCK();
+	}
+#endif /* G2BUSMEM_UNROLL_ITERATIONS */
 
-	G2_LOCK;
+	G2_LOCK();
 
 	while (len--)
 		*baddr = *addr++;
 
-	G2_UNLOCK;
+	G2_UNLOCK();
 }