aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/proc.c
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2014-01-22 10:30:10 +0400
committerDmitriy Vyukov <dvyukov@google.com>2014-01-22 10:30:10 +0400
commit8a3c587dc1a5f7a9cd87b764b74e28a57935ab40 (patch)
tree9848ee5c4e0a4a46d3b33ac17459100b70154ce8 /src/pkg/runtime/proc.c
parentf69391dd9e33132f5082636ffcfd847d7ac07b53 (diff)
downloadgo-8a3c587dc1a5f7a9cd87b764b74e28a57935ab40.tar.xz
runtime: fix and improve CPU profiling
- do not lose profiling signals when we have no mcache (possible for syscalls/cgo) - do not lose any profiling signals on windows - fix profiling of cgo programs on windows (they had no m->thread setup) - properly setup tls in cgo programs on windows - check _beginthread return value Fixes #6417. Fixes #6986. R=alex.brainman, rsc CC=golang-codereviews https://golang.org/cl/44820047
Diffstat (limited to 'src/pkg/runtime/proc.c')
-rw-r--r--src/pkg/runtime/proc.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index d6732d2c61..92d6f27da3 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -638,6 +638,7 @@ struct CgoThreadStart
{
M *m;
G *g;
+ uintptr *tls;
void (*fn)(void);
};
@@ -916,6 +917,7 @@ newm(void(*fn)(void), P *p)
runtime·throw("_cgo_thread_start missing");
ts.m = mp;
ts.g = mp->g0;
+ ts.tls = mp->tls;
ts.fn = runtime·mstart;
runtime·asmcgocall(_cgo_thread_start, &ts);
return;
@@ -2074,18 +2076,25 @@ System(void)
// Called if we receive a SIGPROF signal.
void
-runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
+runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp, M *mp)
{
int32 n;
bool traceback;
+ MCache *mcache;
+ // Do not use global m in this function, use mp instead.
+ // On windows one m is sending reports about all the g's, so m means a wrong thing.
+ byte m;
+
+ m = 0;
+ USED(m);
if(prof.fn == nil || prof.hz == 0)
return;
- traceback = true;
- // Windows does profiling in a dedicated thread w/o m.
- if(!Windows && (m == nil || m->mcache == nil))
- traceback = false;
-
+
+ // Profiling runs concurrently with GC, so it must not allocate.
+ mcache = mp->mcache;
+ mp->mcache = nil;
+
// Define that a "user g" is a user-created goroutine, and a "system g"
// is one that is m->g0 or m->gsignal. We've only made sure that we
// can unwind user g's, so exclude the system g's.
@@ -2158,24 +2167,21 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
// To recap, there are no constraints on the assembly being used for the
// transition. We simply require that g and SP match and that the PC is not
// in runtime.gogo.
- //
- // On Windows, one m is sending reports about all the g's, so gp == m->curg
- // is not a useful comparison. The profilem function in os_windows.c has
- // already checked that gp is a user g.
- if(gp == nil ||
- (!Windows && gp != m->curg) ||
+ traceback = true;
+ if(gp == nil || gp != mp->curg ||
(uintptr)sp < gp->stackguard - StackGuard || gp->stackbase < (uintptr)sp ||
((uint8*)runtime·gogo <= pc && pc < (uint8*)runtime·gogo + RuntimeGogoBytes))
traceback = false;
// Race detector calls asmcgocall w/o entersyscall/exitsyscall,
// we can not currently unwind through asmcgocall.
- if(m != nil && m->racecall)
+ if(mp != nil && mp->racecall)
traceback = false;
runtime·lock(&prof);
if(prof.fn == nil) {
runtime·unlock(&prof);
+ mp->mcache = mcache;
return;
}
n = 0;
@@ -2188,6 +2194,7 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
}
prof.fn(prof.pcbuf, n);
runtime·unlock(&prof);
+ mp->mcache = mcache;
}
// Arrange to call fn with a traceback hz times a second.