diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c index 58f287e9066..829448b020f 100644 --- a/src/pkg/runtime/cgocall.c +++ b/src/pkg/runtime/cgocall.c @@ -83,7 +83,6 @@ // callee-save registers for gcc and returns to GoF, which returns to f. void *initcgo; /* filled in by dynamic linker when Cgo is available */ -int64 ncgocall; static void unlockm(void); static void unwindm(void); @@ -101,7 +100,7 @@ runtime·cgocall(void (*fn)(void*), void *arg) if(fn == 0) runtime·throw("cgocall nil"); - ncgocall++; + m->ncgocall++; /* * Lock g to m to ensure we stay on the same stack if we do a @@ -155,7 +154,11 @@ unlockm(void) void runtime·Cgocalls(int64 ret) { - ret = ncgocall; + M *m; + + ret = 0; + for(m=runtime·atomicloadp(&runtime·allm); m; m=m->alllink) + ret += m->ncgocall; FLUSH(&ret); } diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c index 56c8f9bcf90..6416651ce56 100644 --- a/src/pkg/runtime/proc.c +++ b/src/pkg/runtime/proc.c @@ -278,7 +278,9 @@ mcommoninit(M *m) // Add to runtime·allm so garbage collector doesn't free m // when it is just in a register or thread-local storage. m->alllink = runtime·allm; - runtime·allm = m; + // runtime·Cgocalls() iterates over allm w/o schedlock, + // so we need to publish it safely. + runtime·atomicstorep(&runtime·allm, m); m->id = runtime·sched.mcount++; m->fastrand = 0x49f6428aUL + m->id; diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index ef0cc00f943..50c2b0eeca2 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -231,6 +231,7 @@ struct M int32 dying; int32 profilehz; uint32 fastrand; + uint64 ncgocall; Note havenextg; G* nextg; M* alllink; // on allm