]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/pprof: emit end-of-log marker at end of CPU profile.
authorAlan Donovan <adonovan@google.com>
Tue, 4 Sep 2012 18:34:03 +0000 (14:34 -0400)
committerAlan Donovan <adonovan@google.com>
Tue, 4 Sep 2012 18:34:03 +0000 (14:34 -0400)
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6489065

src/pkg/runtime/cpuprof.c
src/pkg/runtime/pprof/pprof_test.go

index 05fa0cf61ad9c0cbf5faa48217730d97ce0626c0..eded073320c65ba48f8e09c58aaa716fccd75957 100644 (file)
@@ -99,6 +99,7 @@ struct Profile {
        uint32 wtoggle;
        bool wholding;  // holding & need to release a log half
        bool flushing;  // flushing hash table - profile is over
+       bool eod_sent;  // special end-of-data record sent; => flushing
 };
 
 static Lock lk;
@@ -109,6 +110,8 @@ static void add(Profile*, uintptr*, int32);
 static bool evict(Profile*, Entry*);
 static bool flushlog(Profile*);
 
+static uintptr eod[3] = {0, 1, 0};
+
 // LostProfileData is a no-op function used in profiles
 // to mark the number of profiling stack traces that were
 // discarded due to slow data writers.
@@ -163,6 +166,7 @@ runtime·SetCPUProfileRate(int32 hz)
                prof->wholding = false;
                prof->wtoggle = 0;
                prof->flushing = false;
+               prof->eod_sent = false;
                runtime·noteclear(&prof->wait);
 
                runtime·setcpuprofilerate(tick, hz);
@@ -409,6 +413,16 @@ breakflush:
        }
 
        // Made it through the table without finding anything to log.
+       if(!p->eod_sent) {
+               // We may not have space to append this to the partial log buf,
+               // so we always return a new slice for the end-of-data marker.
+               p->eod_sent = true;
+               ret.array = (byte*)eod;
+               ret.len = sizeof eod;
+               ret.cap = ret.len;
+               return ret;
+       }
+
        // Finally done.  Clean up and return nil.
        p->flushing = false;
        if(!runtime·cas(&p->handoff, p->handoff, 0))
index 82bb2a2926b20358e30f632a68f69cdbf89a630a..f8d65d483b7ebba124141c46535712d128134ace 100644 (file)
@@ -49,19 +49,25 @@ func TestCPUProfile(t *testing.T) {
 
        // Convert []byte to []uintptr.
        bytes := prof.Bytes()
+       l := len(bytes) / int(unsafe.Sizeof(uintptr(0)))
        val := *(*[]uintptr)(unsafe.Pointer(&bytes))
-       val = val[:len(bytes)/int(unsafe.Sizeof(uintptr(0)))]
+       val = val[:l]
 
-       if len(val) < 10 {
+       if l < 13 {
                t.Fatalf("profile too short: %#x", val)
        }
-       if val[0] != 0 || val[1] != 3 || val[2] != 0 || val[3] != 1e6/100 || val[4] != 0 {
-               t.Fatalf("unexpected header %#x", val[:5])
+
+       hd, val, tl := val[:5], val[5:l-3], val[l-3:]
+       if hd[0] != 0 || hd[1] != 3 || hd[2] != 0 || hd[3] != 1e6/100 || hd[4] != 0 {
+               t.Fatalf("unexpected header %#x", hd)
+       }
+
+       if tl[0] != 0 || tl[1] != 1 || tl[2] != 0 {
+               t.Fatalf("malformed end-of-data marker %#x", tl)
        }
 
        // Check that profile is well formed and contains ChecksumIEEE.
        found := false
-       val = val[5:]
        for len(val) > 0 {
                if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] {
                        t.Fatalf("malformed profile.  leftover: %#x", val)