syscall: make pwd process-wide on Plan 9

On Plan 9, the pwd is apparently per-thread not per process. That
means different goroutines saw different current directories, even
changing within a goroutine as they were scheduled.

Instead, track the the process-wide pwd protected by a mutex in the
syscall package and set the current goroutine thread's pwd to the
correct once at critical points.

Fixes #9428

Change-Id: I928e90886355be4a95c2be834f5883e2b50fc0cf
Reviewed-on: https://go-review.googlesource.com/6350
Reviewed-by: David du Colombier <0intro@gmail.com>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go
index 618e02c..79857cc 100644
--- a/src/syscall/syscall_plan9.go
+++ b/src/syscall/syscall_plan9.go
@@ -129,17 +129,6 @@
 
 var ioSync int64
 
-func Getwd() (wd string, err error) {
-	fd, e := Open(".", O_RDONLY)
-
-	if e != nil {
-		return "", e
-	}
-	defer Close(fd)
-
-	return Fd2path(fd)
-}
-
 //sys	fd2path(fd int, buf []byte) (err error)
 func Fd2path(fd int) (path string, err error) {
 	var buf [512]byte
@@ -242,6 +231,7 @@
 }
 
 func Unmount(name, old string) (err error) {
+	Fixwd()
 	oldp, err := BytePtrFromString(old)
 	if err != nil {
 		return err
@@ -325,17 +315,47 @@
 	return make([]int, 0), nil
 }
 
+//sys	open(path string, mode int) (fd int, err error)
+func Open(path string, mode int) (fd int, err error) {
+	Fixwd()
+	return open(path, mode)
+}
+
+//sys	create(path string, mode int, perm uint32) (fd int, err error)
+func Create(path string, mode int, perm uint32) (fd int, err error) {
+	Fixwd()
+	return create(path, mode, perm)
+}
+
+//sys	remove(path string) (err error)
+func Remove(path string) error {
+	Fixwd()
+	return remove(path)
+}
+
+//sys	stat(path string, edir []byte) (n int, err error)
+func Stat(path string, edir []byte) (n int, err error) {
+	Fixwd()
+	return stat(path, edir)
+}
+
+//sys	bind(name string, old string, flag int) (err error)
+func Bind(name string, old string, flag int) (err error) {
+	Fixwd()
+	return bind(name, old, flag)
+}
+
+//sys	wstat(path string, edir []byte) (err error)
+func Wstat(path string, edir []byte) (err error) {
+	Fixwd()
+	return wstat(path, edir)
+}
+
+//sys	chdir(path string) (err error)
 //sys	Dup(oldfd int, newfd int) (fd int, err error)
-//sys	Open(path string, mode int) (fd int, err error)
-//sys	Create(path string, mode int, perm uint32) (fd int, err error)
-//sys	Remove(path string) (err error)
 //sys	Pread(fd int, p []byte, offset int64) (n int, err error)
 //sys	Pwrite(fd int, p []byte, offset int64) (n int, err error)
 //sys	Close(fd int) (err error)
-//sys	Chdir(path string) (err error)
-//sys	Bind(name string, old string, flag int) (err error)
 //sys	Mount(fd int, afd int, old string, flag int, aname string) (err error)
-//sys	Stat(path string, edir []byte) (n int, err error)
 //sys	Fstat(fd int, edir []byte) (n int, err error)
-//sys	Wstat(path string, edir []byte) (err error)
 //sys	Fwstat(fd int, edir []byte) (err error)