diff mbox

Hurd port for GCC Go

Message ID 878v1wo7x0.fsf@kepler.schwinge.homeip.net
State New
Headers show

Commit Message

Thomas Schwinge June 26, 2013, 9:53 p.m. UTC
Hi!

On Fri, 14 Jun 2013 16:42:06 +0200, I wrote:
> I have now pushed my working branch to tschwinge/t/hurd/go, and will
> update this from time to time, both for integrating further changes (my
> own as well as those that you send me), and merge in GCC trunk changes.
> On that branch, use something like »git diff :/refs/top-bases/baseline«
> to diff your working tree against the branch's base.  When reviewing the
> commit history on that branch, it may be helpful to exclude any bulk
> merges from trunk, so use something like »git log HEAD ^origin/trunk«.
> 
> Fotis and Svante, please base any futher work for the Hurd port for GCC
> Go on that branch.  Send patches by email, for now.
> 
> > I got as far as having GCC Go compiling with GCC trunk sources; more to
> > come later.

I have just updated tschwinge/t/hurd/go with some further patches, and we
now got a usable baseline, hooray:

    $ grep -v ^PASS: < gcc/testsuite/go/go.sum 
    Test Run By thomas on Wed Jun 26 15:40:55 2013
    Native configuration is i686-unknown-gnu0.3
    
                    === go tests ===
    
    Schedule of variations:
        unix
    
    Running target unix
    Running [...]/gcc/testsuite/go.dg/dg.exp ...
    Running [...]/gcc/testsuite/go.go-torture/execute/execute.exp ...
    Running [...]/gcc/testsuite/go.test/go-test.exp ...
    FAIL: go.test/test/chan/doubleselect.go execution,  -O2 -g 
    FAIL: go.test/test/chan/nonblock.go execution,  -O2 -g 
    UNTESTED: go.test/test/chan/select2.go
    FAIL: go.test/test/chan/select3.go execution,  -O2 -g 
    FAIL: go.test/test/chan/select5.go execution
    UNTESTED: go.test/test/closure.go
    FAIL: go.test/test/fixedbugs/bug147.go execution,  -O2 -g 
    FAIL: go.test/test/fixedbugs/bug347.go execution,  -O0 -g 
    FAIL: go.test/test/fixedbugs/bug348.go execution,  -O0 -g 
    XFAIL: bug429.go  -O2 -g  execution test
    FAIL: go.test/test/goprint.go execution
    UNTESTED: go.test/test/goprint.go compare
    UNTESTED: go.test/test/init1.go
    FAIL: go.test/test/mallocfin.go execution,  -O2 -g 
    FAIL: go.test/test/nil.go execution,  -O2 -g 
    FAIL: go.test/test/recover3.go execution,  -O2 -g 
    UNTESTED: go.test/test/rotate.go
    UNTESTED: go.test/test/stack.go
    
                    === go Summary ===
    
    # of expected passes            5069
    # of unexpected failures        11
    # of expected failures          1
    # of untested testcases         6
    [...]/gcc/testsuite/go/../../gccgo  version 4.9.0 20130606 (experimental) (GCC) 

The patches are:

  * Disable -fsplit-stack (as just pushed to GCC trunk, too).

  * Hack in support in libgo for requesting heap memory with alignment
    requirements.  Any stack used on Hurd must currently have a 2 MiB
    size, and also be aligned accordingly.  This patch is probably not
    suitable/wanted for upstream.

  * Use the patch before to use accordingly-sized stacks on Hurd.  This
    patch is probably not suitable/wanted for upstream.  The Hurd
    eventually will support arbitrarily-sized and aligned stacks.

  * Revert a hack by Svante, which is now no longer needed, as the
    autodetection now works fine.

  * Disable the sigchld.go test, which busy-loops on GNU/Hurd, causing
    the test harness to hang.

  * Disable in libgo on Hurd the setup of an alternate signal stack.
    This patch is probably not suitable/wanted for upstream.  The Hurd
    eventually will support sigaltstack.

  * Disable in libgo on Hurd the use of SA_ONSTACK.  This looks like a
    bug in Hurd's glibc: signal handling breaks down (SIGILL) if no
    alternate signal stack has been set and SA_ONSTACK is used.  The
    standard says about SA_ONSTACK: »If set *and an alternate signal
    stack has been declared with sigaltstack()*, the signal shall be
    delivered to the calling process on that stack.  Otherwise, the
    signal shall be delivered on the current stack.«

  * Re-enable the sigchld.go test, which now passes.

