Patchwork libgo patch committed: Fix channels for big-endian & strict-alignment

login
register
mail settings
Submitter Ian Taylor
Date Feb. 11, 2012, 12:03 a.m.
Message ID <mcry5sakzhx.fsf@dhcp-172-18-216-180.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/140736/
State New
Headers show

Comments

Ian Taylor - Feb. 11, 2012, 12:03 a.m.
This libgo patch fixes the channel code to work correctly on big-endian
systems.  The older version of the code did this right, but I forgot to
handle it in the new version.  This patch also fixes the memory
structure built for the select statement to work correctly on strict
alignment systems.  The code was putting a uint16_t array before a
pointer array, which would of course cause a SIGBUS on a strict
alignment system.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Bootstrapped and ran channel tests on
sparc-sun-solaris2.11; the Go testsuite on that system still has some
failures but they appear to be due to other problems, such as PR 52205
which I just filed.  Committed to mainline.

Ian

Patch

diff -r 93764d4d4aca libgo/runtime/chan.c
--- a/libgo/runtime/chan.c	Fri Feb 10 07:53:37 2012 -0800
+++ b/libgo/runtime/chan.c	Fri Feb 10 15:54:46 2012 -0800
@@ -409,11 +409,20 @@ 
 void
 __go_send_small(ChanType *t, Hchan* c, uint64 val)
 {
-	byte b[sizeof(uint64)];
+	union
+	{
+		byte b[sizeof(uint64)];
+		uint64 v;
+	} u;
+	byte *p;
 
-	runtime_memclr(b, sizeof(uint64));
-	__builtin_memcpy(b, &val, t->__element_type->__size);
-	runtime_chansend(t, c, b, nil);
+	u.v = val;
+#ifndef WORDS_BIGENDIAN
+	p = u.b;
+#else
+	p = u.b + sizeof(uint64) - t->__element_type->__size;
+#endif
+	runtime_chansend(t, c, p, nil);
 }
 
 // The compiler generates a call to __go_send_big to send a value
@@ -433,9 +442,15 @@ 
 		byte b[sizeof(uint64)];
 		uint64 v;
 	} u;
+	byte *p;
 
 	u.v = 0;
-	runtime_chanrecv(t, c, u.b, nil, nil);
+#ifndef WORDS_BIGENDIAN
+	p = u.b;
+#else
+	p = u.b + sizeof(uint64) - t->__element_type->__size;
+#endif
+	runtime_chanrecv(t, c, p, nil, nil);
 	return u.v;
 }
 
@@ -654,8 +669,8 @@ 
 
 	sel->tcase = size;
 	sel->ncase = 0;
-	sel->pollorder = (void*)(sel->scase + size);
-	sel->lockorder = (void*)(sel->pollorder + size);
+	sel->lockorder = (void*)(sel->scase + size);
+	sel->pollorder = (void*)(sel->lockorder + size);
 	*selp = sel;
 
 	if(debug)