"sort"
"strings"
"sync"
+ "sync/atomic"
"text/tabwriter"
"time"
"unsafe"
var cpu struct {
sync.Mutex
- profiling bool
+ profiling uint32 // bool, accessed atomically
done chan bool
}
+func cpuProfiling() bool {
+ return atomic.LoadUint32(&cpu.profiling) != 0
+}
+
+func setCPUProfiling(b bool) {
+ if b {
+ atomic.StoreUint32(&cpu.profiling, 1)
+ } else {
+ atomic.StoreUint32(&cpu.profiling, 0)
+ }
+}
+
// StartCPUProfile enables CPU profiling for the current process.
// While profiling, the profile will be buffered and written to w.
// StartCPUProfile returns an error if profiling is already enabled.
cpu.done = make(chan bool)
}
// Double-check.
- if cpu.profiling {
+ if cpuProfiling() {
return fmt.Errorf("cpu profiling already in use")
}
- cpu.profiling = true
+ setCPUProfiling(true)
runtime.SetCPUProfileRate(hz)
go profileWriter(w)
return nil
b := newProfileBuilder(w)
var err error
for {
- time.Sleep(100 * time.Millisecond)
+ if cpuProfiling() {
+ time.Sleep(100 * time.Millisecond)
+ }
data, tags, eof := readProfile()
if e := b.addCPUData(data, tags); e != nil && err == nil {
err = e
cpu.Lock()
defer cpu.Unlock()
- if !cpu.profiling {
+ if !cpuProfiling() {
return
}
- cpu.profiling = false
+ setCPUProfiling(false)
runtime.SetCPUProfileRate(0)
<-cpu.done
}