Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 240609)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@
-e51657a576367c7a498c94baf985b79066fc082a
+f3fb9bf2d5a009a707962a416fcd1a8435756218
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 240453)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -3787,6 +3787,13 @@ Unary_expression::do_flatten(Gogo* gogo,
       if ((n->encoding() & ESCAPE_MASK) == int(Node::ESCAPE_NONE))
 	this->escapes_ = false;
 
+      // When compiling the runtime, the address operator does not
+      // cause local variables to escapes.  When escape analysis
+      // becomes the default, this should be changed to make it an
+      // error if we have an address operator that escapes.
+      if (gogo->compiling_runtime() && gogo->package_name() == "runtime")
+	this->escapes_ = false;
+
       Named_object* var = NULL;
       if (this->expr_->var_expression() != NULL)
 	var = this->expr_->var_expression()->named_object();
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 240559)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -4480,6 +4480,19 @@ Gogo::write_c_header()
        ++p)
     {
       Named_object* no = *p;
+
+      // Skip names that start with underscore followed by something
+      // other than an uppercase letter, as when compiling the runtime
+      // package they are mostly types defined by mkrsysinfo.sh based
+      // on the C system header files.  We don't need to translate
+      // types to C and back to Go.  But do accept the special cases
+      // _defer and _panic.
+      std::string name = Gogo::unpack_hidden_name(no->name());
+      if (name[0] == '_'
+	  && (name[1] < 'A' || name[1] > 'Z')
+	  && (name != "_defer" && name != "_panic"))
+	continue;
+
       if (no->is_type() && no->type_value()->struct_type() != NULL)
 	types.push_back(no);
       if (no->is_const() && no->const_value()->type()->integer_type() != NULL)
Index: libgo/Makefile.am
===================================================================
--- libgo/Makefile.am	(revision 240588)
+++ libgo/Makefile.am	(working copy)
@@ -396,9 +396,9 @@ rtems_task_variable_add_file =
 endif
 
 if LIBGO_IS_LINUX
-runtime_lock_files = runtime/lock_futex.c runtime/thread-linux.c
+runtime_thread_files = runtime/thread-linux.c
 else
-runtime_lock_files = runtime/lock_sema.c runtime/thread-sema.c
+runtime_thread_files = runtime/thread-sema.c
 endif
 
 if LIBGO_IS_LINUX
@@ -502,7 +502,6 @@ runtime_files = \
 	runtime/go-varargs.c \
 	runtime/env_posix.c \
 	runtime/heapdump.c \
-	$(runtime_lock_files) \
 	runtime/mcache.c \
 	runtime/mcentral.c \
 	$(runtime_mem_file) \
@@ -518,6 +517,7 @@ runtime_files = \
 	runtime/runtime.c \
 	runtime/signal_unix.c \
 	runtime/thread.c \
+	$(runtime_thread_files) \
 	runtime/yield.c \
 	$(rtems_task_variable_add_file) \
 	chan.c \
@@ -633,12 +633,8 @@ s-version: Makefile
 	$(STAMP) $@
 
 runtime_sysinfo.go: s-runtime_sysinfo; @true
-s-runtime_sysinfo: sysinfo.go
-	rm -f tmp-runtime_sysinfo.go
-	echo 'package runtime' > tmp-runtime_sysinfo.go
-	echo >> tmp-runtime_sysinfo.go
-	grep 'const _sizeof_ucontext_t ' sysinfo.go >> tmp-runtime_sysinfo.go
-	grep 'type _sigset_t ' sysinfo.go >> tmp-runtime_sysinfo.go
+s-runtime_sysinfo: $(srcdir)/mkrsysinfo.sh gen-sysinfo.go
+	$(SHELL) $(srcdir)/mkrsysinfo.sh
 	$(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime_sysinfo.go runtime_sysinfo.go
 	$(STAMP) $@
 
Index: libgo/configure.ac
===================================================================
--- libgo/configure.ac	(revision 240146)
+++ libgo/configure.ac	(working copy)
@@ -570,7 +570,7 @@ AC_C_BIGENDIAN
 
 GCC_CHECK_UNWIND_GETIPINFO
 
-AC_CHECK_HEADERS(sched.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
+AC_CHECK_HEADERS(sched.h semaphore.h sys/file.h sys/mman.h syscall.h sys/epoll.h sys/inotify.h sys/ptrace.h sys/syscall.h sys/user.h sys/utsname.h sys/select.h sys/socket.h net/if.h net/if_arp.h net/route.h netpacket/packet.h sys/prctl.h sys/mount.h sys/vfs.h sys/statfs.h sys/timex.h sys/sysinfo.h utime.h linux/ether.h linux/fs.h linux/reboot.h netinet/icmp6.h netinet/in_syst.h netinet/ip.h netinet/ip_mroute.h netinet/if_ether.h)
 
 AC_CHECK_HEADERS([linux/filter.h linux/if_addr.h linux/if_ether.h linux/if_tun.h linux/netlink.h linux/rtnetlink.h], [], [],
 [#ifdef HAVE_SYS_SOCKET_H
Index: libgo/go/runtime/export_test.go
===================================================================
--- libgo/go/runtime/export_test.go	(revision 240609)
+++ libgo/go/runtime/export_test.go	(working copy)
@@ -17,8 +17,6 @@ package runtime
 //var F64toint = f64toint
 //var Sqrt = sqrt
 
-func entersyscall(int32)
-func exitsyscall(int32)
 func golockedOSThread() bool
 
 var Entersyscall = entersyscall
Index: libgo/go/runtime/lock_futex.go
===================================================================
--- libgo/go/runtime/lock_futex.go	(revision 0)
+++ libgo/go/runtime/lock_futex.go	(working copy)
@@ -0,0 +1,225 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build dragonfly freebsd linux
+
+package runtime
+
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
+
+// For gccgo, while we still have C runtime code, use go:linkname to
+// rename some functions to themselves, so that the compiler will
+// export them.
+//
+//go:linkname lock runtime.lock
+//go:linkname unlock runtime.unlock
+//go:linkname noteclear runtime.noteclear
+//go:linkname notewakeup runtime.notewakeup
+//go:linkname notesleep runtime.notesleep
+//go:linkname notetsleep runtime.notetsleep
+//go:linkname notetsleepg runtime.notetsleepg
+
+// This implementation depends on OS-specific implementations of
+//
+//	futexsleep(addr *uint32, val uint32, ns int64)
+//		Atomically,
+//			if *addr == val { sleep }
+//		Might be woken up spuriously; that's allowed.
+//		Don't sleep longer than ns; ns < 0 means forever.
+//
+//	futexwakeup(addr *uint32, cnt uint32)
+//		If any procs are sleeping on addr, wake up at most cnt.
+
+const (
+	mutex_unlocked = 0
+	mutex_locked   = 1
+	mutex_sleeping = 2
+
+	active_spin     = 4
+	active_spin_cnt = 30
+	passive_spin    = 1
+)
+
+// Possible lock states are mutex_unlocked, mutex_locked and mutex_sleeping.
+// mutex_sleeping means that there is presumably at least one sleeping thread.
+// Note that there can be spinning threads during all states - they do not
+// affect mutex's state.
+
+// We use the uintptr mutex.key and note.key as a uint32.
+func key32(p *uintptr) *uint32 {
+	return (*uint32)(unsafe.Pointer(p))
+}
+
+func lock(l *mutex) {
+	gp := getg()
+
+	if gp.m.locks < 0 {
+		throw("runtime·lock: lock count")
+	}
+	gp.m.locks++
+
+	// Speculative grab for lock.
+	v := atomic.Xchg(key32(&l.key), mutex_locked)
+	if v == mutex_unlocked {
+		return
+	}
+
+	// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
+	// depending on whether there is a thread sleeping
+	// on this mutex. If we ever change l->key from
+	// MUTEX_SLEEPING to some other value, we must be
+	// careful to change it back to MUTEX_SLEEPING before
+	// returning, to ensure that the sleeping thread gets
+	// its wakeup call.
+	wait := v
+
+	// On uniprocessors, no point spinning.
+	// On multiprocessors, spin for ACTIVE_SPIN attempts.
+	spin := 0
+	if ncpu > 1 {
+		spin = active_spin
+	}
+	for {
+		// Try for lock, spinning.
+		for i := 0; i < spin; i++ {
+			for l.key == mutex_unlocked {
+				if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {
+					return
+				}
+			}
+			procyield(active_spin_cnt)
+		}
+
+		// Try for lock, rescheduling.
+		for i := 0; i < passive_spin; i++ {
+			for l.key == mutex_unlocked {
+				if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {
+					return
+				}
+			}
+			osyield()
+		}
+
+		// Sleep.
+		v = atomic.Xchg(key32(&l.key), mutex_sleeping)
+		if v == mutex_unlocked {
+			return
+		}
+		wait = mutex_sleeping
+		futexsleep(key32(&l.key), mutex_sleeping, -1)
+	}
+}
+
+func unlock(l *mutex) {
+	v := atomic.Xchg(key32(&l.key), mutex_unlocked)
+	if v == mutex_unlocked {
+		throw("unlock of unlocked lock")
+	}
+	if v == mutex_sleeping {
+		futexwakeup(key32(&l.key), 1)
+	}
+
+	gp := getg()
+	gp.m.locks--
+	if gp.m.locks < 0 {
+		throw("runtime·unlock: lock count")
+	}
+	// if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack
+	//	gp.stackguard0 = stackPreempt
+	// }
+}
+
+// One-time notifications.
+func noteclear(n *note) {
+	n.key = 0
+}
+
+func notewakeup(n *note) {
+	old := atomic.Xchg(key32(&n.key), 1)
+	if old != 0 {
+		print("notewakeup - double wakeup (", old, ")\n")
+		throw("notewakeup - double wakeup")
+	}
+	futexwakeup(key32(&n.key), 1)
+}
+
+func notesleep(n *note) {
+	gp := getg()
+
+	// Currently OK to sleep in non-g0 for gccgo.  It happens in
+	// stoptheworld because we have not implemented preemption.
+	// if gp != gp.m.g0 {
+	// 	throw("notesleep not on g0")
+	// }
+
+	for atomic.Load(key32(&n.key)) == 0 {
+		gp.m.blocked = true
+		futexsleep(key32(&n.key), 0, -1)
+		gp.m.blocked = false
+	}
+}
+
+// May run with m.p==nil if called from notetsleep, so write barriers
+// are not allowed.
+//
+//go:nosplit
+//go:nowritebarrier
+func notetsleep_internal(n *note, ns int64) bool {
+	gp := getg()
+
+	if ns < 0 {
+		for atomic.Load(key32(&n.key)) == 0 {
+			gp.m.blocked = true
+			futexsleep(key32(&n.key), 0, -1)
+			gp.m.blocked = false
+		}
+		return true
+	}
+
+	if atomic.Load(key32(&n.key)) != 0 {
+		return true
+	}
+
+	deadline := nanotime() + ns
+	for {
+		gp.m.blocked = true
+		futexsleep(key32(&n.key), 0, ns)
+		gp.m.blocked = false
+		if atomic.Load(key32(&n.key)) != 0 {
+			break
+		}
+		now := nanotime()
+		if now >= deadline {
+			break
+		}
+		ns = deadline - now
+	}
+	return atomic.Load(key32(&n.key)) != 0
+}
+
+func notetsleep(n *note, ns int64) bool {
+	gp := getg()
+	if gp != gp.m.g0 && gp.m.preemptoff != "" {
+		throw("notetsleep not on g0")
+	}
+
+	return notetsleep_internal(n, ns)
+}
+
+// same as runtime·notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+func notetsleepg(n *note, ns int64) bool {
+	gp := getg()
+	if gp == gp.m.g0 {
+		throw("notetsleepg on g0")
+	}
+
+	entersyscallblock(0)
+	ok := notetsleep_internal(n, ns)
+	exitsyscall(0)
+	return ok
+}
Index: libgo/go/runtime/lock_sema.go
===================================================================
--- libgo/go/runtime/lock_sema.go	(revision 0)
+++ libgo/go/runtime/lock_sema.go	(working copy)
@@ -0,0 +1,281 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin nacl netbsd openbsd plan9 solaris windows
+
+package runtime
+
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
+
+// For gccgo, while we still have C runtime code, use go:linkname to
+// rename some functions to themselves, so that the compiler will
+// export them.
+//
+//go:linkname lock runtime.lock
+//go:linkname unlock runtime.unlock
+//go:linkname noteclear runtime.noteclear
+//go:linkname notewakeup runtime.notewakeup
+//go:linkname notesleep runtime.notesleep
+//go:linkname notetsleep runtime.notetsleep
+//go:linkname notetsleepg runtime.notetsleepg
+
+// This implementation depends on OS-specific implementations of
+//
+//	func semacreate(mp *m)
+//		Create a semaphore for mp, if it does not already have one.
+//
+//	func semasleep(ns int64) int32
+//		If ns < 0, acquire m's semaphore and return 0.
+//		If ns >= 0, try to acquire m's semaphore for at most ns nanoseconds.
+//		Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
+//
+//	func semawakeup(mp *m)
+//		Wake up mp, which is or will soon be sleeping on its semaphore.
+//
+const (
+	mutex_locked uintptr = 1
+
+	active_spin     = 4
+	active_spin_cnt = 30
+	passive_spin    = 1
+)
+
+func lock(l *mutex) {
+	gp := getg()
+	if gp.m.locks < 0 {
+		throw("runtime·lock: lock count")
+	}
+	gp.m.locks++
+
+	// Speculative grab for lock.
+	if atomic.Casuintptr(&l.key, 0, mutex_locked) {
+		return
+	}
+	semacreate(gp.m)
+
+	// On uniprocessor's, no point spinning.
+	// On multiprocessors, spin for ACTIVE_SPIN attempts.
+	spin := 0
+	if ncpu > 1 {
+		spin = active_spin
+	}
+Loop:
+	for i := 0; ; i++ {
+		v := atomic.Loaduintptr(&l.key)
+		if v&mutex_locked == 0 {
+			// Unlocked. Try to lock.
+			if atomic.Casuintptr(&l.key, v, v|mutex_locked) {
+				return
+			}
+			i = 0
+		}
+		if i < spin {
+			procyield(active_spin_cnt)
+		} else if i < spin+passive_spin {
+			osyield()
+		} else {
+			// Someone else has it.
+			// l->waitm points to a linked list of M's waiting
+			// for this lock, chained through m->nextwaitm.
+			// Queue this M.
+			for {
+				gp.m.nextwaitm = v &^ mutex_locked
+				if atomic.Casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|mutex_locked) {
+					break
+				}
+				v = atomic.Loaduintptr(&l.key)
+				if v&mutex_locked == 0 {
+					continue Loop
+				}
+			}
+			if v&mutex_locked != 0 {
+				// Queued. Wait.
+				semasleep(-1)
+				i = 0
+			}
+		}
+	}
+}
+
+//go:nowritebarrier
+// We might not be holding a p in this code.
+func unlock(l *mutex) {
+	gp := getg()
+	var mp *m
+	for {
+		v := atomic.Loaduintptr(&l.key)
+		if v == mutex_locked {
+			if atomic.Casuintptr(&l.key, mutex_locked, 0) {
+				break
+			}
+		} else {
+			// Other M's are waiting for the lock.
+			// Dequeue an M.
+			mp = (*m)(unsafe.Pointer(v &^ mutex_locked))
+			if atomic.Casuintptr(&l.key, v, mp.nextwaitm) {
+				// Dequeued an M.  Wake it.
+				semawakeup(mp)
+				break
+			}
+		}
+	}
+	gp.m.locks--
+	if gp.m.locks < 0 {
+		throw("runtime·unlock: lock count")
+	}
+	// if gp.m.locks == 0 && gp.preempt { // restore the preemption request in case we've cleared it in newstack
+	//	gp.stackguard0 = stackPreempt
+	// }
+}
+
+// One-time notifications.
+func noteclear(n *note) {
+	n.key = 0
+}
+
+func notewakeup(n *note) {
+	var v uintptr
+	for {
+		v = atomic.Loaduintptr(&n.key)
+		if atomic.Casuintptr(&n.key, v, mutex_locked) {
+			break
+		}
+	}
+
+	// Successfully set waitm to locked.
+	// What was it before?
+	switch {
+	case v == 0:
+		// Nothing was waiting. Done.
+	case v == mutex_locked:
+		// Two notewakeups!  Not allowed.
+		throw("notewakeup - double wakeup")
+	default:
+		// Must be the waiting m. Wake it up.
+		semawakeup((*m)(unsafe.Pointer(v)))
+	}
+}
+
+func notesleep(n *note) {
+	gp := getg()
+
+	// Currently OK to sleep in non-g0 for gccgo.  It happens in
+	// stoptheworld because we have not implemented preemption.
+	// if gp != gp.m.g0 {
+	//	throw("notesleep not on g0")
+	// }
+
+	semacreate(gp.m)
+	if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+		// Must be locked (got wakeup).
+		if n.key != mutex_locked {
+			throw("notesleep - waitm out of sync")
+		}
+		return
+	}
+	// Queued. Sleep.
+	gp.m.blocked = true
+	semasleep(-1)
+	gp.m.blocked = false
+}
+
+//go:nosplit
+func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
+	// gp and deadline are logically local variables, but they are written
+	// as parameters so that the stack space they require is charged
+	// to the caller.
+	// This reduces the nosplit footprint of notetsleep_internal.
+	gp = getg()
+
+	// Register for wakeup on n->waitm.
+	if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+		// Must be locked (got wakeup).
+		if n.key != mutex_locked {
+			throw("notetsleep - waitm out of sync")
+		}
+		return true
+	}
+	if ns < 0 {
+		// Queued. Sleep.
+		gp.m.blocked = true
+		semasleep(-1)
+		gp.m.blocked = false
+		return true
+	}
+
+	deadline = nanotime() + ns
+	for {
+		// Registered. Sleep.
+		gp.m.blocked = true
+		if semasleep(ns) >= 0 {
+			gp.m.blocked = false
+			// Acquired semaphore, semawakeup unregistered us.
+			// Done.
+			return true
+		}
+		gp.m.blocked = false
+		// Interrupted or timed out. Still registered. Semaphore not acquired.
+		ns = deadline - nanotime()
+		if ns <= 0 {
+			break
+		}
+		// Deadline hasn't arrived. Keep sleeping.
+	}
+
+	// Deadline arrived. Still registered. Semaphore not acquired.
+	// Want to give up and return, but have to unregister first,
+	// so that any notewakeup racing with the return does not
+	// try to grant us the semaphore when we don't expect it.
+	for {
+		v := atomic.Loaduintptr(&n.key)
+		switch v {
+		case uintptr(unsafe.Pointer(gp.m)):
+			// No wakeup yet; unregister if possible.
+			if atomic.Casuintptr(&n.key, v, 0) {
+				return false
+			}
+		case mutex_locked:
+			// Wakeup happened so semaphore is available.
+			// Grab it to avoid getting out of sync.
+			gp.m.blocked = true
+			if semasleep(-1) < 0 {
+				throw("runtime: unable to acquire - semaphore out of sync")
+			}
+			gp.m.blocked = false
+			return true
+		default:
+			throw("runtime: unexpected waitm - semaphore out of sync")
+		}
+	}
+}
+
+func notetsleep(n *note, ns int64) bool {
+	gp := getg()
+
+	// Currently OK to sleep in non-g0 for gccgo.  It happens in
+	// stoptheworld because we have not implemented preemption.
+	// if gp != gp.m.g0 && gp.m.preemptoff != "" {
+	//	throw("notetsleep not on g0")
+	// }
+
+	semacreate(gp.m)
+	return notetsleep_internal(n, ns, nil, 0)
+}
+
+// same as runtime·notetsleep, but called on user g (not g0)
+// calls only nosplit functions between entersyscallblock/exitsyscall
+func notetsleepg(n *note, ns int64) bool {
+	gp := getg()
+	if gp == gp.m.g0 {
+		throw("notetsleepg on g0")
+	}
+	semacreate(gp.m)
+	entersyscallblock(0)
+	ok := notetsleep_internal(n, ns, nil, 0)
+	exitsyscall(0)
+	return ok
+}
Index: libgo/go/runtime/os_darwin.go
===================================================================
--- libgo/go/runtime/os_darwin.go	(revision 0)
+++ libgo/go/runtime/os_darwin.go	(working copy)
@@ -0,0 +1,326 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type mOS struct {
+	machport uint32 // return address for mach ipc
+	waitsema uint32 // semaphore for parking on locks
+}
+
+//go:noescape
+//extern mach_msg_trap
+func mach_msg_trap(h unsafe.Pointer, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32
+
+//extern mach_reply_port
+func mach_reply_port() uint32
+
+//extern mach_task_self
+func mach_task_self() uint32
+
+func unimplemented(name string) {
+	println(name, "not implemented")
+	*(*int)(unsafe.Pointer(uintptr(1231))) = 1231
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+	mach_semrelease(mp.mos.waitsema)
+}
+
+//go:nosplit
+func semacreate(mp *m) {
+	if mp.mos.waitsema != 0 {
+		return
+	}
+	systemstack(func() {
+		mp.mos.waitsema = mach_semcreate()
+	})
+}
+
+// Mach IPC, to get at semaphores
+// Definitions are in /usr/include/mach on a Mac.
+
+func macherror(r int32, fn string) {
+	print("mach error ", fn, ": ", r, "\n")
+	throw("mach error")
+}
+
+const _DebugMach = false
+
+var zerondr machndr
+
+func mach_msgh_bits(a, b uint32) uint32 {
+	return a | b<<8
+}
+
+func mach_msg(h *machheader, op int32, send_size, rcv_size, rcv_name, timeout, notify uint32) int32 {
+	// TODO: Loop on interrupt.
+	return mach_msg_trap(unsafe.Pointer(h), op, send_size, rcv_size, rcv_name, timeout, notify)
+}
+
+// Mach RPC (MIG)
+const (
+	_MinMachMsg = 48
+	_MachReply  = 100
+)
+
+type codemsg struct {
+	h    machheader
+	ndr  machndr
+	code int32
+}
+
+func machcall(h *machheader, maxsize int32, rxsize int32) int32 {
+	_g_ := getg()
+	port := _g_.m.mos.machport
+	if port == 0 {
+		port = mach_reply_port()
+		_g_.m.mos.machport = port
+	}
+
+	h.msgh_bits |= mach_msgh_bits(_MACH_MSG_TYPE_COPY_SEND, _MACH_MSG_TYPE_MAKE_SEND_ONCE)
+	h.msgh_local_port = port
+	h.msgh_reserved = 0
+	id := h.msgh_id
+
+	if _DebugMach {
+		p := (*[10000]unsafe.Pointer)(unsafe.Pointer(h))
+		print("send:\t")
+		var i uint32
+		for i = 0; i < h.msgh_size/uint32(unsafe.Sizeof(p[0])); i++ {
+			print(" ", p[i])
+			if i%8 == 7 {
+				print("\n\t")
+			}
+		}
+		if i%8 != 0 {
+			print("\n")
+		}
+	}
+	ret := mach_msg(h, _MACH_SEND_MSG|_MACH_RCV_MSG, h.msgh_size, uint32(maxsize), port, 0, 0)
+	if ret != 0 {
+		if _DebugMach {
+			print("mach_msg error ", ret, "\n")
+		}
+		return ret
+	}
+	if _DebugMach {
+		p := (*[10000]unsafe.Pointer)(unsafe.Pointer(h))
+		var i uint32
+		for i = 0; i < h.msgh_size/uint32(unsafe.Sizeof(p[0])); i++ {
+			print(" ", p[i])
+			if i%8 == 7 {
+				print("\n\t")
+			}
+		}
+		if i%8 != 0 {
+			print("\n")
+		}
+	}
+	if h.msgh_id != id+_MachReply {
+		if _DebugMach {
+			print("mach_msg _MachReply id mismatch ", h.msgh_id, " != ", id+_MachReply, "\n")
+		}
+		return -303 // MIG_REPLY_MISMATCH
+	}
+	// Look for a response giving the return value.
+	// Any call can send this back with an error,
+	// and some calls only have return values so they
+	// send it back on success too. I don't quite see how
+	// you know it's one of these and not the full response
+	// format, so just look if the message is right.
+	c := (*codemsg)(unsafe.Pointer(h))
+	if uintptr(h.msgh_size) == unsafe.Sizeof(*c) && h.msgh_bits&_MACH_MSGH_BITS_COMPLEX == 0 {
+		if _DebugMach {
+			print("mig result ", c.code, "\n")
+		}
+		return c.code
+	}
+	if h.msgh_size != uint32(rxsize) {
+		if _DebugMach {
+			print("mach_msg _MachReply size mismatch ", h.msgh_size, " != ", rxsize, "\n")
+		}
+		return -307 // MIG_ARRAY_TOO_LARGE
+	}
+	return 0
+}
+
+// Semaphores!
+
+const (
+	tmach_semcreate = 3418
+	rmach_semcreate = tmach_semcreate + _MachReply
+
+	tmach_semdestroy = 3419
+	rmach_semdestroy = tmach_semdestroy + _MachReply
+
+	_KERN_ABORTED             = 14
+	_KERN_OPERATION_TIMED_OUT = 49
+)
+
+type tmach_semcreatemsg struct {
+	h      machheader
+	ndr    machndr
+	policy int32
+	value  int32
+}
+
+type rmach_semcreatemsg struct {
+	h         machheader
+	body      machbody
+	semaphore machport
+}
+
+type tmach_semdestroymsg struct {
+	h         machheader
+	body      machbody
+	semaphore machport
+}
+
+func mach_semcreate() uint32 {
+	var m [256]uint8
+	tx := (*tmach_semcreatemsg)(unsafe.Pointer(&m))
+	rx := (*rmach_semcreatemsg)(unsafe.Pointer(&m))
+
+	tx.h.msgh_bits = 0
+	tx.h.msgh_size = uint32(unsafe.Sizeof(*tx))
+	tx.h.msgh_remote_port = mach_task_self()
+	tx.h.msgh_id = tmach_semcreate
+	tx.ndr = zerondr
+
+	tx.policy = 0 // 0 = SYNC_POLICY_FIFO
+	tx.value = 0
+
+	for {
+		r := machcall(&tx.h, int32(unsafe.Sizeof(m)), int32(unsafe.Sizeof(*rx)))
+		if r == 0 {
+			break
+		}
+		if r == _KERN_ABORTED { // interrupted
+			continue
+		}
+		macherror(r, "semaphore_create")
+	}
+	if rx.body.msgh_descriptor_count != 1 {
+		unimplemented("mach_semcreate desc count")
+	}
+	return rx.semaphore.name
+}
+
+func mach_semdestroy(sem uint32) {
+	var m [256]uint8
+	tx := (*tmach_semdestroymsg)(unsafe.Pointer(&m))
+
+	tx.h.msgh_bits = _MACH_MSGH_BITS_COMPLEX
+	tx.h.msgh_size = uint32(unsafe.Sizeof(*tx))
+	tx.h.msgh_remote_port = mach_task_self()
+	tx.h.msgh_id = tmach_semdestroy
+	tx.body.msgh_descriptor_count = 1
+	tx.semaphore.name = sem
+	tx.semaphore.disposition = _MACH_MSG_TYPE_MOVE_SEND
+	tx.semaphore._type = 0
+
+	for {
+		r := machcall(&tx.h, int32(unsafe.Sizeof(m)), 0)
+		if r == 0 {
+			break
+		}
+		if r == _KERN_ABORTED { // interrupted
+			continue
+		}
+		macherror(r, "semaphore_destroy")
+	}
+}
+
+//extern semaphore_wait
+func mach_semaphore_wait(sema uint32) int32
+
+//extern semaphore_timedwait
+func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
+
+//extern semaphore_signal
+func mach_semaphore_signal(sema uint32) int32
+
+//extern semaphore_signal_all
+func mach_semaphore_signal_all(sema uint32) int32
+
+func semasleep1(ns int64) int32 {
+	_g_ := getg()
+
+	if ns >= 0 {
+		var nsecs int32
+		secs := timediv(ns, 1000000000, &nsecs)
+		r := mach_semaphore_timedwait(_g_.m.mos.waitsema, uint32(secs), uint32(nsecs))
+		if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT {
+			return -1
+		}
+		if r != 0 {
+			macherror(r, "semaphore_wait")
+		}
+		return 0
+	}
+
+	for {
+		r := mach_semaphore_wait(_g_.m.mos.waitsema)
+		if r == 0 {
+			break
+		}
+		if r == _KERN_ABORTED { // interrupted
+			continue
+		}
+		macherror(r, "semaphore_wait")
+	}
+	return 0
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+	var r int32
+	systemstack(func() {
+		r = semasleep1(ns)
+	})
+	return r
+}
+
+//go:nosplit
+func mach_semrelease(sem uint32) {
+	for {
+		r := mach_semaphore_signal(sem)
+		if r == 0 {
+			break
+		}
+		if r == _KERN_ABORTED { // interrupted
+			continue
+		}
+
+		// mach_semrelease must be completely nosplit,
+		// because it is called from Go code.
+		// If we're going to die, start that process on the system stack
+		// to avoid a Go stack split.
+		systemstack(func() { macherror(r, "semaphore_signal") })
+	}
+}
+
+type machheader struct {
+	msgh_bits        uint32
+	msgh_size        uint32
+	msgh_remote_port uint32
+	msgh_local_port  uint32
+	msgh_reserved    uint32
+	msgh_id          int32
+}
+
+type machndr struct {
+	mig_vers     uint8
+	if_vers      uint8
+	reserved1    uint8
+	mig_encoding uint8
+	int_rep      uint8
+	char_rep     uint8
+	float_rep    uint8
+	reserved2    uint8
+}
Index: libgo/go/runtime/os_dragonfly.go
===================================================================
--- libgo/go/runtime/os_dragonfly.go	(revision 0)
+++ libgo/go/runtime/os_dragonfly.go	(working copy)
@@ -0,0 +1,62 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type mOS struct {
+	unused byte
+}
+
+//go:noescape
+//extern umtx_sleep
+func sys_umtx_sleep(addr *uint32, val, timeout int32) int32
+
+//go:noescape
+//extern umtx_wakeup
+func sys_umtx_wakeup(addr *uint32, val int32) int32
+
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+	systemstack(func() {
+		futexsleep1(addr, val, ns)
+	})
+}
+
+func futexsleep1(addr *uint32, val uint32, ns int64) {
+	var timeout int32
+	if ns >= 0 {
+		// The timeout is specified in microseconds - ensure that we
+		// do not end up dividing to zero, which would put us to sleep
+		// indefinitely...
+		timeout = timediv(ns, 1000, nil)
+		if timeout == 0 {
+			timeout = 1
+		}
+	}
+
+	// sys_umtx_sleep will return EWOULDBLOCK (EAGAIN) when the timeout
+	// expires or EBUSY if the mutex value does not match.
+	ret := sys_umtx_sleep(addr, int32(val), timeout)
+	if ret >= 0 || ret == -_EINTR || ret == -_EAGAIN || ret == -_EBUSY {
+		return
+	}
+
+	print("umtx_sleep addr=", addr, " val=", val, " ret=", ret, "\n")
+	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
+}
+
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+	ret := sys_umtx_wakeup(addr, int32(cnt))
+	if ret >= 0 {
+		return
+	}
+
+	systemstack(func() {
+		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
+		*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
+	})
+}
Index: libgo/go/runtime/os_freebsd.go
===================================================================
--- libgo/go/runtime/os_freebsd.go	(revision 0)
+++ libgo/go/runtime/os_freebsd.go	(working copy)
@@ -0,0 +1,56 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+	"unsafe"
+)
+
+type mOS struct {
+	unused byte
+}
+
+//go:noescape
+//extern _umtx_op
+func sys_umtx_op(addr *uint32, mode int32, val uint32, ptr2, ts *timespec) int32
+
+// FreeBSD's umtx_op syscall is effectively the same as Linux's futex, and
+// thus the code is largely similar. See Linux implementation
+// and lock_futex.go for comments.
+
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+	systemstack(func() {
+		futexsleep1(addr, val, ns)
+	})
+}
+
+func futexsleep1(addr *uint32, val uint32, ns int64) {
+	var tsp *timespec
+	if ns >= 0 {
+		var ts timespec
+		ts.tv_nsec = 0
+		ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
+		tsp = &ts
+	}
+	ret := sys_umtx_op(addr, _UMTX_OP_WAIT_UINT_PRIVATE, val, nil, tsp)
+	if ret >= 0 || ret == -_EINTR {
+		return
+	}
+	print("umtx_wait addr=", addr, " val=", val, " ret=", ret, "\n")
+	*(*int32)(unsafe.Pointer(uintptr(0x1005))) = 0x1005
+}
+
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+	ret := sys_umtx_op(addr, _UMTX_OP_WAKE_PRIVATE, cnt, nil, nil)
+	if ret >= 0 {
+		return
+	}
+
+	systemstack(func() {
+		print("umtx_wake_addr=", addr, " ret=", ret, "\n")
+	})
+}
Index: libgo/go/runtime/os_linux.go
===================================================================
--- libgo/go/runtime/os_linux.go	(revision 240609)
+++ libgo/go/runtime/os_linux.go	(working copy)
@@ -9,6 +9,80 @@ import (
 	"unsafe"
 )
 
