all: merge master into release-branch.go1.7

7a62274 net/http: make Transport use new connection if over HTTP/2 concurrency limit
219ca60 doc: fix required OS X version inconsistency for binary downloads
26015b9 runtime: make stack 16-byte aligned for external code in _rt0_amd64_linux_lib
9fde86b runtime, syscall: fix kernel gettimeofday ABI change on iOS 10
3a03e87 os: check for waitid returning ENOSYS
1031675 net/http: update bundled http2 for flow control window adjustment fix
da070be syscall: fix Gettimeofday on macOS Sierra
f135c32 runtime: initialize hash algs before typemap

Change-Id: Ie176f3db1e253d75ae8e56b16d3fd9900b37dde3
diff --git a/doc/install.html b/doc/install.html
index 0e6b86f..cfe3e67 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -17,7 +17,7 @@
 <p>
 <a href="https://golang.org/dl/" target="_blank">Official binary
 distributions</a> are available for the FreeBSD (release 8-STABLE and above),
-Linux, Mac OS X (10.7 and above), and Windows operating systems and
+Linux, Mac OS X (10.8 and above), and Windows operating systems and
 the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
 architectures.
 </p>
@@ -49,7 +49,7 @@
 <tr><td colspan="3"><hr></td></tr>
 <tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
 <tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported</td></tr>
-<tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
+<tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup> for <code>cgo</code> support</td></tr>
 <tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr>
 </table>
 
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index cd66c09..ffe15f0 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -28,6 +28,7 @@
 	"io"
 	"io/ioutil"
 	"log"
+	"math"
 	"net"
 	"net/http/httptrace"
 	"net/textproto"
@@ -403,9 +404,17 @@
 type http2StreamError struct {
 	StreamID uint32
 	Code     http2ErrCode
+	Cause    error // optional additional detail
+}
+
+func http2streamError(id uint32, code http2ErrCode) http2StreamError {
+	return http2StreamError{StreamID: id, Code: code}
 }
 
 func (e http2StreamError) Error() string {
+	if e.Cause != nil {
+		return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
+	}
 	return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
 }
 
@@ -1366,7 +1375,7 @@
 		if fh.StreamID == 0 {
 			return nil, http2ConnectionError(http2ErrCodeProtocol)
 		}
-		return nil, http2StreamError{fh.StreamID, http2ErrCodeProtocol}
+		return nil, http2streamError(fh.StreamID, http2ErrCodeProtocol)
 	}
 	return &http2WindowUpdateFrame{
 		http2FrameHeader: fh,
@@ -1444,7 +1453,7 @@
 		}
 	}
 	if len(p)-int(padLength) <= 0 {
-		return nil, http2StreamError{fh.StreamID, http2ErrCodeProtocol}
+		return nil, http2streamError(fh.StreamID, http2ErrCodeProtocol)
 	}
 	hf.headerFragBuf = p[:len(p)-int(padLength)]
 	return hf, nil
@@ -1911,6 +1920,9 @@
 	hdec.SetEmitEnabled(true)
 	hdec.SetMaxStringLength(fr.maxHeaderStringLen())
 	hdec.SetEmitFunc(func(hf hpack.HeaderField) {
+		if http2VerboseLogs && http2logFrameReads {
+			log.Printf("http2: decoded hpack field %+v", hf)
+		}
 		if !httplex.ValidHeaderFieldValue(hf.Value) {
 			invalid = http2headerFieldValueError(hf.Value)
 		}
@@ -1969,11 +1981,17 @@
 	}
 	if invalid != nil {
 		fr.errDetail = invalid
-		return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol}
+		if http2VerboseLogs {
+			log.Printf("http2: invalid header: %v", invalid)
+		}
+		return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol, invalid}
 	}
 	if err := mh.checkPseudos(); err != nil {
 		fr.errDetail = err
-		return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol}
+		if http2VerboseLogs {
+			log.Printf("http2: invalid pseudo headers: %v", err)
+		}
+		return nil, http2StreamError{mh.StreamID, http2ErrCodeProtocol, err}
 	}
 	return mh, nil
 }
@@ -3604,7 +3622,7 @@
 		case http2stateOpen:
 
 			st.state = http2stateHalfClosedLocal
