aboutsummaryrefslogtreecommitdiff
path: root/libgo/runtime/cpuprof.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/runtime/cpuprof.c')
-rw-r--r--libgo/runtime/cpuprof.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index 252948d..9bf5d11 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -105,6 +105,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;
@@ -115,6 +116,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.
@@ -168,6 +171,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);
@@ -414,6 +418,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))