go issue7978go()
// test in c code, before callback
issue7978wait(0, 1)
- issue7978check(t, "runtime.cgocall(", "", 1)
+ issue7978check(t, "_Cfunc_issue7978c(", "", 1)
// test in go code, during callback
issue7978wait(2, 3)
issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
// test in c code, after callback
issue7978wait(4, 5)
- issue7978check(t, "runtime.cgocall(", "runtime.cgocallback", 1)
+ issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
// test in go code, after return from cgo
issue7978wait(6, 7)
issue7978check(t, "test.issue7978go(", "", 3)
pc := getcallerpc(unsafe.Pointer(&buf))
systemstack(func() {
g0 := getg()
+ // Force traceback=1 to override GOTRACEBACK setting,
+ // so that Stack's results are consistent.
+ // GOTRACEBACK is only about crash dumps.
+ g0.m.traceback = 1
g0.writebuf = buf[0:0:len(buf)]
goroutineheader(gp)
traceback(pc, sp, 0, gp)
if all {
tracebackothers(gp)
}
+ g0.m.traceback = 0
n = len(g0.writebuf)
g0.writebuf = nil
})
_g_ := getg()
casgstatus(gp, _Grunning, _Gdead)
+ if isSystemGoroutine(gp) {
+ atomic.Xadd(&sched.ngsys, -1)
+ }
gp.m = nil
gp.lockedm = nil
_g_.m.lockedg = nil
gostartcallfn(&newg.sched, fn)
newg.gopc = callerpc
newg.startpc = fn.fn
+ if isSystemGoroutine(newg) {
+ atomic.Xadd(&sched.ngsys, +1)
+ }
casgstatus(newg, _Gdead, _Grunnable)
if _p_.goidcache == _p_.goidcacheend {
}
func gcount() int32 {
- n := int32(allglen) - sched.ngfree
+ n := int32(allglen) - sched.ngfree - int32(atomic.Load(&sched.ngsys))
for i := 0; ; i++ {
_p_ := allp[i]
if _p_ == nil {
"net"
"runtime"
"runtime/debug"
+ "strings"
"sync"
"sync/atomic"
"syscall"
}
}
+func TestNumGoroutine(t *testing.T) {
+ output := runTestProg(t, "testprog", "NumGoroutine")
+ want := "1\n"
+ if output != want {
+ t.Fatalf("want %q, got %q", want, output)
+ }
+
+ buf := make([]byte, 1<<20)
+ buf = buf[:runtime.Stack(buf, true)]
+
+ n := runtime.NumGoroutine()
+
+ if nstk := strings.Count(string(buf), "goroutine "); n != nstk {
+ t.Fatalf("NumGoroutine=%d, but found %d goroutines in stack dump", n, nstk)
+ }
+}
+
func TestPingPongHog(t *testing.T) {
if testing.Short() {
t.Skip("skipping in -short mode")
)
type schedt struct {
- lock mutex
+ // accessed atomically. keep at top to ensure alignment on 32-bit systems.
+ goidgen uint64
+ lastpoll uint64
- goidgen uint64
+ lock mutex
midle muintptr // idle m's waiting for work
nmidle int32 // number of idle m's waiting for work
mcount int32 // number of m's that have been created
maxmcount int32 // maximum number of m's allowed (or die)
+ ngsys uint32 // number of system goroutines; updated atomically
+
pidle puintptr // idle p's
npidle uint32
nmspinning uint32 // See "Worker thread parking/unparking" comment in proc.go.
stopnote note
sysmonwait uint32
sysmonnote note
- lastpoll uint64
// safepointFn should be called on each P at the next GC
// safepoint if p.runSafePointFn is set.
--- /dev/null
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime"
+
+func init() {
+ register("NumGoroutine", NumGoroutine)
+}
+
+func NumGoroutine() {
+ println(runtime.NumGoroutine())
+}