-			errCancel := http2StreamError{st.id, http2ErrCodeCancel}
+			errCancel := http2streamError(st.id, http2ErrCodeCancel)
 			sc.resetStream(errCancel)
 		case http2stateHalfClosedRemote:
 			sc.closeStream(st, http2errHandlerComplete)
@@ -3797,7 +3815,7 @@
 			return nil
 		}
 		if !st.flow.add(int32(f.Increment)) {
-			return http2StreamError{f.StreamID, http2ErrCodeFlowControl}
+			return http2streamError(f.StreamID, http2ErrCodeFlowControl)
 		}
 	default:
 		if !sc.flow.add(int32(f.Increment)) {
@@ -3819,7 +3837,7 @@
 	if st != nil {
 		st.gotReset = true
 		st.cancelCtx()
-		sc.closeStream(st, http2StreamError{f.StreamID, f.ErrCode})
+		sc.closeStream(st, http2streamError(f.StreamID, f.ErrCode))
 	}
 	return nil
 }
@@ -3922,13 +3940,13 @@
 	if !ok || st.state != http2stateOpen || st.gotTrailerHeader {
 
 		if sc.inflow.available() < int32(f.Length) {
-			return http2StreamError{id, http2ErrCodeFlowControl}
+			return http2streamError(id, http2ErrCodeFlowControl)
 		}
 
 		sc.inflow.take(int32(f.Length))
 		sc.sendWindowUpdate(nil, int(f.Length))
 
-		return http2StreamError{id, http2ErrCodeStreamClosed}
+		return http2streamError(id, http2ErrCodeStreamClosed)
 	}
 	if st.body == nil {
 		panic("internal error: should have a body in this state")
@@ -3936,19 +3954,19 @@
 
 	if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
 		st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
-		return http2StreamError{id, http2ErrCodeStreamClosed}
+		return http2streamError(id, http2ErrCodeStreamClosed)
 	}
 	if f.Length > 0 {
 
 		if st.inflow.available() < int32(f.Length) {
-			return http2StreamError{id, http2ErrCodeFlowControl}
+			return http2streamError(id, http2ErrCodeFlowControl)
 		}
 		st.inflow.take(int32(f.Length))
 
 		if len(data) > 0 {
 			wrote, err := st.body.Write(data)
 			if err != nil {
-				return http2StreamError{id, http2ErrCodeStreamClosed}
+				return http2streamError(id, http2ErrCodeStreamClosed)
 			}
 			if wrote != len(data) {
 				panic("internal error: bad Writer")
@@ -4046,10 +4064,10 @@
 
 		if sc.unackedSettings == 0 {
 
-			return http2StreamError{st.id, http2ErrCodeProtocol}
+			return http2streamError(st.id, http2ErrCodeProtocol)
 		}
 
-		return http2StreamError{st.id, http2ErrCodeRefusedStream}
+		return http2streamError(st.id, http2ErrCodeRefusedStream)
 	}
 
 	rw, req, err := sc.newWriterAndRequest(st, f)
@@ -4083,18 +4101,18 @@
 	}
 	st.gotTrailerHeader = true
 	if !f.StreamEnded() {
-		return http2StreamError{st.id, http2ErrCodeProtocol}
+		return http2streamError(st.id, http2ErrCodeProtocol)
 	}
 
 	if len(f.PseudoFields()) > 0 {
-		return http2StreamError{st.id, http2ErrCodeProtocol}
+		return http2streamError(st.id, http2ErrCodeProtocol)
 	}
 	if st.trailer != nil {
 		for _, hf := range f.RegularFields() {
 			key := sc.canonicalHeader(hf.Name)
 			if !http2ValidTrailerHeader(key) {
 
-				return http2StreamError{st.id, http2ErrCodeProtocol}
+				return http2streamError(st.id, http2ErrCodeProtocol)
 			}
 			st.trailer[key] = append(st.trailer[key], hf.Value)
 		}
@@ -4148,18 +4166,18 @@
 	isConnect := method == "CONNECT"
 	if isConnect {
 		if path != "" || scheme != "" || authority == "" {
-			return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol}
+			return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
 		}
 	} else if method == "" || path == "" ||
 		(scheme != "https" && scheme != "http") {
 
-		return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol}
+		return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
 	}
 
 	bodyOpen := !f.StreamEnded()
 	if method == "HEAD" && bodyOpen {
 
-		return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol}
+		return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
 	}
 	var tlsState *tls.ConnectionState // nil if not scheme https
 
