net: fix data races on deadline vars

Fixes #4434.

This proposal replaces the previous CL 6855110. Due to issue 599, 64-bit atomic operations should probably be avoided, so use a sync.Mutex instead.

Benchmark comparisons against 025b9d070a85 on linux/386:

CL 6855110:

benchmark                        old ns/op    new ns/op    delta
BenchmarkTCPOneShot                 710024       727409   +2.45%
BenchmarkTCPOneShotTimeout          758178       768620   +1.38%
BenchmarkTCPPersistent              223464       228058   +2.06%
BenchmarkTCPPersistentTimeout       234494       242600   +3.46%

This proposal:

benchmark                        old ns/op    new ns/op    delta
BenchmarkTCPOneShot                 710024       718492   +1.19%
BenchmarkTCPOneShotTimeout          758178       748783   -1.24%
BenchmarkTCPPersistent              223464       227628   +1.86%
BenchmarkTCPPersistentTimeout       234494       238321   +1.63%

R=rsc, dvyukov, mikioh.mikioh, alex.brainman, bradfitz
CC=golang-dev, remyoudompheng
https://golang.org/cl/6866050
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index 9af0514..f60c1e4c 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -46,6 +46,7 @@
 	"errors"
 	"io"
 	"os"
+	"sync"
 	"syscall"
 	"time"
 )
@@ -375,3 +376,36 @@
 	// Use wrapper to hide existing r.ReadFrom from io.Copy.
 	return io.Copy(writerOnly{w}, r)
 }
+
+// deadline is an atomically-accessed number of nanoseconds since 1970
+// or 0, if no deadline is set.
+type deadline struct {
+	sync.Mutex
+	val int64
+}
+
+func (d *deadline) expired() bool {
+	t := d.value()
+	return t > 0 && time.Now().UnixNano() >= t
+}
+
+func (d *deadline) value() (v int64) {
+	d.Lock()
+	v = d.val
+	d.Unlock()
+	return
+}
+
+func (d *deadline) set(v int64) {
+	d.Lock()
+	d.val = v
+	d.Unlock()
+}
+
+func (d *deadline) setTime(t time.Time) {
+	if t.IsZero() {
+		d.set(0)
+	} else {
+		d.set(t.UnixNano())
+	}
+}