From 2ad67147936bb1bf1f95d2a2ae41deab236712e9 Mon Sep 17 00:00:00 2001 From: Anthony Martin Date: Mon, 17 Dec 2012 08:33:51 -0800 Subject: [PATCH] syscall: lazily populate the environment cache on Plan 9 This decreases the amount of system calls during the first call to Getenv. Calling Environ will still read in all environment variables and populate the cache. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6939048 --- src/pkg/syscall/env_plan9.go | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/pkg/syscall/env_plan9.go b/src/pkg/syscall/env_plan9.go index 2848d9b32b..0f89aa9ee3 100644 --- a/src/pkg/syscall/env_plan9.go +++ b/src/pkg/syscall/env_plan9.go @@ -12,14 +12,17 @@ import ( ) var ( - // envOnce guards initialization by copyenv, which populates env. + // envOnce guards copyenv, which populates env. envOnce sync.Once // envLock guards env. envLock sync.RWMutex // env maps from an environment variable to its value. - env map[string]string + env = make(map[string]string) + + errZeroLengthKey = errors.New("zero length key") + errShortWrite = errors.New("i/o count too small") ) func readenv(key string) (string, error) { @@ -47,12 +50,18 @@ func writeenv(key, value string) error { return err } defer Close(fd) - _, err = Write(fd, []byte(value)) - return err + b := []byte(value) + n, err := Write(fd, b) + if err != nil { + return err + } + if n != len(b) { + return errShortWrite + } + return nil } func copyenv() { - env = make(map[string]string) fd, err := Open("/env", O_RDONLY) if err != nil { return @@ -72,7 +81,6 @@ func copyenv() { } func Getenv(key string) (value string, found bool) { - envOnce.Do(copyenv) if len(key) == 0 { return "", false } @@ -80,17 +88,20 @@ func Getenv(key string) (value string, found bool) { envLock.RLock() defer envLock.RUnlock() - v, ok := env[key] - if !ok { + if v, ok := env[key]; ok { + return v, true + } + v, err := readenv(key) + if err != nil { return "", false } + env[key] = v return v, true } func Setenv(key, value string) error { - envOnce.Do(copyenv) if len(key) == 0 { - return errors.New("zero length key") + return errZeroLengthKey } envLock.Lock() @@ -105,8 +116,6 @@ func Setenv(key, value string) error { } func Clearenv() { - envOnce.Do(copyenv) // prevent copyenv in Getenv/Setenv - envLock.Lock() defer envLock.Unlock() @@ -115,9 +124,10 @@ func Clearenv() { } func Environ() []string { - envOnce.Do(copyenv) envLock.RLock() defer envLock.RUnlock() + + envOnce.Do(copyenv) a := make([]string, len(env)) i := 0 for k, v := range env {