@@ -4216,7 +4234,7 @@
 		var err error
 		url_, err = url.ParseRequestURI(path)
 		if err != nil {
-			return nil, nil, http2StreamError{f.StreamID, http2ErrCodeProtocol}
+			return nil, nil, http2streamError(f.StreamID, http2ErrCodeProtocol)
 		}
 		requestURI = path
 	}
@@ -4993,14 +5011,14 @@
 	br              *bufio.Reader
 	fr              *http2Framer
 	lastActive      time.Time
-
-	// Settings from peer:
+	// Settings from peer: (also guarded by mu)
 	maxFrameSize         uint32
 	maxConcurrentStreams uint32
 	initialWindowSize    uint32
-	hbuf                 bytes.Buffer // HPACK encoder writes into this
-	henc                 *hpack.Encoder
-	freeBuf              [][]byte
+
+	hbuf    bytes.Buffer // HPACK encoder writes into this
+	henc    *hpack.Encoder
+	freeBuf [][]byte
 
 	wmu  sync.Mutex // held while writing; acquire AFTER mu if holding both
 	werr error      // first write error that has occurred
@@ -5244,10 +5262,6 @@
 }
 
 func (t *http2Transport) newClientConn(c net.Conn, singleUse bool) (*http2ClientConn, error) {
-	if http2VerboseLogs {
-		t.vlogf("http2: Transport creating client conn to %v", c.RemoteAddr())
-	}
-
 	cc := &http2ClientConn{
 		t:                    t,
 		tconn:                c,
@@ -5260,6 +5274,10 @@
 		singleUse:            singleUse,
 		wantSettingsAck:      true,
 	}
+	if http2VerboseLogs {
+		t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
+	}
+
 	cc.cond = sync.NewCond(&cc.mu)
 	cc.flow.add(int32(http2initialWindowSize))
 
@@ -5324,7 +5342,7 @@
 	}
 	return cc.goAway == nil && !cc.closed &&
 		int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
-		cc.nextStreamID < 2147483647
+		cc.nextStreamID < math.MaxInt32
 }
 
 func (cc *http2ClientConn) closeIfIdle() {
@@ -5334,9 +5352,13 @@
 		return
 	}
 	cc.closed = true
+	nextID := cc.nextStreamID
 
 	cc.mu.Unlock()
 
+	if http2VerboseLogs {
+		cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, nextID-2)
+	}
 	cc.tconn.Close()
 }
 
@@ -5986,11 +6008,15 @@
 	for {
 		f, err := cc.fr.ReadFrame()
 		if err != nil {
-			cc.vlogf("Transport readFrame error: (%T) %v", err, err)
+			cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
 		}
 		if se, ok := err.(http2StreamError); ok {
 			if cs := cc.streamByID(se.StreamID, true); cs != nil {
-				rl.endStreamError(cs, cc.fr.errDetail)
+				cs.cc.writeStreamReset(cs.ID, se.Code, err)
+				if se.Cause == nil {
+					se.Cause = cc.fr.errDetail
+				}
+				rl.endStreamError(cs, se)
 			}
 			continue
 		} else if err != nil {
@@ -6034,6 +6060,9 @@
 			cc.logf("Transport: unhandled response frame type %T", f)
 		}
 		if err != nil {
+			if http2VerboseLogs {
+				cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, http2summarizeFrame(f), err)
+			}
 			return err
 		}
 		if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
@@ -6381,6 +6410,11 @@
 	if http2isConnectionCloseRequest(cs.req) {
 		rl.closeWhenIdle = true
 	}
