// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build !goexperiment.exectracer2
+
// Go execution tracer.
// The tracer captures a wide range of execution events like goroutine
// creation/blocking/unblocking, syscall enter/exit/block, GC-related events,
lastP puintptr // last P emitted an event for this goroutine
}
+// Unused; for compatibility with the new tracer.
+func (s *gTraceState) reset() {}
+
// mTraceState is per-M state for the tracer.
type mTraceState struct {
startingTrace bool // this M is in TraceStart, potentially before traceEnabled is true
unlock(&trace.lock)
}
+// ThreadDestroy is a no-op. It exists as a stub to support the new tracer.
+//
+// This must run on the system stack, just to match the new tracer.
+func traceThreadDestroy(_ *m) {
+ // No-op in old tracer.
+}
+
// traceFullQueue queues buf into queue of full buffers.
func traceFullQueue(buf traceBufPtr) {
buf.ptr().link = 0
// traceCPUSample writes a CPU profile sample stack to the execution tracer's
// profiling buffer. It is called from a signal handler, so is limited in what
// it can do.
-func traceCPUSample(gp *g, pp *p, stk []uintptr) {
+func traceCPUSample(gp *g, _ *m, pp *p, stk []uintptr) {
if !traceEnabled() {
// Tracing is usually turned off; don't spend time acquiring the signal
// lock unless it's active.
traceEvent(traceEvGoSysCall, skip)
}
-func (_ traceLocker) GoSysExit() {
+func (_ traceLocker) GoSysExit(lostP bool) {
+ if !lostP {
+ throw("lostP must always be true in the old tracer for GoSysExit")
+ }
gp := getg().m.curg
if !gp.trace.tracedSyscallEnter {
// There was no syscall entry traced for us at all, so there's definitely
traceEvent(traceEvGoSysExit, -1, gp.goid, gp.trace.seq, uint64(ts))
}
+// nosplit because it's called from exitsyscall without a P.
+//
+//go:nosplit
+func (_ traceLocker) RecordSyscallExitedTime(gp *g, oldp *p) {
+ // Wait till traceGoSysBlock event is emitted.
+ // This ensures consistency of the trace (the goroutine is started after it is blocked).
+ for oldp != nil && oldp.syscalltick == gp.m.syscalltick {
+ osyield()
+ }
+ // We can't trace syscall exit right now because we don't have a P.
+ // Tracing code can invoke write barriers that cannot run without a P.
+ // So instead we remember the syscall exit time and emit the event
+ // in execute when we have a P.
+ gp.trace.sysExitTime = traceClockNow()
+}
+
func (_ traceLocker) GoSysBlock(pp *p) {
// Sysmon and stopTheWorld can declare syscalls running on remote Ps as blocked,
// to handle this we temporary employ the P.
releasem(mp)
}
+func (t traceLocker) ProcSteal(pp *p, forMe bool) {
+ t.ProcStop(pp)
+}
+
func (_ traceLocker) HeapAlloc(live uint64) {
traceEvent(traceEvHeapAlloc, -1, live)
}
traceEvent(traceEvGoInSyscall, -1, gp.goid)
}
+// Used only in the new tracer.
+func (tl traceLocker) GoCreateSyscall(gp *g) {
+}
+
+// Used only in the new tracer.
+func (tl traceLocker) GoDestroySyscall() {
+}
+
// traceTime represents a timestamp for the trace.
type traceTime uint64
func traceClockNow() traceTime {
return traceTime(cputicks() / traceTimeDiv)
}
+
+func traceExitingSyscall() {
+}
+
+func traceExitedSyscall() {
+}
+
+// Not used in the old tracer. Defined for compatibility.
+const defaultTraceAdvancePeriod = 0