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())
+ }
+}