commit 397bf49a65468084df39b3208971e53e0b166c65
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Tue Jun 25 16:32:02 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Tue Jun 25 18:13:47 2013 +0200

    gcc/
    	* config/i386/gnu.h [TARGET_LIBC_PROVIDES_SSP]
    	(TARGET_CAN_SPLIT_STACK, TARGET_THREAD_SPLIT_STACK_OFFSET):
    	Undefine.
---
 gcc/config/i386/gnu.h |    6 ++++++
 1 file changed, 6 insertions(+)



Grüße,
 Thomas
diff mbox

Patch

diff --git gcc/config/i386/gnu.h gcc/config/i386/gnu.h
index 35063e6..4a91c84 100644
--- gcc/config/i386/gnu.h
+++ gcc/config/i386/gnu.h
@@ -36,6 +36,12 @@  along with GCC.  If not, see <http://www.gnu.org/licenses/>.
 #endif
 
 #ifdef TARGET_LIBC_PROVIDES_SSP
+
 /* Not supported yet.  */
 # undef TARGET_THREAD_SSP_OFFSET
+
+/* Not supported yet.  */
+# undef TARGET_CAN_SPLIT_STACK
+# undef TARGET_THREAD_SPLIT_STACK_OFFSET
+
 #endif

commit 540a787bfe48ad434c1e44d425e287b7ac91af2f
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Tue Jun 25 17:59:28 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:13:57 2013 +0200

    Hack in support for requesting heap memory with alignment requirements.
    
    This has not been tested very much.
---
 libgo/runtime/malloc.goc |    2 +-
 libgo/runtime/malloc.h   |    2 +-
 libgo/runtime/mcentral.c |    2 +-
 libgo/runtime/mheap.c    |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
 4 files changed, 87 insertions(+), 20 deletions(-)

diff --git libgo/runtime/malloc.goc libgo/runtime/malloc.goc
index a484642..b68436f 100644
--- libgo/runtime/malloc.goc
+++ libgo/runtime/malloc.goc
@@ -78,7 +78,7 @@  runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 		npages = size >> PageShift;
 		if((size & PageMask) != 0)
 			npages++;
-		s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, zeroed);
+		s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 0, 1, zeroed);
 		if(s == nil)
 			runtime_throw("out of memory");
 		size = npages<<PageShift;
diff --git libgo/runtime/malloc.h libgo/runtime/malloc.h
index a820774..9b88536 100644
--- libgo/runtime/malloc.h
+++ libgo/runtime/malloc.h
@@ -430,7 +430,7 @@  struct MHeap
 extern MHeap runtime_mheap;
 
 void	runtime_MHeap_Init(MHeap *h, void *(*allocator)(uintptr));
-MSpan*	runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed);
+MSpan*	runtime_MHeap_Alloc(MHeap *h, uintptr npage, uintptr align, int32 sizeclass, int32 acct, int32 zeroed);
 void	runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct);
 MSpan*	runtime_MHeap_Lookup(MHeap *h, void *v);
 MSpan*	runtime_MHeap_LookupMaybe(MHeap *h, void *v);
diff --git libgo/runtime/mcentral.c libgo/runtime/mcentral.c
index b405438..cb8f807 100644
--- libgo/runtime/mcentral.c
+++ libgo/runtime/mcentral.c
@@ -200,7 +200,7 @@  MCentral_Grow(MCentral *c)
 
 	runtime_unlock(c);
 	runtime_MGetSizeClassInfo(c->sizeclass, &size, &npages, &n);