+type mOS struct {
+	unused byte
+}
+
+func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32 {
+	return int32(syscall(_SYS_futex, uintptr(addr), uintptr(op), uintptr(val), uintptr(ts), uintptr(addr2), uintptr(val3)))
+}
+
+// Linux futex.
+//
+//	futexsleep(uint32 *addr, uint32 val)
+//	futexwakeup(uint32 *addr)
+//
+// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
+// Futexwakeup wakes up threads sleeping on addr.
+// Futexsleep is allowed to wake up spuriously.
+
+const (
+	_FUTEX_WAIT = 0
+	_FUTEX_WAKE = 1
+)
+
+// Atomically,
+//	if(*addr == val) sleep
+// Might be woken up spuriously; that's allowed.
+// Don't sleep longer than ns; ns < 0 means forever.
+//go:nosplit
+func futexsleep(addr *uint32, val uint32, ns int64) {
+	var ts timespec
+
+	// Some Linux kernels have a bug where futex of
+	// FUTEX_WAIT returns an internal error code
+	// as an errno. Libpthread ignores the return value
+	// here, and so can we: as it says a few lines up,
+	// spurious wakeups are allowed.
+	if ns < 0 {
+		futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, nil, nil, 0)
+		return
+	}
+
+	// It's difficult to live within the no-split stack limits here.
+	// On ARM and 386, a 64-bit divide invokes a general software routine
+	// that needs more stack than we can afford. So we use timediv instead.
+	// But on real 64-bit systems, where words are larger but the stack limit
+	// is not, even timediv is too heavy, and we really need to use just an
+	// ordinary machine instruction.
+	if sys.PtrSize == 8 {
+		ts.set_sec(ns / 1000000000)
+		ts.set_nsec(int32(ns % 1000000000))
+	} else {
+		ts.tv_nsec = 0
+		ts.set_sec(int64(timediv(ns, 1000000000, (*int32)(unsafe.Pointer(&ts.tv_nsec)))))
+	}
+	futex(unsafe.Pointer(addr), _FUTEX_WAIT, val, unsafe.Pointer(&ts), nil, 0)
+}
+
+// If any procs are sleeping on addr, wake up at most cnt.
+//go:nosplit
+func futexwakeup(addr *uint32, cnt uint32) {
+	ret := futex(unsafe.Pointer(addr), _FUTEX_WAKE, cnt, nil, nil, 0)
+	if ret >= 0 {
+		return
+	}
+
+	// I don't know that futex wakeup can return
+	// EAGAIN or EINTR, but if it does, it would be
+	// safe to loop and call futex again.
+	systemstack(func() {
+		print("futexwakeup addr=", addr, " returned ", ret, "\n")
+	})
+
+	*(*int32)(unsafe.Pointer(uintptr(0x1006))) = 0x1006
+}
+
 const (
 	_AT_NULL   = 0  // End of vector
 	_AT_PAGESZ = 6  // System physical page size
Index: libgo/go/runtime/os_netbsd.go
===================================================================
--- libgo/go/runtime/os_netbsd.go	(revision 0)
+++ libgo/go/runtime/os_netbsd.go	(working copy)
@@ -0,0 +1,73 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
+
+type mOS struct {
+	waitsemacount uint32
+}
+
+//go:noescape
+//extern lwp_park
+func lwp_park(abstime *timespec, unpark int32, hint, unparkhint unsafe.Pointer) int32
+
+//go:noescape
+//extern lwp_unpark
+func lwp_unpark(lwp int32, hint unsafe.Pointer) int32
+
+//go:nosplit
+func semacreate(mp *m) {
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+	_g_ := getg()
+
+	// Compute sleep deadline.
+	var tsp *timespec
+	if ns >= 0 {
+		var ts timespec
+		var nsec int32
+		ns += nanotime()
+		ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
+		ts.set_nsec(nsec)
+		tsp = &ts
+	}
+
+	for {
+		v := atomic.Load(&_g_.m.mos.waitsemacount)
+		if v > 0 {
+			if atomic.Cas(&_g_.m.mos.waitsemacount, v, v-1) {
+				return 0 // semaphore acquired
+			}
+			continue
+		}
+
+		// Sleep until unparked by semawakeup or timeout.
+		ret := lwp_park(tsp, 0, unsafe.Pointer(&_g_.m.mos.waitsemacount), nil)
+		if ret == _ETIMEDOUT {
+			return -1
+		}
+	}
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+	atomic.Xadd(&mp.mos.waitsemacount, 1)
+	// From NetBSD's _lwp_unpark(2) manual:
+	// "If the target LWP is not currently waiting, it will return
+	// immediately upon the next call to _lwp_park()."
+	ret := lwp_unpark(int32(mp.procid), unsafe.Pointer(&mp.mos.waitsemacount))
+	if ret != 0 && ret != _ESRCH {
+		// semawakeup can be called on signal stack.
+		systemstack(func() {
+			print("thrwakeup addr=", &mp.mos.waitsemacount, " sem=", mp.mos.waitsemacount, " ret=", ret, "\n")
+		})
+	}
+}
Index: libgo/go/runtime/os_openbsd.go
===================================================================
--- libgo/go/runtime/os_openbsd.go	(revision 0)
+++ libgo/go/runtime/os_openbsd.go	(working copy)
@@ -0,0 +1,76 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
+
+type mOS struct {
+	waitsemacount uint32
+}
+
+//go:noescape
+//extern thrsleep
+func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32
+
+//go:noescape
+//extern thrwakeup
+func thrwakeup(ident uintptr, n int32) int32
+
+//go:nosplit
+func semacreate(mp *m) {
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+	_g_ := getg()
+
+	// Compute sleep deadline.
+	var tsp *timespec
+	if ns >= 0 {
+		var ts timespec
+		var nsec int32
+		ns += nanotime()
+		ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
+		ts.set_nsec(nsec)
+		tsp = &ts
+	}
+
+	for {
+		v := atomic.Load(&_g_.m.mos.waitsemacount)
+		if v > 0 {
+			if atomic.Cas(&_g_.m.mos.waitsemacount, v, v-1) {
+				return 0 // semaphore acquired
+			}
+			continue
+		}
+
+		// Sleep until woken by semawakeup or timeout; or abort if waitsemacount != 0.
+		//
+		// From OpenBSD's __thrsleep(2) manual:
+		// "The abort argument, if not NULL, points to an int that will
+		// be examined [...] immediately before blocking. If that int
+		// is non-zero then __thrsleep() will immediately return EINTR
+		// without blocking."
+		ret := thrsleep(uintptr(unsafe.Pointer(&_g_.m.mos.waitsemacount)), _CLOCK_MONOTONIC, tsp, 0, &_g_.m.mos.waitsemacount)
+		if ret == _EWOULDBLOCK {
+			return -1
+		}
+	}
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+	atomic.Xadd(&mp.mos.waitsemacount, 1)
+	ret := thrwakeup(uintptr(unsafe.Pointer(&mp.mos.waitsemacount)), 1)
+	if ret != 0 && ret != _ESRCH {
+		// semawakeup can be called on signal stack.
+		systemstack(func() {
+			print("thrwakeup addr=", &mp.mos.waitsemacount, " sem=", mp.mos.waitsemacount, " ret=", ret, "\n")
+		})
+	}
+}
Index: libgo/go/runtime/os_solaris.go
===================================================================
--- libgo/go/runtime/os_solaris.go	(revision 0)
+++ libgo/go/runtime/os_solaris.go	(working copy)
@@ -0,0 +1,85 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime
+
+import "unsafe"
+
+type mOS struct {
+	waitsema uintptr // semaphore for parking on locks
+}
+
+//extern malloc
+func libc_malloc(uintptr) unsafe.Pointer
+
+//go:noescape
+//extern sem_init
+func sem_init(sem *semt, pshared int32, value uint32) int32
+
+//go:noescape
+//extern sem_wait
+func sem_wait(sem *semt) int32
+
+//go:noescape
+//extern sem_post
+func sem_post(sem *semt) int32
+
+//go:noescape
+//extern sem_reltimedwait_np
+func sem_reltimedwait_np(sem *semt, timeout *timespec) int32
+
+//go:nosplit
+func semacreate(mp *m) {
+	if mp.mos.waitsema != 0 {
+		return
+	}
+
+	var sem *semt
+
+	// Call libc's malloc rather than malloc. This will
+	// allocate space on the C heap. We can't call malloc
+	// here because it could cause a deadlock.
+	sem = (*semt)(libc_malloc(unsafe.Sizeof(*sem)))
+	if sem_init(sem, 0, 0) != 0 {
+		throw("sem_init")
+	}
+	mp.mos.waitsema = uintptr(unsafe.Pointer(sem))
+}
+
+//go:nosplit
+func semasleep(ns int64) int32 {
+	_m_ := getg().m
+	if ns >= 0 {
+		var ts timespec
+		ts.set_sec(ns / 1000000000)
+		ts.set_nsec(int32(ns % 1000000000))
+
+		if sem_reltimedwait_np((*semt)(unsafe.Pointer(_m_.mos.waitsema)), &ts) != 0 {
+			err := errno()
+			if err == _ETIMEDOUT || err == _EAGAIN || err == _EINTR {
+				return -1
+			}
+			throw("sem_reltimedwait_np")
+		}
+		return 0
+	}
+	for {
+		r1 := sem_wait((*semt)(unsafe.Pointer(_m_.mos.waitsema)))
+		if r1 == 0 {
+			break
+		}
+		if errno() == _EINTR {
+			continue
+		}
+		throw("sem_wait")
+	}
+	return 0
+}
+
+//go:nosplit
+func semawakeup(mp *m) {
+	if sem_post((*semt)(unsafe.Pointer(mp.mos.waitsema))) != 0 {
+		throw("sem_post")
+	}
+}
Index: libgo/go/runtime/runtime2.go
===================================================================
--- libgo/go/runtime/runtime2.go	(revision 240609)
+++ libgo/go/runtime/runtime2.go	(working copy)
@@ -396,7 +396,7 @@ type g struct {
 	gcnextsegment unsafe.Pointer
 	gcnextsp      unsafe.Pointer
 	gcinitialsp   unsafe.Pointer
-	gcregs        _ucontext_t
+	gcregs        g_ucontext_t
 
 	entry    unsafe.Pointer // goroutine entry point
 	fromgogo bool           // whether entered from gogo function
@@ -406,7 +406,7 @@ type g struct {
 
 	traceback *traceback // stack traceback buffer
 
-	context      _ucontext_t        // saved context for setcontext
+	context      g_ucontext_t       // saved context for setcontext
 	stackcontext [10]unsafe.Pointer // split-stack context
 }
 
@@ -474,7 +474,7 @@ type m struct {
 	// Not for gccgo: libcallg  guintptr
 	// Not for gccgo: syscall   libcall // stores syscall parameters on windows
 
-	// Not for gccgo: mOS
+	mos mOS
 
 	// Remaining fields are specific to gccgo.
 
@@ -485,8 +485,6 @@ type m struct {
 
 	gcing int32
 
-	waitsema uintptr // semaphore on systems that don't use futexes
-
 	cgomal *cgoMal // allocations via _cgo_allocate
 }
 
@@ -771,13 +769,15 @@ const (
 const _TracebackMaxFrames = 100
 
 var (
-//	emptystring string
-//	allglen     uintptr
-//	allm        *m
-//	allp        [_MaxGomaxprocs + 1]*p
-//	gomaxprocs  int32
-//	panicking   uint32
-//	ncpu        int32
+	//	emptystring string
+	//	allglen     uintptr
+	//	allm        *m
+	//	allp        [_MaxGomaxprocs + 1]*p
+	//	gomaxprocs  int32
+	//	panicking   uint32
+
+	ncpu int32
+
 //	forcegc     forcegcstate
 //	sched       schedt
 //	newprocs    int32
@@ -803,13 +803,13 @@ var (
 
 // Types that are only used by gccgo.
 
-// _ucontext_t is a Go version of the C ucontext_t type, used by getcontext.
-// _sizeof_ucontext_t is defined by the Makefile from <ucontext.h>.
+// g_ucontext_t is a Go version of the C ucontext_t type, used by getcontext.
+// _sizeof_ucontext_t is defined by mkrsysinfo.sh from <ucontext.h>.
 // On some systems getcontext and friends require a value that is
 // aligned to a 16-byte boundary.  We implement this by increasing the
 // required size and picking an appropriate offset when we use the
 // array.
-type _ucontext_t [(_sizeof_ucontext_t + 15) / unsafe.Sizeof(unsafe.Pointer(nil))]unsafe.Pointer
+type g_ucontext_t [(_sizeof_ucontext_t + 15) / unsafe.Sizeof(unsafe.Pointer(nil))]unsafe.Pointer
 
 // traceback is used to collect stack traces from other goroutines.
 type traceback struct {
Index: libgo/go/runtime/stubs.go
===================================================================
--- libgo/go/runtime/stubs.go	(revision 240609)
+++ libgo/go/runtime/stubs.go	(working copy)
@@ -38,12 +38,7 @@ func getg() *g
 func mcall(fn func(*g))
 
 // systemstack runs fn on a system stack.
-// If systemstack is called from the per-OS-thread (g0) stack, or
-// if systemstack is called from the signal handling (gsignal) stack,
-// systemstack calls fn directly and returns.
-// Otherwise, systemstack is being called from the limited stack
-// of an ordinary goroutine. In this case, systemstack switches
-// to the per-OS-thread stack, calls fn, and switches back.
+//
 // It is common to use a func literal as the argument, in order
 // to share inputs and outputs with the code around the call
 // to system stack:
@@ -54,8 +49,14 @@ func mcall(fn func(*g))
 //	})
 //	... use x ...
 //
-//go:noescape
-func systemstack(fn func())
+// For the gc toolchain this permits running a function that requires
+// additional stack space in a context where the stack can not be
+// split.  For gccgo, however, stack splitting is not managed by the
+// Go runtime. In effect, all stacks are system stacks. So this gccgo
+// version just runs the function.
+func systemstack(fn func()) {
+	fn()
+}
 
 func badsystemstack() {
 	throw("systemstack called from unexpected goroutine")
@@ -215,6 +216,13 @@ func checkASM() bool {
 	return true
 }
 
+// For gccgo this is in the C code.
+func osyield()
+
+// For gccgo this can be called directly.
+//extern syscall
+func syscall(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr
+
 // throw crashes the program.
 // For gccgo unless and until we port panic.go.
 func throw(string)
@@ -368,3 +376,11 @@ func casp(ptr *unsafe.Pointer, old, new
 // Here for gccgo until we port lock_*.go.
 func lock(l *mutex)
 func unlock(l *mutex)
+
+// Here for gccgo for Solaris.
+func errno() int
+
+// Temporary for gccgo until we port proc.go.
+func entersyscall(int32)
+func entersyscallblock(int32)
+func exitsyscall(int32)
Index: libgo/mkrsysinfo.sh
===================================================================
--- libgo/mkrsysinfo.sh	(revision 0)
+++ libgo/mkrsysinfo.sh	(working copy)
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+# Copyright 2016 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Create runtime_sysinfo.go from gen-sysinfo.go and errno.i.
+
+OUT=tmp-runtime_sysinfo.go
+
+set -e
+
+echo 'package runtime' > ${OUT}
+
+# Get all the consts and types, skipping ones which could not be
+# represented in Go and ones which we need to rewrite.  We also skip
+# function declarations, as we don't need them here.  All the symbols
+# will all have a leading underscore.
+grep -v '^// ' gen-sysinfo.go | \
+  grep -v '^func' | \
+  grep -v '^type _timeval ' | \
+  grep -v '^type _timespec_t ' | \
+  grep -v '^type _timespec ' | \
+  grep -v '^type _epoll_' | \
+  grep -v 'in6_addr' | \
+  grep -v 'sockaddr_in6' | \
+  sed -e 's/\([^a-zA-Z0-9_]\)_timeval\([^a-zA-Z0-9_]\)/\1timeval\2/g' \
+      -e 's/\([^a-zA-Z0-9_]\)_timespec_t\([^a-zA-Z0-9_]\)/\1timespec\2/g' \
+      -e 's/\([^a-zA-Z0-9_]\)_timespec\([^a-zA-Z0-9_]\)/\1timespec\2/g' \
+    >> ${OUT}
+
+# The time structures need special handling: we need to name the
+# types, so that we can cast integers to the right types when
+# assigning to the structures.
+timeval=`grep '^type _timeval ' gen-sysinfo.go`
+timeval_sec=`echo $timeval | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
+timeval_usec=`echo $timeval | sed -n -e 's/^.*tv_usec \([^ ]*\);.*$/\1/p'`
+echo "type timeval_sec_t $timeval_sec" >> ${OUT}
+echo "type timeval_usec_t $timeval_usec" >> ${OUT}
+echo $timeval | \
+  sed -e 's/type _timeval /type timeval /' \
+      -e 's/tv_sec *[a-zA-Z0-9_]*/tv_sec timeval_sec_t/' \
+      -e 's/tv_usec *[a-zA-Z0-9_]*/tv_usec timeval_usec_t/' >> ${OUT}
+timespec=`grep '^type _timespec ' gen-sysinfo.go || true`
+if test "$timespec" = ""; then
+  # IRIX 6.5 has __timespec instead.
+  timespec=`grep '^type ___timespec ' gen-sysinfo.go || true`
+fi
+timespec_sec=`echo $timespec | sed -n -e 's/^.*tv_sec \([^ ]*\);.*$/\1/p'`
+timespec_nsec=`echo $timespec | sed -n -e 's/^.*tv_nsec \([^ ]*\);.*$/\1/p'`
+echo "type timespec_sec_t $timespec_sec" >> ${OUT}
+echo "type timespec_nsec_t $timespec_nsec" >> ${OUT}
+echo $timespec | \
+  sed -e 's/^type ___timespec /type timespec /' \
+      -e 's/^type _timespec /type timespec /' \
+      -e 's/tv_sec *[a-zA-Z0-9_]*/tv_sec timespec_sec_t/' \
+      -e 's/tv_nsec *[a-zA-Z0-9_]*/tv_nsec timespec_nsec_t/' >> ${OUT}
+echo >> ${OUT}
+echo "func (ts *timespec) set_sec(x int64) {" >> ${OUT}
+echo "	ts.tv_sec = timespec_sec_t(x)" >> ${OUT}
+echo "}" >> ${OUT}
+echo >> ${OUT}
+echo "func (ts *timespec) set_nsec(x int32) {" >> ${OUT}
+echo "	ts.tv_nsec = timespec_nsec_t(x)" >> ${OUT}
+echo "}" >> ${OUT}
+
+# The semt structure, for Solaris.
+grep '^type _sem_t ' gen-sysinfo.go | \
+    sed -e 's/_sem_t/semt/' >> ${OUT}
+
+# Solaris 2 needs _u?pad128_t, but its default definition in terms of long
+# double is commented by -fdump-go-spec.
+if grep "^// type _pad128_t" gen-sysinfo.go > /dev/null 2>&1; then
+  echo "type _pad128_t struct { _l [4]int32; }" >> ${OUT}
+fi
+if grep "^// type _upad128_t" gen-sysinfo.go > /dev/null 2>&1; then
+  echo "type _upad128_t struct { _l [4]uint32; }" >> ${OUT}
+fi
+
+# The Solaris 11 Update 1 _zone_net_addr_t struct.
+grep '^type _zone_net_addr_t ' gen-sysinfo.go | \
+    sed -e 's/_in6_addr/[16]byte/' \
+    >> ${OUT}
+
+# The Solaris 12 _flow_arp_desc_t struct.
+grep '^type _flow_arp_desc_t ' gen-sysinfo.go | \
+    sed -e 's/_in6_addr_t/[16]byte/g' \
+    >> ${OUT}
+
+# The Solaris 12 _flow_l3_desc_t struct.
+grep '^type _flow_l3_desc_t ' gen-sysinfo.go | \
+    sed -e 's/_in6_addr_t/[16]byte/g' \
+    >> ${OUT}
+
+# The Solaris 12 _mac_ipaddr_t struct.
+grep '^type _mac_ipaddr_t ' gen-sysinfo.go | \
+    sed -e 's/_in6_addr_t/[16]byte/g' \
+    >> ${OUT}
+
+# The Solaris 12 _mactun_info_t struct.
+grep '^type _mactun_info_t ' gen-sysinfo.go | \
+    sed -e 's/_in6_addr_t/[16]byte/g' \
+    >> ${OUT}

Property changes on: libgo/mkrsysinfo.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: libgo/runtime/go-cgo.c
===================================================================
--- libgo/runtime/go-cgo.c	(revision 240053)
+++ libgo/runtime/go-cgo.c	(working copy)
@@ -45,7 +45,7 @@ syscall_cgocall ()
   m = runtime_m ();
   ++m->ncgocall;
   ++m->ncgo;
-  runtime_entersyscall ();
+  runtime_entersyscall (0);
 }
 
 /* Prepare to return to Go code from C/C++ code.  */
@@ -69,7 +69,7 @@ syscall_cgocalldone ()
   /* If we are invoked because the C function called _cgo_panic, then
      _cgo_panic will already have exited syscall mode.  */
   if (g->atomicstatus == _Gsyscall)
-    runtime_exitsyscall ();
+    runtime_exitsyscall (0);
 
   runtime_unlockOSThread();
 }
@@ -89,7 +89,7 @@ syscall_cgocallback ()
       mp->dropextram = true;
     }
 
-  runtime_exitsyscall ();
+  runtime_exitsyscall (0);
 
   if (runtime_m ()->ncgo == 0)
     {
@@ -115,7 +115,7 @@ syscall_cgocallbackdone ()
 {
   M *mp;
 
-  runtime_entersyscall ();
+  runtime_entersyscall (0);
   mp = runtime_m ();
   if (mp->dropextram && mp->ncgo == 0)
     {
@@ -154,9 +154,9 @@ _cgo_allocate (size_t n)
 {
   void *ret;
 
-  runtime_exitsyscall ();
+  runtime_exitsyscall (0);
   ret = alloc_saved (n);
-  runtime_entersyscall ();
+  runtime_entersyscall (0);
   return ret;
 }
 
@@ -171,7 +171,7 @@ _cgo_panic (const char *p)
   String *ps;
   struct __go_empty_interface e;
 
-  runtime_exitsyscall ();
+  runtime_exitsyscall (0);
   len = __builtin_strlen (p);
   data = alloc_saved (len);
   __builtin_memcpy (data, p, len);
Index: libgo/runtime/lock_futex.c
===================================================================
--- libgo/runtime/lock_futex.c	(revision 240053)
+++ libgo/runtime/lock_futex.c	(working copy)
@@ -1,204 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build dragonfly freebsd linux
-
-#include "runtime.h"
-
-// This implementation depends on OS-specific implementations of
-//
-//	runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
-//		Atomically,
-//			if(*addr == val) sleep
-//		Might be woken up spuriously; that's allowed.
-//		Don't sleep longer than ns; ns < 0 means forever.
-//
-//	runtime_futexwakeup(uint32 *addr, uint32 cnt)
-//		If any procs are sleeping on addr, wake up at most cnt.
-
-enum
-{
-	MUTEX_UNLOCKED = 0,
-	MUTEX_LOCKED = 1,
-	MUTEX_SLEEPING = 2,
-
-	ACTIVE_SPIN = 4,
-	ACTIVE_SPIN_CNT = 30,
-	PASSIVE_SPIN = 1,
-};
-
-// Possible lock states are MUTEX_UNLOCKED, MUTEX_LOCKED and MUTEX_SLEEPING.
-// MUTEX_SLEEPING means that there is presumably at least one sleeping thread.
-// Note that there can be spinning threads during all states - they do not
-// affect mutex's state.
-void
-runtime_lock(Lock *l)
-{
-	uint32 i, v, wait, spin;
-
-	if(runtime_m()->locks++ < 0)
-		runtime_throw("runtime_lock: lock count");
-
-	// Speculative grab for lock.
-	v = runtime_xchg((uint32*)&l->key, MUTEX_LOCKED);
-	if(v == MUTEX_UNLOCKED)
-		return;
-
-	// wait is either MUTEX_LOCKED or MUTEX_SLEEPING
-	// depending on whether there is a thread sleeping
-	// on this mutex.  If we ever change l->key from
-	// MUTEX_SLEEPING to some other value, we must be
-	// careful to change it back to MUTEX_SLEEPING before
-	// returning, to ensure that the sleeping thread gets
-	// its wakeup call.
-	wait = v;
-
-	// On uniprocessor's, no point spinning.
-	// On multiprocessors, spin for ACTIVE_SPIN attempts.
-	spin = 0;
-	if(runtime_ncpu > 1)
-		spin = ACTIVE_SPIN;
-
-	for(;;) {
-		// Try for lock, spinning.
-		for(i = 0; i < spin; i++) {
-			while(l->key == MUTEX_UNLOCKED)
-				if(runtime_cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
-					return;
-			runtime_procyield(ACTIVE_SPIN_CNT);
-		}
-
-		// Try for lock, rescheduling.
-		for(i=0; i < PASSIVE_SPIN; i++) {
-			while(l->key == MUTEX_UNLOCKED)
-				if(runtime_cas((uint32*)&l->key, MUTEX_UNLOCKED, wait))
-					return;
-			runtime_osyield();
-		}
-
-		// Sleep.
-		v = runtime_xchg((uint32*)&l->key, MUTEX_SLEEPING);
-		if(v == MUTEX_UNLOCKED)
-			return;
-		wait = MUTEX_SLEEPING;
-		runtime_futexsleep((uint32*)&l->key, MUTEX_SLEEPING, -1);
-	}
-}
-
-void
-runtime_unlock(Lock *l)
-{
-	uint32 v;
-
-	v = runtime_xchg((uint32*)&l->key, MUTEX_UNLOCKED);
-	if(v == MUTEX_UNLOCKED)
-		runtime_throw("unlock of unlocked lock");
-	if(v == MUTEX_SLEEPING)
-		runtime_futexwakeup((uint32*)&l->key, 1);
-
-	if(--runtime_m()->locks < 0)
-		runtime_throw("runtime_unlock: lock count");
-}
-
-// One-time notifications.
-void
-runtime_noteclear(Note *n)
-{
-	n->key = 0;
-}
-
-void
-runtime_notewakeup(Note *n)
-{
-	uint32 old;
-
-	old = runtime_xchg((uint32*)&n->key, 1);
-	if(old != 0) {
-		runtime_printf("notewakeup - double wakeup (%d)\n", old);
-		runtime_throw("notewakeup - double wakeup");
-	}
-	runtime_futexwakeup((uint32*)&n->key, 1);
-}
-
-void
-runtime_notesleep(Note *n)
-{
-	M *m = runtime_m();
-
-  /* For gccgo it's OK to sleep in non-g0, and it happens in
-     stoptheworld because we have not implemented preemption.
-
-	if(runtime_g() != runtime_m()->g0)
-		runtime_throw("notesleep not on g0");
-  */
-	while(runtime_atomicload((uint32*)&n->key) == 0) {
-		m->blocked = true;
-		runtime_futexsleep((uint32*)&n->key, 0, -1);
-		m->blocked = false;
-	}
-}
-
-static bool
-notetsleep(Note *n, int64 ns, int64 deadline, int64 now)
-{
-	M *m = runtime_m();
-
-	// Conceptually, deadline and now are local variables.
-	// They are passed as arguments so that the space for them
-	// does not count against our nosplit stack sequence.
-
-	if(ns < 0) {
-		while(runtime_atomicload((uint32*)&n->key) == 0) {
-			m->blocked = true;
-			runtime_futexsleep((uint32*)&n->key, 0, -1);
-			m->blocked = false;
-		}
-		return true;
-	}
-
-	if(runtime_atomicload((uint32*)&n->key) != 0)
-		return true;
-
-	deadline = runtime_nanotime() + ns;
-	for(;;) {
-		m->blocked = true;
-		runtime_futexsleep((uint32*)&n->key, 0, ns);
-		m->blocked = false;
-		if(runtime_atomicload((uint32*)&n->key) != 0)
-			break;
-		now = runtime_nanotime();
-		if(now >= deadline)
-			break;
-		ns = deadline - now;
-	}
-	return runtime_atomicload((uint32*)&n->key) != 0;
-}
-
-bool
-runtime_notetsleep(Note *n, int64 ns)
-{
-	bool res;
-
-	if(runtime_g() != runtime_m()->g0 && !runtime_m()->gcing)
-		runtime_throw("notetsleep not on g0");
-
-	res = notetsleep(n, ns, 0, 0);
-	return res;
-}
-
-// same as runtime_notetsleep, but called on user g (not g0)
-// calls only nosplit functions between entersyscallblock/exitsyscall
-bool
-runtime_notetsleepg(Note *n, int64 ns)
-{
-	bool res;
-
-	if(runtime_g() == runtime_m()->g0)
-		runtime_throw("notetsleepg on g0");
-
-	runtime_entersyscallblock();
-	res = notetsleep(n, ns, 0, 0);
-	runtime_exitsyscall();
-	return res;
-}
Index: libgo/runtime/lock_sema.c
===================================================================
--- libgo/runtime/lock_sema.c	(revision 240053)
+++ libgo/runtime/lock_sema.c	(working copy)
@@ -1,281 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build darwin nacl netbsd openbsd plan9 solaris windows
-
-#include "runtime.h"
-
-// This implementation depends on OS-specific implementations of
-//
-//	uintptr runtime_semacreate(void)
-//		Create a semaphore, which will be assigned to m->waitsema.
-//		The zero value is treated as absence of any semaphore,
-//		so be sure to return a non-zero value.
-//
-//	int32 runtime_semasleep(int64 ns)
-//		If ns < 0, acquire m->waitsema and return 0.
-//		If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds.
-//		Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
-//
-//	int32 runtime_semawakeup(M *mp)
-//		Wake up mp, which is or will soon be sleeping on mp->waitsema.
-//
-
-enum
-{
-	LOCKED = 1,
-
-	ACTIVE_SPIN = 4,
-	ACTIVE_SPIN_CNT = 30,
-	PASSIVE_SPIN = 1,
-};
-
-void
-runtime_lock(Lock *l)
-{
-	M *m;
-	uintptr v;
-	uint32 i, spin;
-
-	m = runtime_m();
-	if(m->locks++ < 0)
-		runtime_throw("runtime_lock: lock count");
-
-	// Speculative grab for lock.
-	if(runtime_casp((void**)&l->key, nil, (void*)LOCKED))
-		return;
-
-	if(m->waitsema == 0)
-		m->waitsema = runtime_semacreate();
-
-	// On uniprocessor's, no point spinning.
-	// On multiprocessors, spin for ACTIVE_SPIN attempts.
-	spin = 0;
-	if(runtime_ncpu > 1)
-		spin = ACTIVE_SPIN;
-
-	for(i=0;; i++) {
-		v = (uintptr)runtime_atomicloadp((void**)&l->key);
-		if((v&LOCKED) == 0) {
-unlocked:
-			if(runtime_casp((void**)&l->key, (void*)v, (void*)(v|LOCKED)))
-				return;
-			i = 0;
-		}
-		if(i<spin)
-			runtime_procyield(ACTIVE_SPIN_CNT);
-		else if(i<spin+PASSIVE_SPIN)
-			runtime_osyield();
-		else {
-			// Someone else has it.
-			// l->waitm points to a linked list of M's waiting
-			// for this lock, chained through m->nextwaitm.
-			// Queue this M.
-			for(;;) {
-				m->nextwaitm = v&~LOCKED;
-				if(runtime_casp((void**)&l->key, (void*)v, (void*)((uintptr)m|LOCKED)))
-					break;
-				v = (uintptr)runtime_atomicloadp((void**)&l->key);
-				if((v&LOCKED) == 0)
-					goto unlocked;
-			}
-			if(v&LOCKED) {
-				// Queued.  Wait.
-				runtime_semasleep(-1);
-				i = 0;
-			}
-		}
-	}
-}
-
-void
-runtime_unlock(Lock *l)
-{
-	uintptr v;
-	M *mp;
-
-	for(;;) {
-		v = (uintptr)runtime_atomicloadp((void**)&l->key);
-		if(v == LOCKED) {
-			if(runtime_casp((void**)&l->key, (void*)LOCKED, nil))
-				break;
-		} else {
-			// Other M's are waiting for the lock.
-			// Dequeue an M.
-			mp = (void*)(v&~LOCKED);
-			if(runtime_cas(&l->key, v, mp->nextwaitm)) {
-				// Dequeued an M.  Wake it.
-				runtime_semawakeup(mp);
-				break;
-			}
-		}
-	}
-
-	if(--runtime_m()->locks < 0)
-		runtime_throw("runtime_unlock: lock count");
-}
-
-// One-time notifications.
-void
-runtime_noteclear(Note *n)
-{
-	n->key = 0;
-}
-
-void
-runtime_notewakeup(Note *n)
-{
-	M *mp;
-
-	do
-		mp = runtime_atomicloadp((void**)&n->key);
-	while(!runtime_casp((void**)&n->key, mp, (void*)LOCKED));
-
-	// Successfully set waitm to LOCKED.
-	// What was it before?
-	if(mp == nil) {
-		// Nothing was waiting.  Done.
-	} else if(mp == (M*)LOCKED) {
-		// Two notewakeups!  Not allowed.
-		runtime_throw("notewakeup - double wakeup");
-	} else {
-		// Must be the waiting m.  Wake it up.
-		runtime_semawakeup(mp);
-	}
-}
-
-void
-runtime_notesleep(Note *n)
-{
-	M *m;
-
-	m = runtime_m();
-
-  /* For gccgo it's OK to sleep in non-g0, and it happens in
-     stoptheworld because we have not implemented preemption.
-
-	if(runtime_g() != m->g0)
-		runtime_throw("notesleep not on g0");
-  */
-
-	if(m->waitsema == 0)
-		m->waitsema = runtime_semacreate();
-	if(!runtime_casp((void**)&n->key, nil, m)) {  // must be LOCKED (got wakeup)
-		if(n->key != LOCKED)
-			runtime_throw("notesleep - waitm out of sync");
-		return;
-	}
-	// Queued.  Sleep.
-	m->blocked = true;
-	runtime_semasleep(-1);
-	m->blocked = false;
-}
-
-static bool
-notetsleep(Note *n, int64 ns, int64 deadline, M *mp)
-{
-	M *m;
-
-	m = runtime_m();
-
-	// Conceptually, deadline and mp are local variables.
-	// They are passed as arguments so that the space for them
-	// does not count against our nosplit stack sequence.
-
-	// Register for wakeup on n->waitm.
-	if(!runtime_casp((void**)&n->key, nil, m)) {  // must be LOCKED (got wakeup already)
-		if(n->key != LOCKED)
-			runtime_throw("notetsleep - waitm out of sync");
-		return true;
-	}
-
-	if(ns < 0) {
-		// Queued.  Sleep.
-		m->blocked = true;
-		runtime_semasleep(-1);
-		m->blocked = false;
-		return true;
-	}
-
-	deadline = runtime_nanotime() + ns;
-	for(;;) {
-		// Registered.  Sleep.
-		m->blocked = true;
-		if(runtime_semasleep(ns) >= 0) {
-			m->blocked = false;
-			// Acquired semaphore, semawakeup unregistered us.
-			// Done.
-			return true;
-		}
-		m->blocked = false;
-
-		// Interrupted or timed out.  Still registered.  Semaphore not acquired.
-		ns = deadline - runtime_nanotime();
-		if(ns <= 0)
-			break;
-		// Deadline hasn't arrived.  Keep sleeping.
-	}
-
-	// Deadline arrived.  Still registered.  Semaphore not acquired.
-	// Want to give up and return, but have to unregister first,
-	// so that any notewakeup racing with the return does not
-	// try to grant us the semaphore when we don't expect it.
-	for(;;) {
-		mp = runtime_atomicloadp((void**)&n->key);
-		if(mp == m) {
-			// No wakeup yet; unregister if possible.
-			if(runtime_casp((void**)&n->key, mp, nil))
-				return false;
-		} else if(mp == (M*)LOCKED) {
-			// Wakeup happened so semaphore is available.
-			// Grab it to avoid getting out of sync.
-			m->blocked = true;
-			if(runtime_semasleep(-1) < 0)
-				runtime_throw("runtime: unable to acquire - semaphore out of sync");
-			m->blocked = false;
-			return true;
-		} else
-			runtime_throw("runtime: unexpected waitm - semaphore out of sync");
-	}
-}
-
-bool
-runtime_notetsleep(Note *n, int64 ns)
-{
-	M *m;
-	bool res;
-
-	m = runtime_m();
-
-	if(runtime_g() != m->g0 && !m->gcing)
-		runtime_throw("notetsleep not on g0");
-
-	if(m->waitsema == 0)
-		m->waitsema = runtime_semacreate();
-
-	res = notetsleep(n, ns, 0, nil);
-	return res;
-}
-
-// same as runtime_notetsleep, but called on user g (not g0)
-// calls only nosplit functions between entersyscallblock/exitsyscall
-bool
-runtime_notetsleepg(Note *n, int64 ns)
-{
-	M *m;
-	bool res;
-
-	m = runtime_m();
-
-	if(runtime_g() == m->g0)
-		runtime_throw("notetsleepg on g0");
-
-	if(m->waitsema == 0)
-		m->waitsema = runtime_semacreate();
-
-	runtime_entersyscallblock();
-	res = notetsleep(n, ns, 0, nil);
-	runtime_exitsyscall();
-	return res;
-}
Index: libgo/runtime/malloc.goc
===================================================================
--- libgo/runtime/malloc.goc	(revision 240334)
+++ libgo/runtime/malloc.goc	(working copy)
@@ -99,7 +99,7 @@ runtime_mallocgc(uintptr size, uintptr t
 		// returns a non-pointer, so memory allocation occurs
 		// after syscall.Cgocall but before syscall.CgocallDone.
 		// We treat it as a callback.
-		runtime_exitsyscall();
+		runtime_exitsyscall(0);
 		m = runtime_m();
 		incallback = true;
 		flag |= FlagNoInvokeGC;
@@ -171,7 +171,7 @@ runtime_mallocgc(uintptr size, uintptr t
 					m->mallocing = 0;
 					m->locks--;
 					if(incallback)
-						runtime_entersyscall();
+						runtime_entersyscall(0);
 					return v;
 				}
 			}
@@ -256,7 +256,7 @@ runtime_mallocgc(uintptr size, uintptr t
 		runtime_gc(0);
 
 	if(incallback)
-		runtime_entersyscall();
+		runtime_entersyscall(0);
 
 	return v;
 }
Index: libgo/runtime/proc.c
===================================================================
--- libgo/runtime/proc.c	(revision 240334)
+++ libgo/runtime/proc.c	(working copy)
@@ -2021,11 +2021,11 @@ goexit0(G *gp)
 // make g->sched refer to the caller's stack segment, because
 // entersyscall is going to return immediately after.
 
-void runtime_entersyscall(void) __attribute__ ((no_split_stack));
+void runtime_entersyscall(int32) __attribute__ ((no_split_stack));
 static void doentersyscall(void) __attribute__ ((no_split_stack, noinline));
 
 void
-runtime_entersyscall()
+runtime_entersyscall(int32 dummy __attribute__ ((unused)))
 {
 	// Save the registers in the g structure so that any pointers
 	// held in registers will be seen by the garbage collector.
@@ -2095,7 +2095,7 @@ doentersyscall()
 
 // The same as runtime_entersyscall(), but with a hint that the syscall is blocking.
 void
-runtime_entersyscallblock(void)
+runtime_entersyscallblock(int32 dummy __attribute__ ((unused)))
 {
 	P *p;
 
@@ -2133,7 +2133,7 @@ runtime_entersyscallblock(void)
 // This is called only from the go syscall library, not
 // from the low-level system calls used by the runtime.
 void
-runtime_exitsyscall(void)
+runtime_exitsyscall(int32 dummy __attribute__ ((unused)))
 {
 	G *gp;
 
@@ -2254,6 +2254,28 @@ exitsyscall0(G *gp)
 	schedule();  // Never returns.
 }
 
+void syscall_entersyscall(void)
+  __asm__(GOSYM_PREFIX "syscall.Entersyscall");
+
+void syscall_entersyscall(void) __attribute__ ((no_split_stack));
+
+void
+syscall_entersyscall()
+{
+  runtime_entersyscall(0);
+}
+
+void syscall_exitsyscall(void)
+  __asm__(GOSYM_PREFIX "syscall.Exitsyscall");
+
+void syscall_exitsyscall(void) __attribute__ ((no_split_stack));
+
+void
+syscall_exitsyscall()
+{
+  runtime_exitsyscall(0);
+}
+
 // Called from syscall package before fork.
 void syscall_runtime_BeforeFork(void)
   __asm__(GOSYM_PREFIX "syscall.runtime_BeforeFork");
@@ -2323,33 +2345,6 @@ runtime_malg(int32 stacksize, byte** ret
 	return newg;
 }
 
-/* For runtime package testing.  */
-
-
-// Create a new g running fn with siz bytes of arguments.
-// Put it on the queue of g's waiting to run.
-// The compiler turns a go statement into a call to this.
-// Cannot split the stack because it assumes that the arguments
-// are available sequentially after &fn; they would not be
-// copied if a stack split occurred.  It's OK for this to call
-// functions that split the stack.
-void runtime_testing_entersyscall(int32)
-  __asm__ (GOSYM_PREFIX "runtime.entersyscall");
-void
-runtime_testing_entersyscall(int32 dummy __attribute__ ((unused)))
-{
-	runtime_entersyscall();
-}
-
-void runtime_testing_exitsyscall(int32)
-  __asm__ (GOSYM_PREFIX "runtime.exitsyscall");
-
-void
-runtime_testing_exitsyscall(int32 dummy __attribute__ ((unused)))
-{
-	runtime_exitsyscall();
-}
-
 G*
 __go_go(void (*fn)(void*), void* arg)
 {
Index: libgo/runtime/runtime.c
===================================================================
--- libgo/runtime/runtime.c	(revision 240609)
+++ libgo/runtime/runtime.c	(working copy)
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#include <errno.h>
 #include <signal.h>
 #include <unistd.h>
 
@@ -210,3 +211,12 @@ go_closefd(int32 fd)
 {
   return runtime_close(fd);
 }
+
+intgo go_errno(void)
+  __asm__ (GOSYM_PREFIX "runtime.errno");
+
+intgo
+go_errno()
+{
+  return (intgo)errno;
+}
Index: libgo/runtime/runtime.h
===================================================================
--- libgo/runtime/runtime.h	(revision 240609)
+++ libgo/runtime/runtime.h	(working copy)
@@ -108,8 +108,16 @@ struct FuncVal
 #include "array.h"
 #include "interface.h"
 
+// Rename Go types generated by mkrsysinfo.sh from C types, to avoid
+// the name conflict.
+#define timeval go_timeval
+#define timespec go_timespec
+
 #include "runtime.inc"
 
+#undef timeval
+#undef timespec
+
 /*
  * Per-CPU declaration.
  */
@@ -392,9 +400,12 @@ void	runtime_parkunlock(Lock*, const cha
 void	runtime_tsleep(int64, const char*);
 M*	runtime_newm(void);
 void	runtime_goexit(void);
-void	runtime_entersyscall(void) __asm__ (GOSYM_PREFIX "syscall.Entersyscall");
-void	runtime_entersyscallblock(void);
-void	runtime_exitsyscall(void) __asm__ (GOSYM_PREFIX "syscall.Exitsyscall");
+void	runtime_entersyscall(int32)
+  __asm__ (GOSYM_PREFIX "runtime.entersyscall");
+void	runtime_entersyscallblock(int32)
+  __asm__ (GOSYM_PREFIX "runtime.entersyscallblock");
+void	runtime_exitsyscall(int32)
+  __asm__ (GOSYM_PREFIX "runtime.exitsyscall");
 G*	__go_go(void (*pfn)(void*), void*);
 void	siginit(void);
 bool	__go_sigsend(int32 sig);
@@ -476,21 +487,16 @@ void	runtime_unlock(Lock*)
  * notesleep/notetsleep are generally called on g0,
  * notetsleepg is similar to notetsleep but is called on user g.
  */
-void	runtime_noteclear(Note*);
-void	runtime_notesleep(Note*);
-void	runtime_notewakeup(Note*);
-bool	runtime_notetsleep(Note*, int64);  // false - timeout
-bool	runtime_notetsleepg(Note*, int64);  // false - timeout
-
-/*
- * low-level synchronization for implementing the above
- */
-uintptr	runtime_semacreate(void);
-int32	runtime_semasleep(int64);
-void	runtime_semawakeup(M*);
-// or
-void	runtime_futexsleep(uint32*, uint32, int64);
-void	runtime_futexwakeup(uint32*, uint32);
+void	runtime_noteclear(Note*)
+  __asm__ (GOSYM_PREFIX "runtime.noteclear");
+void	runtime_notesleep(Note*)
+  __asm__ (GOSYM_PREFIX "runtime.notesleep");
+void	runtime_notewakeup(Note*)
+  __asm__ (GOSYM_PREFIX "runtime.notewakeup");
+bool	runtime_notetsleep(Note*, int64)  // false - timeout
+  __asm__ (GOSYM_PREFIX "runtime.notetsleep");
+bool	runtime_notetsleepg(Note*, int64)  // false - timeout
+  __asm__ (GOSYM_PREFIX "runtime.notetsleepg");
 
 /*
  * Lock-free stack.
@@ -578,8 +584,10 @@ void	runtime_newErrorCString(const char*
 void	runtime_semacquire(uint32 volatile *, bool);
 void	runtime_semrelease(uint32 volatile *);
 int32	runtime_gomaxprocsfunc(int32 n);
-void	runtime_procyield(uint32);
-void	runtime_osyield(void);
+void	runtime_procyield(uint32)
+  __asm__(GOSYM_PREFIX "runtime.procyield");
+void	runtime_osyield(void)
+  __asm__(GOSYM_PREFIX "runtime.osyield");
 void	runtime_lockOSThread(void);
 void	runtime_unlockOSThread(void);
 bool	runtime_lockedOSThread(void);
Index: libgo/runtime/thread-linux.c
===================================================================
--- libgo/runtime/thread-linux.c	(revision 240053)
+++ libgo/runtime/thread-linux.c	(working copy)
@@ -7,69 +7,11 @@
 #include "signal_unix.h"
 
 // Linux futex.
-//
-//	futexsleep(uint32 *addr, uint32 val)
-//	futexwakeup(uint32 *addr)
-//
-// Futexsleep atomically checks if *addr == val and if so, sleeps on addr.
-// Futexwakeup wakes up threads sleeping on addr.
-// Futexsleep is allowed to wake up spuriously.
 
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <syscall.h>
 #include <linux/futex.h>
 
-typedef struct timespec Timespec;
-
-// Atomically,
-//	if(*addr == val) sleep
-// Might be woken up spuriously; that's allowed.
-// Don't sleep longer than ns; ns < 0 means forever.
-void
-runtime_futexsleep(uint32 *addr, uint32 val, int64 ns)
-{
-	Timespec ts;
-	int32 nsec;
-
-	// Some Linux kernels have a bug where futex of
-	// FUTEX_WAIT returns an internal error code
-	// as an errno.  Libpthread ignores the return value
-	// here, and so can we: as it says a few lines up,
-	// spurious wakeups are allowed.
-
-	if(ns < 0) {
-		syscall(__NR_futex, addr, FUTEX_WAIT, val, nil, nil, 0);
-		return;
-	}
-	ts.tv_sec = runtime_timediv(ns, 1000000000LL, &nsec);
-	ts.tv_nsec = nsec;
-	syscall(__NR_futex, addr, FUTEX_WAIT, val, &ts, nil, 0);
-}
-
-// If any procs are sleeping on addr, wake up at most cnt.
-void
-runtime_futexwakeup(uint32 *addr, uint32 cnt)
-{
-	int64 ret;
-
-	ret = syscall(__NR_futex, addr, FUTEX_WAKE, cnt, nil, nil, 0);
-
-	if(ret >= 0)
-		return;
-
-	// I don't know that futex wakeup can return
-	// EAGAIN or EINTR, but if it does, it would be
-	// safe to loop and call futex again.
-	runtime_printf("futexwakeup addr=%p returned %D\n", addr, ret);
-	*(int32*)0x1006 = 0x1006;
-}
-
 void
 runtime_osinit(void)
 {
Index: libgo/runtime/thread-sema.c
===================================================================
--- libgo/runtime/thread-sema.c	(revision 240053)
+++ libgo/runtime/thread-sema.c	(working copy)
@@ -10,131 +10,6 @@
 #include <time.h>
 #include <semaphore.h>
 
-/* If we don't have sem_timedwait, use pthread_cond_timedwait instead.
-   We don't always use condition variables because on some systems
-   pthread_mutex_lock and pthread_mutex_unlock must be called by the
-   same thread.  That is never true of semaphores.  */
-
-struct go_sem
-{
-  sem_t sem;
-
-#ifndef HAVE_SEM_TIMEDWAIT
-  int timedwait;
-  pthread_mutex_t mutex;
-  pthread_cond_t cond;
-#endif
-};
-
-/* Create a semaphore.  */
-
-uintptr
-runtime_semacreate(void)
-{
-  struct go_sem *p;
-
-  /* Call malloc rather than runtime_malloc.  This will allocate space
-     on the C heap.  We can't call runtime_malloc here because it
-     could cause a deadlock.  */
-  p = malloc (sizeof (struct go_sem));
-  if (sem_init (&p->sem, 0, 0) != 0)
-    runtime_throw ("sem_init");
-
-#ifndef HAVE_SEM_TIMEDWAIT
-  if (pthread_mutex_init (&p->mutex, NULL) != 0)
-    runtime_throw ("pthread_mutex_init");
-  if (pthread_cond_init (&p->cond, NULL) != 0)
-    runtime_throw ("pthread_cond_init");
-#endif
-
-  return (uintptr) p;
-}
-
-/* Acquire m->waitsema.  */
-
-int32
-runtime_semasleep (int64 ns)
-{
-  M *m;
-  struct go_sem *sem;
-  int r;
-
-  m = runtime_m ();
-  sem = (struct go_sem *) m->waitsema;
-  if (ns >= 0)
-    {
-      int64 abs;
-      struct timespec ts;
-      int err;
-
-      abs = ns + runtime_nanotime ();
-      ts.tv_sec = abs / 1000000000LL;
-      ts.tv_nsec = abs % 1000000000LL;
-
-      err = 0;
-
-#ifdef HAVE_SEM_TIMEDWAIT
-      r = sem_timedwait (&sem->sem, &ts);
-      if (r != 0)
-	err = errno;
-#else
-      if (pthread_mutex_lock (&sem->mutex) != 0)
-	runtime_throw ("pthread_mutex_lock");
-
-      while ((r = sem_trywait (&sem->sem)) != 0)
-	{
-	  r = pthread_cond_timedwait (&sem->cond, &sem->mutex, &ts);
-	  if (r != 0)
-	    {
-	      err = r;
-	      break;
-	    }
-	}
-
-      if (pthread_mutex_unlock (&sem->mutex) != 0)
-	runtime_throw ("pthread_mutex_unlock");
-#endif
-
-      if (err != 0)
-	{
-	  if (err == ETIMEDOUT || err == EAGAIN || err == EINTR)
-	    return -1;
-	  runtime_throw ("sema_timedwait");
-	}
-      return 0;
-    }
-
-  while (sem_wait (&sem->sem) != 0)
-    {
-      if (errno == EINTR)
-	continue;
-      runtime_throw ("sem_wait");
-    }
-
-  return 0;
-}
-
-/* Wake up mp->waitsema.  */
-
-void
-runtime_semawakeup (M *mp)
-{
-  struct go_sem *sem;
-
-  sem = (struct go_sem *) mp->waitsema;
-  if (sem_post (&sem->sem) != 0)
-    runtime_throw ("sem_post");
-
-#ifndef HAVE_SEM_TIMEDWAIT
-  if (pthread_mutex_lock (&sem->mutex) != 0)
-    runtime_throw ("pthread_mutex_lock");
-  if (pthread_cond_broadcast (&sem->cond) != 0)
-    runtime_throw ("pthread_cond_broadcast");
-  if (pthread_mutex_unlock (&sem->mutex) != 0)
-    runtime_throw ("pthread_mutex_unlock");
-#endif
-}
-
 void
 runtime_osinit (void)
 {
Index: libgo/sysinfo.c
===================================================================
--- libgo/sysinfo.c	(revision 240560)
+++ libgo/sysinfo.c	(working copy)
@@ -152,6 +152,9 @@
 #if defined(HAVE_SCHED_H)
 #include <sched.h>
 #endif
+#if defined(HAVE_SEMAPHORE_H)
+#include <semaphore.h>
+#endif
 
 /* Constants that may only be defined as expressions on some systems,
    expressions too complex for -fdump-go-spec to handle.  These are