+
+	select {
+	case cs.resc <- http2resAndError{err: err}:
+	default:
+	}
 }
 
 func (cs *http2clientStream) copyTrailers() {
@@ -6425,6 +6459,16 @@
 			cc.maxConcurrentStreams = s.Val
 		case http2SettingInitialWindowSize:
 
+			if s.Val > math.MaxInt32 {
+				return http2ConnectionError(http2ErrCodeFlowControl)
+			}
+
+			delta := int32(s.Val) - int32(cc.initialWindowSize)
+			for _, cs := range cc.streams {
+				cs.flow.add(delta)
+			}
+			cc.cond.Broadcast()
+
 			cc.initialWindowSize = s.Val
 		default:
 
@@ -6475,7 +6519,7 @@
 	case <-cs.peerReset:
 
 	default:
-		err := http2StreamError{cs.ID, f.ErrCode}
+		err := http2streamError(cs.ID, f.ErrCode)
 		cs.resetErr = err
 		close(cs.peerReset)
 		cs.bufPipe.CloseWithError(err)
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 009f3c5..3046de5 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -398,6 +398,15 @@
 // HTTP request on a new connection. The non-nil input error is the
 // error from roundTrip.
 func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool {
+	if err == http2ErrNoCachedConn {
+		// Issue 16582: if the user started a bunch of
+		// requests at once, they can all pick the same conn
+		// and violate the server's max concurrent streams.
+		// Instead, match the HTTP/1 behavior for now and dial
+		// again to get a new TCP connection, rather than failing
+		// this request.
+		return true
+	}
 	if err == errMissingHost {
 		// User error.
 		return false
diff --git a/src/os/wait_waitid.go b/src/os/wait_waitid.go
index 5dbd7f9..74b7494 100644
--- a/src/os/wait_waitid.go
+++ b/src/os/wait_waitid.go
@@ -28,6 +28,12 @@
 	_, _, e := syscall.Syscall6(syscall.SYS_WAITID, _P_PID, uintptr(p.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0)
 	runtime.KeepAlive(psig)
 	if e != 0 {
+		// waitid has been available since Linux 2.6.9, but
+		// reportedly is not available in Ubuntu on Windows.
+		// See issue 16610.
+		if e == syscall.ENOSYS {
+			return false, nil
+		}
 		return false, NewSyscallError("waitid", e)
 	}
 	return true, nil
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
index 6694349..147332e 100644
--- a/src/runtime/alg.go
+++ b/src/runtime/alg.go
@@ -289,7 +289,7 @@
 // used in hash{32,64}.go to seed the hash function
 var hashkey [4]uintptr
 
-func init() {
+func alginit() {
 	// Install aes hash algorithm if we have the instructions we need
 	if (GOARCH == "386" || GOARCH == "amd64") &&
 		GOOS != "nacl" &&
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 1d00930a..e693f7e 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -439,7 +439,8 @@
 	stackinit()
 	mallocinit()
 	mcommoninit(_g_.m)
-	typelinksinit()
+	alginit()       // maps must not be used before this call
+	typelinksinit() // uses maps
 	itabsinit()
 
 	msigsave(_g_.m)
diff --git a/src/runtime/rt0_linux_amd64.s b/src/runtime/rt0_linux_amd64.s
index 564b51c..ced471f 100644
--- a/src/runtime/rt0_linux_amd64.s
+++ b/src/runtime/rt0_linux_amd64.s
@@ -12,13 +12,18 @@
 
 // When building with -buildmode=c-shared, this symbol is called when the shared
 // library is loaded.
-TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x48
+// Note: This function calls external C code, which might required 16-byte stack
+// alignment after cmd/internal/obj applies its transformations.
+TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x50
+	MOVQ	SP, AX
+	ANDQ	$-16, SP
 	MOVQ	BX, 0x10(SP)
 	MOVQ	BP, 0x18(SP)
 	MOVQ	R12, 0x20(SP)
 	MOVQ	R13, 0x28(SP)
 	MOVQ	R14, 0x30(SP)
 	MOVQ	R15, 0x38(SP)
+	MOVQ	AX, 0x40(SP)
 
 	MOVQ	DI, _rt0_amd64_linux_lib_argc<>(SB)
 	MOVQ	SI, _rt0_amd64_linux_lib_argv<>(SB)
@@ -50,6 +55,7 @@
 	MOVQ	0x28(SP), R13
 	MOVQ	0x30(SP), R14
 	MOVQ	0x38(SP), R15
+	MOVQ	0x40(SP), SP
 	RET
 
 TEXT _rt0_amd64_linux_lib_go(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_darwin_arm.s b/src/runtime/sys_darwin_arm.s
index 6b6437d..52f6a94 100644
--- a/src/runtime/sys_darwin_arm.s
+++ b/src/runtime/sys_darwin_arm.s
@@ -162,11 +162,15 @@
 TEXT time·now(SB), 7, $32
 	MOVW	$8(R13), R0  // timeval
 	MOVW	$0, R1  // zone
+	MOVW	$0, R2	// see issue 16570
 	MOVW	$SYS_gettimeofday, R12
 	SWI	$0x80 // Note: R0 is tv_sec, R1 is tv_usec
-
+	CMP	$0, R0
+	BNE	inreg
+	MOVW	8(R13), R0
+	MOVW	12(R13), R1
+inreg:
 	MOVW    R1, R2  // usec
-
 	MOVW	R0, sec+0(FP)
 	MOVW	$0, R1
 	MOVW	R1, loc+4(FP)
@@ -178,9 +182,14 @@
 TEXT runtime·nanotime(SB),NOSPLIT,$32
 	MOVW	$8(R13), R0  // timeval
 	MOVW	$0, R1  // zone
+	MOVW	$0, R2	// see issue 16570
 	MOVW	$SYS_gettimeofday, R12
 	SWI	$0x80 // Note: R0 is tv_sec, R1 is tv_usec
-
+	CMP	$0, R0
+	BNE	inreg
+	MOVW	8(R13), R0
+	MOVW	12(R13), R1
+inreg:
 	MOVW    R1, R2
 	MOVW	$1000000000, R3
 	MULLU	R0, R3, (R1, R0)
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index a3b851d..8e6b5b1 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -155,9 +155,14 @@
 	MOVD	RSP, R0	// timeval
 	MOVD	R0, R9	// this is how dyld calls gettimeofday
 	MOVW	$0, R1	// zone
+	MOVD	$0, R2	// see issue 16570
 	MOVW	$SYS_gettimeofday, R16
 	SVC	$0x80	// Note: x0 is tv_sec, w1 is tv_usec
-
+	CMP	$0, R0
+	BNE	inreg
+	MOVD	0(RSP), R0
+	MOVW	8(RSP), R1
+inreg:
 	MOVD	R0, sec+0(FP)
 	MOVW	$1000, R3
 	MUL	R3, R1
@@ -168,9 +173,14 @@
 	MOVD	RSP, R0	// timeval
 	MOVD	R0, R9	// this is how dyld calls gettimeofday
 	MOVW	$0, R1	// zone
+	MOVD	$0, R2	// see issue 16570
 	MOVW	$SYS_gettimeofday, R16
 	SVC	$0x80	// Note: x0 is tv_sec, w1 is tv_usec
-
+	CMP	$0, R0
+	BNE	inreg
+	MOVD	0(RSP), R0
+	MOVW	8(RSP), R1
+inreg:
 	MOVW	$1000000000, R3
 	MUL	R3, R0
 	MOVW	$1000, R3
diff --git a/src/syscall/syscall_darwin_386.go b/src/syscall/syscall_darwin_386.go
index 7dbb1c3..f75de00 100644
--- a/src/syscall/syscall_darwin_386.go
+++ b/src/syscall/syscall_darwin_386.go
@@ -26,14 +26,21 @@
 }
 
 //sysnb	gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
-func Gettimeofday(tv *Timeval) (err error) {
-	// The tv passed to gettimeofday must be non-nil
-	// but is otherwise unused. The answers come back
-	// in the two registers.
+func Gettimeofday(tv *Timeval) error {
+	// The tv passed to gettimeofday must be non-nil.
+	// Before macOS Sierra (10.12), tv was otherwise unused and
+	// the answers came back in the two registers.
+	// As of Sierra, gettimeofday return zeros and populates
+	// tv itself.
 	sec, usec, err := gettimeofday(tv)
-	tv.Sec = int32(sec)
-	tv.Usec = int32(usec)
-	return err
+	if err != nil {
+		return err
+	}
+	if sec != 0 || usec != 0 {
+		tv.Sec = int32(sec)
+		tv.Usec = int32(usec)
+	}
+	return nil
 }
 
 func SetKevent(k *Kevent_t, fd, mode, flags int) {
diff --git a/src/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go
index 80e6024..7908311 100644
--- a/src/syscall/syscall_darwin_amd64.go
+++ b/src/syscall/syscall_darwin_amd64.go
@@ -26,14 +26,21 @@
 }
 
 //sysnb	gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
-func Gettimeofday(tv *Timeval) (err error) {
-	// The tv passed to gettimeofday must be non-nil
-	// but is otherwise unused. The answers come back
-	// in the two registers.
+func Gettimeofday(tv *Timeval) error {
+	// The tv passed to gettimeofday must be non-nil.
+	// Before macOS Sierra (10.12), tv was otherwise unused and
+	// the answers came back in the two registers.
+	// As of Sierra, gettimeofday return zeros and populates
+	// tv itself.
 	sec, usec, err := gettimeofday(tv)
-	tv.Sec = sec
-	tv.Usec = usec
-	return err
+	if err != nil {
+		return err
+	}
+	if sec != 0 || usec != 0 {
+		tv.Sec = sec
+		tv.Usec = usec
+	}
+	return nil
 }
 
 func SetKevent(k *Kevent_t, fd, mode, flags int) {
diff --git a/src/syscall/syscall_darwin_arm.go b/src/syscall/syscall_darwin_arm.go
index c302d83..fe43103 100644
--- a/src/syscall/syscall_darwin_arm.go
+++ b/src/syscall/syscall_darwin_arm.go
@@ -26,14 +26,19 @@
 }
 
 //sysnb	gettimeofday(tp *Timeval) (sec int32, usec int32, err error)
-func Gettimeofday(tv *Timeval) (err error) {
+func Gettimeofday(tv *Timeval) error {
 	// The tv passed to gettimeofday must be non-nil
 	// but is otherwise unused. The answers come back
 	// in the two registers.
 	sec, usec, err := gettimeofday(tv)
-	tv.Sec = int32(sec)
-	tv.Usec = int32(usec)
-	return err
+	if err != nil {
+		return err
+	}
+	if sec != 0 || usec != 0 {
+		tv.Sec = int32(sec)
+		tv.Usec = int32(usec)
+	}
+	return nil
 }
 
 func SetKevent(k *Kevent_t, fd, mode, flags int) {
diff --git a/src/syscall/syscall_darwin_arm64.go b/src/syscall/syscall_darwin_arm64.go
index 29f40d4..d396e25 100644
--- a/src/syscall/syscall_darwin_arm64.go
+++ b/src/syscall/syscall_darwin_arm64.go
@@ -26,14 +26,19 @@
 }
 
 //sysnb	gettimeofday(tp *Timeval) (sec int64, usec int32, err error)
-func Gettimeofday(tv *Timeval) (err error) {
+func Gettimeofday(tv *Timeval) error {
 	// The tv passed to gettimeofday must be non-nil
 	// but is otherwise unused. The answers come back
 	// in the two registers.
 	sec, usec, err := gettimeofday(tv)
-	tv.Sec = sec
-	tv.Usec = usec
-	return err
+	if err != nil {
+		return err
+	}
+	if sec != 0 || usec != 0 {
+		tv.Sec = sec
+		tv.Usec = usec
+	}
+	return nil
 }
 
 func SetKevent(k *Kevent_t, fd, mode, flags int) {
diff --git a/src/syscall/syscall_darwin_test.go b/src/syscall/syscall_darwin_test.go
new file mode 100644
index 0000000..cea5636
--- /dev/null
+++ b/src/syscall/syscall_darwin_test.go
@@ -0,0 +1,23 @@
+// 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.
+
+// +build darwin
+// +build amd64 386 arm arm64
+
+package syscall_test
+
+import (
+	"syscall"
+	"testing"
+)
+
+func TestDarwinGettimeofday(t *testing.T) {
+	tv := &syscall.Timeval{}
+	if err := syscall.Gettimeofday(tv); err != nil {
+		t.Fatal(err)
+	}
+	if tv.Sec == 0 && tv.Usec == 0 {
+		t.Fatal("Sec and Usec both zero")
+	}
+}