-	s = runtime_MHeap_Alloc(&runtime_mheap, npages, c->sizeclass, 0, 1);
+	s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, c->sizeclass, 0, 1);
 	if(s == nil) {
 		// TODO(rsc): Log out of memory
 		runtime_lock(c);
diff --git libgo/runtime/mheap.c libgo/runtime/mheap.c
index 6636b01..b91db9b 100644
--- libgo/runtime/mheap.c
+++ libgo/runtime/mheap.c
@@ -16,11 +16,11 @@ 
 #include "arch.h"
 #include "malloc.h"
 
-static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
-static bool MHeap_Grow(MHeap*, uintptr);
+static MSpan *MHeap_AllocLocked(MHeap*, uintptr, uintptr, int32);
+static bool MHeap_Grow(MHeap*, uintptr, uintptr);
 static void MHeap_FreeLocked(MHeap*, MSpan*);
-static MSpan *MHeap_AllocLarge(MHeap*, uintptr);
-static MSpan *BestFit(MSpan*, uintptr, MSpan*);
+static MSpan *MHeap_AllocLarge(MHeap*, uintptr, uintptr);
+static MSpan *BestFit(MSpan*, uintptr, uintptr, MSpan*);
 
 static void
 RecordSpan(void *vh, byte *p)
@@ -66,13 +66,13 @@  runtime_MHeap_Init(MHeap *h, void *(*alloc)(uintptr))
 // Allocate a new span of npage pages from the heap
 // and record its size class in the HeapMap and HeapMapCache.
 MSpan*
-runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32 zeroed)
+runtime_MHeap_Alloc(MHeap *h, uintptr npage, uintptr align, int32 sizeclass, int32 acct, int32 zeroed)
 {
 	MSpan *s;
 
 	runtime_lock(h);
 	runtime_purgecachedstats(runtime_m()->mcache);
-	s = MHeap_AllocLocked(h, npage, sizeclass);
+	s = MHeap_AllocLocked(h, npage, align, sizeclass);
 	if(s != nil) {
 		mstats.heap_inuse += npage<<PageShift;
 		if(acct) {
@@ -87,7 +87,7 @@  runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, int32 acct, int32
 }
 
 static MSpan*
-MHeap_AllocLocked(MHeap *h, uintptr npage, int32 sizeclass)
+MHeap_AllocLocked(MHeap *h, uintptr npage, uintptr align, int32 sizeclass)
 {
 	uintptr n;
 	MSpan *s, *t;
@@ -97,15 +97,34 @@  MHeap_AllocLocked(MHeap *h, uintptr npage, int32 sizeclass)
 	for(n=npage; n < nelem(h->free); n++) {
 		if(!runtime_MSpanList_IsEmpty(&h->free[n])) {
 			s = h->free[n].next;
+			if (align == 0) {
 				goto HaveSpan;
+			} else {
+#if 0
+				// Does it fit in with our alignment requirements, too?
+				uintptr padding = align - ((s->start << PageShift) & (align - 1));
+				// This does not have to consider any
+				// sub-PageSize padding amounts, that is, we
+				// don't have to round up to the next page, as
+				// we're just interested in snipping off a
+				// region so that the following page matches
+				// the required alignment.
+				uintptr npage_snip = padding >> PageShift;
+				if (s->npages >= (npage_snip + npage)) {
+					goto HaveSpan;
+				}
+#else
+				runtime_throw("untested");
+#endif
+			}
 		}
 	}
 
 	// Best fit in list of large spans.
-	if((s = MHeap_AllocLarge(h, npage)) == nil) {
-		if(!MHeap_Grow(h, npage))
+	if((s = MHeap_AllocLarge(h, npage, align)) == nil) {
+		if(!MHeap_Grow(h, npage, align))
 			return nil;
-		if((s = MHeap_AllocLarge(h, npage)) == nil)
+		if((s = MHeap_AllocLarge(h, npage, align)) == nil)
 			return nil;
 	}
 
@@ -121,6 +140,36 @@  HaveSpan:
 	mstats.heap_released -= s->npreleased<<PageShift;
 	s->npreleased = 0;
 
+	// Snip off a region at the beginning if so required.
+	if ((align != 0) && (((s->start << PageShift) & (align - 1)) != 0)) {
+		uintptr padding = align - ((s->start << PageShift) & (align - 1));
+		// This does not have to consider any sub-PageSize padding
+		// amounts, that is, we don't have to round up to the next
+		// page, as we're just interested in snipping off a region so
+		// that the following page matches the required alignment.
+		uintptr npage_snip = padding >> PageShift;
+		if (npage_snip > 0) {
+			t = runtime_FixAlloc_Alloc(&h->spanalloc);
+			mstats.mspan_inuse = h->spanalloc.inuse;
+			mstats.mspan_sys = h->spanalloc.sys;
+			runtime_MSpan_Init(t, s->start, npage_snip);
+			s->start += npage_snip;
+			s->npages -= npage_snip;
+			p = t->start;
+			if(sizeof(void*) == 8)
+				p -= ((uintptr)h->arena_start>>PageShift);
+			h->map[p] = t;
+			h->map[p+t->npages-1] = t;
+			h->map[p+t->npages] = s;
+			*(uintptr*)(t->start<<PageShift) = *(uintptr*)(s->start<<PageShift);  // copy "needs zeroing" mark
+			t->state = MSpanInUse;
+			MHeap_FreeLocked(h, t);
+			t->unusedsince = s->unusedsince; // preserve age
+		}
+	}
+	if(s->npages < npage)
+		runtime_throw("MHeap_AllocLocked - bad npages after alignment");
+
 	if(s->npages > npage) {
 		// Trim extra and put it back in the heap.
 		t = runtime_FixAlloc_Alloc(&h->spanalloc);
@@ -157,22 +206,33 @@  HaveSpan:
 
 // Allocate a span of exactly npage pages from the list of large spans.
 static MSpan*
-MHeap_AllocLarge(MHeap *h, uintptr npage)
+MHeap_AllocLarge(MHeap *h, uintptr npage, uintptr align)
 {
-	return BestFit(&h->large, npage, nil);
+	return BestFit(&h->large, npage, align, nil);
 }
 
 // Search list for smallest span with >= npage pages.
 // If there are multiple smallest spans, take the one
 // with the earliest starting address.
 static MSpan*
-BestFit(MSpan *list, uintptr npage, MSpan *best)
+BestFit(MSpan *list, uintptr npage, uintptr align, MSpan *best)
 {
 	MSpan *s;
 
 	for(s=list->next; s != list; s=s->next) {
-		if(s->npages < npage)
+		uintptr npage_snip = 0;
+		if (align != 0) {
+			uintptr padding = align - ((s->start << PageShift) & (align - 1));
+			// This does not have to consider any sub-PageSize
+			// padding amounts, that is, we don't have to round up
+			// to the next page, as we're just interested in
+			// snipping off a region so that the following page
+			// matches the required alignment.
+			npage_snip = padding >> PageShift;
+		}
+		if(s->npages < (npage_snip + npage))
 			continue;
+		// TODO: Need more tuning for align != 0?
 		if(best == nil
 		|| s->npages < best->npages
 		|| (s->npages == best->npages && s->start < best->start))
@@ -184,7 +244,7 @@  BestFit(MSpan *list, uintptr npage, MSpan *best)
 // Try to add at least npage pages of memory to the heap,
 // returning whether it worked.
 static bool
-MHeap_Grow(MHeap *h, uintptr npage)
+MHeap_Grow(MHeap *h, uintptr npage, uintptr align)
 {
 	uintptr ask;
 	void *v;
@@ -197,17 +257,24 @@  MHeap_Grow(MHeap *h, uintptr npage)
 	// Allocate a multiple of 64kB (16 pages).
 	npage = (npage+15)&~15;
 	ask = npage<<PageShift;
+	if (align != 0) {
+		// Allocate more than the caller requested: add as much as the
+		// size of the alignment requested, to be prepared for the
+		// operating system returning a memory region with the most
+		// unsuitable alignment.
+		ask += align;
+	}
 	if(ask < HeapAllocChunk)
 		ask = HeapAllocChunk;
 
 	v = runtime_MHeap_SysAlloc(h, ask);
 	if(v == nil) {
-		if(ask > (npage<<PageShift)) {
+		if((align == 0) && (ask > (npage<<PageShift))) {
 			ask = npage<<PageShift;
 			v = runtime_MHeap_SysAlloc(h, ask);
 		}
 		if(v == nil) {
-			runtime_printf("runtime: out of memory: cannot allocate %D-byte block (%D in use)\n", (uint64)ask, mstats.heap_sys);
+			runtime_printf("runtime: out of memory: cannot allocate %D-byte block with %D-byte alignment (%D in use)\n", (uint64)ask, (uint64) align, mstats.heap_sys);
 			return false;
 		}
 	}

commit 30b019c6c6c9932f9907f16765057fa35163d3df
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Wed Jun 26 08:45:22 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:16:15 2013 +0200

    <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>.
---
 libgo/configure          |    6 ++++++
 libgo/configure.ac       |    6 ++++++
 libgo/runtime/malloc.goc |   24 +++++++++++++++++++++++-
 libgo/runtime/malloc.h   |    2 ++
 libgo/runtime/mheap.c    |    4 ++++
 libgo/runtime/proc.c     |   10 ++++++++--
 libgo/runtime/thread.c   |    5 +++++
 7 files changed, 54 insertions(+), 3 deletions(-)

diff --git libgo/configure libgo/configure
index 2c4b758..4b2bdef 100755
--- libgo/configure
+++ libgo/configure
@@ -15106,7 +15106,13 @@  else
 
 __thread int tls;
 
+/* <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html> */
+#ifdef __GNU__
+static char __attribute__ ((aligned (2 * 1024 * 1024)))
+stack[2 * 1024 * 1024];
+#else
 static char stack[10 * 1024 * 1024];
+#endif
 static ucontext_t c;
 
 /* Called via makecontext/setcontext.  */
diff --git libgo/configure.ac libgo/configure.ac
index 99ed3a9..9f79e69 100644
--- libgo/configure.ac
+++ libgo/configure.ac
@@ -686,7 +686,13 @@  AC_RUN_IFELSE(
 
 __thread int tls;
 
+/* <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html> */
+#ifdef __GNU__
+static char __attribute__ ((aligned (2 * 1024 * 1024)))
+stack[[2 * 1024 * 1024]];
+#else
 static char stack[[10 * 1024 * 1024]];
+#endif
 static ucontext_t c;
 
 /* Called via makecontext/setcontext.  */
diff --git libgo/runtime/malloc.goc libgo/runtime/malloc.goc
index b68436f..f29a30a 100644
--- libgo/runtime/malloc.goc
+++ libgo/runtime/malloc.goc
@@ -42,6 +42,14 @@  runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 	MSpan *s;
 	void *v;
 
+	// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+#ifdef __GNU__
+	if (((flag & FlagStack) != 0) && (size != 2 * 1024 * 1024)) {
+		runtime_printf("stack allocation with size %D requested\n", (uint64) size);
+		runtime_throw("unusable size for a stack");
+	}
+#endif
+
 	m = runtime_m();
 	g = runtime_g();
 	if(g->status == Gsyscall)
@@ -62,6 +70,13 @@  runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 	c = m->mcache;
 	c->local_nmalloc++;
 	if(size <= MaxSmallSize) {
+		// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+#ifdef __GNU__
+		if ((flag & FlagStack) != 0) {
+			runtime_throw("unexpected and unsupported case for allocating a stack");
+		}
+#endif
+
 		// Allocate from mcache free lists.
 		sizeclass = runtime_SizeToClass(size);
 		size = runtime_class_to_size[sizeclass];
@@ -75,10 +90,17 @@  runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
 		// TODO(rsc): Report tracebacks for very large allocations.
 
 		// Allocate directly from heap.
+		uintptr align = 0;
+		// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+#ifdef __GNU__
+		if ((flag & FlagStack) != 0) {
+			align = 2 * 1024 * 1024;
+		}
+#endif
 		npages = size >> PageShift;
 		if((size & PageMask) != 0)
 			npages++;
-		s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 0, 1, zeroed);
+		s = runtime_MHeap_Alloc(&runtime_mheap, npages, align, 0, 1, zeroed);
 		if(s == nil)
 			runtime_throw("out of memory");
 		size = npages<<PageShift;
diff --git libgo/runtime/malloc.h libgo/runtime/malloc.h
index 9b88536..d0d75c1 100644
--- libgo/runtime/malloc.h
+++ libgo/runtime/malloc.h
@@ -466,6 +466,8 @@  enum
 	FlagNoPointers = 1<<0,	// no pointers here
 	FlagNoProfiling = 1<<1,	// must not profile
 	FlagNoGC = 1<<2,	// must not free or scan for pointers
+	// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+	FlagStack = 1<<3,	// To be used as a stack.
 };
 
 typedef struct Obj Obj;
diff --git libgo/runtime/mheap.c libgo/runtime/mheap.c
index b91db9b..f3df786 100644
--- libgo/runtime/mheap.c
+++ libgo/runtime/mheap.c
@@ -114,6 +114,10 @@  MHeap_AllocLocked(MHeap *h, uintptr npage, uintptr align, int32 sizeclass)
 					goto HaveSpan;
 				}
 #else
+				// As it turns out, the fixed-size spans have a
+				// maximum size of 1 MiB, so this code path is
+				// unreachable in context of
+				// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>.
 				runtime_throw("untested");
 #endif
 			}
diff --git libgo/runtime/proc.c libgo/runtime/proc.c
index e7ac1bd..16c1d86 100644
--- libgo/runtime/proc.c
+++ libgo/runtime/proc.c
@@ -48,7 +48,8 @@  extern void __splitstack_block_signals_context (void *context[10], int *,
 # define PTHREAD_STACK_MIN 8192
 #endif
 
-#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
+// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK) && !defined(__GNU__)
 # define StackMin PTHREAD_STACK_MIN
 #else
 # define StackMin 2 * 1024 * 1024
@@ -1241,6 +1242,10 @@  runtime_newm(void)
 	if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
 		runtime_throw("pthread_attr_setdetachstate");
 
+	// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+#ifdef __GNU__
+	stacksize = StackMin;
+#else
 	stacksize = PTHREAD_STACK_MIN;
 
 	// With glibc before version 2.16 the static TLS size is taken
@@ -1250,6 +1255,7 @@  runtime_newm(void)
 	// This can be disabled in glibc 2.16 and later, if the bug is
 	// indeed fixed then.
 	stacksize += tlssize;
+#endif
 
 	if(pthread_attr_setstacksize(&attr, stacksize) != 0)
 		runtime_throw("pthread_attr_setstacksize");
@@ -1519,7 +1525,7 @@  runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
 		__splitstack_block_signals_context(&newg->stack_context[0],
 						   &dont_block_signals, nil);
 #else
-		*ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0);
+		*ret_stack = runtime_mallocgc(stacksize, FlagStack|FlagNoProfiling|FlagNoGC, 0, 0);
 		*ret_stacksize = stacksize;
 		newg->gcinitial_sp = *ret_stack;
 		newg->gcstack_size = stacksize;
diff --git libgo/runtime/thread.c libgo/runtime/thread.c
index 12d0099..4bd272c 100644
--- libgo/runtime/thread.c
+++ libgo/runtime/thread.c
@@ -143,7 +143,12 @@  runtime_minit(void)
 	sigset_t sigs;
 
 	// Initialize signal handling.
+	// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
+#ifdef __GNU__
+	runtime_m()->gsignal = runtime_malg(2 * 1024 * 1024, &stack, &stacksize);
+#else
 	runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize);	// OS X wants >=8K, Linux >=2K
+#endif
 	ss.ss_sp = stack;
 	ss.ss_flags = 0;
 	ss.ss_size = stacksize;

commit 889869833e61d844d3703903791a332fa737411a
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Tue Jun 25 18:11:44 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:16:26 2013 +0200

    Revert "id:"1370596471.4596.25.camel@PackardBell-PC""
    
    This reverts commit 6d024607533390d446fff4e0e71fdf7dd17da129.
    
    This is now properly detected automatically.
---
 libgo/runtime/proc.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git libgo/runtime/proc.c libgo/runtime/proc.c
index 16c1d86..4f6c7ad 100644
--- libgo/runtime/proc.c
+++ libgo/runtime/proc.c
@@ -73,8 +73,7 @@  G	runtime_g0;	// idle goroutine for m0
 static __thread G *g;
 static __thread M *m;
 
-/* #ifndef SETCONTEXT_CLOBBERS_TLS */
-#if !defined(SETCONTEXT_CLOBBERS_TLS) || defined(__GNU__)
+#ifndef SETCONTEXT_CLOBBERS_TLS
 
 static inline void
 initcontext(void)

commit ff761071b9a173e71f526ecce15ac55754c374c1
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Tue Jun 25 18:04:11 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:16:30 2013 +0200

    gcc/testsuite/
    	* go.test/go-test.exp: Disable sigchld.go test.
---
 gcc/testsuite/go.test/go-test.exp |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git gcc/testsuite/go.test/go-test.exp gcc/testsuite/go.test/go-test.exp
index 6f39734..82866e5 100644
--- gcc/testsuite/go.test/go-test.exp
+++ gcc/testsuite/go.test/go-test.exp
@@ -352,6 +352,12 @@  proc go-gc-tests { } {
 	    continue
 	}
 
+	if { [file tail $test] == "sigchld.go" } {
+	    # Busy-loops on GNU/Hurd, causing the test harness to hang.
+	    untested $name
+	    continue
+	}
+
 	if { [file tail $test] == "bug347.go" \
 		 || [file tail $test] == "bug348.go" } {
 	    # These tests don't work if the functions are inlined.

commit 925d0cf65f6375b030df830bcb4c0d801097b136
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Wed Jun 26 14:25:49 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:16:34 2013 +0200

    	* libgo/runtime/thread.c (runtime_minit): No alternate signal
    	stack on GNU Hurd.
    
    <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
---
 libgo/runtime/thread.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git libgo/runtime/thread.c libgo/runtime/thread.c
index 4bd272c..2710831 100644
--- libgo/runtime/thread.c
+++ libgo/runtime/thread.c
@@ -137,23 +137,25 @@  __sync_add_and_fetch_8 (uint64* ptr, uint64 add)
 void
 runtime_minit(void)
 {
+#ifndef __GNU__
 	byte* stack;
 	size_t stacksize;
 	stack_t ss;
+#endif
 	sigset_t sigs;
 
 	// Initialize signal handling.
 	// <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>
 #ifdef __GNU__
-	runtime_m()->gsignal = runtime_malg(2 * 1024 * 1024, &stack, &stacksize);
+	runtime_m()->gsignal = nil;
 #else
 	runtime_m()->gsignal = runtime_malg(32*1024, &stack, &stacksize);	// OS X wants >=8K, Linux >=2K
-#endif
 	ss.ss_sp = stack;
 	ss.ss_flags = 0;
 	ss.ss_size = stacksize;
 	if(sigaltstack(&ss, nil) < 0)
 		*(int *)0xf1 = 0xf1;
+#endif
 	if (sigemptyset(&sigs) != 0)
 		runtime_throw("sigemptyset");
 	sigprocmask(SIG_SETMASK, &sigs, nil);

commit 0c51c07752cf854aeb8fc0e2ea73f784bdf61443
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Wed Jun 26 14:27:30 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:23:01 2013 +0200

    	* libgo/runtime/go-signal.c (runtime_setsig) [__GNU__]: Don't set
    	SA_ONSTACK.
    
    Bug in Hurd's glibc?  The standard says about SA_ONSTACK: If set *and an
    alternate signal stack has been declared with sigaltstack()*, the signal shall
    be delivered to the calling process on that stack.  Otherwise, the signal shall
    be delivered on the current stack.
---
 libgo/runtime/go-signal.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git libgo/runtime/go-signal.c libgo/runtime/go-signal.c
index 1965e05..0c313ef 100644
--- libgo/runtime/go-signal.c
+++ libgo/runtime/go-signal.c
@@ -434,7 +434,10 @@  runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
 
   if ((t->flags & SigPanic) == 0)
     {
+      /* <http://www.gnu.org/software/hurd/open_issues/libpthread_set_stack_size.html>.  */
+#ifndef __GNU__
       sa.sa_flags = SA_ONSTACK;
+#endif
       sa.sa_handler = sig_tramp;
     }
   else

commit 91840dfb3942a8d241cc4f0e573e5a9956011532
Author:     Thomas Schwinge <thomas@codesourcery.com>
AuthorDate: Wed Jun 26 14:26:14 2013 +0200
Commit:     Thomas Schwinge <thomas@codesourcery.com>
CommitDate: Wed Jun 26 15:24:32 2013 +0200

    Revert "gcc/testsuite/"
    
    This reverts commit 2eb51eab5f58fbd110aae626d3239789440ddb94.
    
    The test runs fine if an alternate signal stack is not set (which is known to
    be broken).
---
 gcc/testsuite/go.test/go-test.exp |    6 ------
 1 file changed, 6 deletions(-)

diff --git gcc/testsuite/go.test/go-test.exp gcc/testsuite/go.test/go-test.exp
index 82866e5..6f39734 100644
--- gcc/testsuite/go.test/go-test.exp
+++ gcc/testsuite/go.test/go-test.exp
@@ -352,12 +352,6 @@  proc go-gc-tests { } {
 	    continue
 	}
 
-	if { [file tail $test] == "sigchld.go" } {
-	    # Busy-loops on GNU/Hurd, causing the test harness to hang.
-	    untested $name
-	    continue
-	}
-
 	if { [file tail $test] == "bug347.go" \
 		 || [file tail $test] == "bug348.go" } {
 	    # These tests don't work if the functions are inlined.