os: fix data race on Process.done

Fixes #3969.

R=dvyukov, r, alex.brainman, minux.ma
CC=golang-dev
https://golang.org/cl/6462081
diff --git a/src/pkg/os/exec.go b/src/pkg/os/exec.go
index eb6a4f8..5aea309 100644
--- a/src/pkg/os/exec.go
+++ b/src/pkg/os/exec.go
@@ -6,6 +6,7 @@
 
 import (
 	"runtime"
+	"sync/atomic"
 	"syscall"
 )
 
@@ -13,7 +14,7 @@
 type Process struct {
 	Pid    int
 	handle uintptr
-	done   bool // process has been successfully waited on
+	isdone uint32 // process has been successfully waited on, non zero if true
 }
 
 func newProcess(pid int, handle uintptr) *Process {
@@ -22,6 +23,14 @@
 	return p
 }
 
+func (p *Process) setDone() {
+	atomic.StoreUint32(&p.isdone, 1)
+}
+
+func (p *Process) done() bool {
+	return atomic.LoadUint32(&p.isdone) > 0
+}
+
 // ProcAttr holds the attributes that will be applied to a new process
 // started by StartProcess.
 type ProcAttr struct {
diff --git a/src/pkg/os/exec_plan9.go b/src/pkg/os/exec_plan9.go
index ca2dfbf..2a7a597 100644
--- a/src/pkg/os/exec_plan9.go
+++ b/src/pkg/os/exec_plan9.go
@@ -49,7 +49,7 @@
 }
 
 func (p *Process) signal(sig Signal) error {
-	if p.done {
+	if p.done() {
 		return errors.New("os: process already finished")
 	}
 	if sig == Kill {
@@ -84,7 +84,7 @@
 		}
 
 		if waitmsg.Pid == p.Pid {
-			p.done = true
+			p.setDone()
 			break
 		}
 	}
diff --git a/src/pkg/os/exec_unix.go b/src/pkg/os/exec_unix.go
index ecfe535..fa3ba8a 100644
--- a/src/pkg/os/exec_unix.go
+++ b/src/pkg/os/exec_unix.go
@@ -24,7 +24,7 @@
 		return nil, NewSyscallError("wait", e)
 	}
 	if pid1 != 0 {
-		p.done = true
+		p.setDone()
 	}
 	ps = &ProcessState{
 		pid:    pid1,
@@ -35,7 +35,7 @@
 }
 
 func (p *Process) signal(sig Signal) error {
-	if p.done {
+	if p.done() {
 		return errors.New("os: process already finished")
 	}
 	s, ok := sig.(syscall.Signal)
diff --git a/src/pkg/os/exec_windows.go b/src/pkg/os/exec_windows.go
index 5beca4a..4aa2ade 100644
--- a/src/pkg/os/exec_windows.go
+++ b/src/pkg/os/exec_windows.go
@@ -32,7 +32,7 @@
 	if e != nil {
 		return nil, NewSyscallError("GetProcessTimes", e)
 	}
-	p.done = true
+	p.setDone()
 	// NOTE(brainman): It seems that sometimes process is not dead
 	// when WaitForSingleObject returns. But we do not know any
 	// other way to wait for it. Sleeping for a while seems to do
@@ -43,7 +43,7 @@
 }
 
 func (p *Process) signal(sig Signal) error {
-	if p.done {
+	if p.done() {
 		return errors.New("os: process already finished")
 	}
 	if sig == Kill {