runtime: use -fgo-c-header to build C header file
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 30 Aug 2016 21:07:47 +0000 (21:07 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 30 Aug 2016 21:07:47 +0000 (21:07 +0000)
    Use the new -fgo-c-header option to build a header file for the Go
    runtime code in libgo/go/runtime, and use the new header file in the C
    runtime code in libgo/runtime.  This will ensure that the Go code and C
    code share the same data structures as we convert the runtime from C to
    Go.

    The new file libgo/go/runtime/runtime2.go is copied from the Go 1.7
    release, and then edited to remove unnecessary data structures and
    modify others for use with libgo.

    The new file libgo/go/runtime/mcache.go is an initial version of the
    same files in the Go 1.7 release, and will be replaced by the Go 1.7
    file when we convert to the new memory allocator.

    The new file libgo/go/runtime/type.go describes the gccgo version of the
    reflection data structures, and replaces the Go 1.7 runtime file which
    describes the gc version of those structures.

    Using the new header file means changing a number of struct fields to
    use Go naming conventions (that is, no underscores) and to rename
    constants to have a leading underscore so that they are not exported
    from the Go package.  These names were updated in the C code.

    The C code was also changed to drop the thread-local variable m, as was
    done some time ago in the gc sources.  Now the m field is always
    accessed using g->m, where g is the single remaining thread-local
    variable.  This in turn required some adjustments to set g->m correctly
    in all cases.

    Also pass the new -fgo-compiling-runtime option when compiling the
    runtime package, although that option doesn't do anything yet.

    Reviewed-on: https://go-review.googlesource.com/28051

From-SVN: r239872

33 files changed:
gcc/go/gofrontend/MERGE
libgo/Makefile.am
libgo/Makefile.in
libgo/go/runtime/mcache.go [new file with mode: 0644]
libgo/go/runtime/runtime2.go [new file with mode: 0644]
libgo/go/runtime/type.go [new file with mode: 0644]
libgo/mksysinfo.sh
libgo/runtime/go-cgo.c
libgo/runtime/go-defer.c
libgo/runtime/go-defer.h [deleted file]
libgo/runtime/go-deferred-recover.c
libgo/runtime/go-panic.c
libgo/runtime/go-panic.h
libgo/runtime/go-recover.c
libgo/runtime/go-signal.c
libgo/runtime/go-unwind.c
libgo/runtime/heapdump.c
libgo/runtime/lock_sema.c
libgo/runtime/malloc.goc
libgo/runtime/malloc.h
libgo/runtime/mcache.c
libgo/runtime/mcentral.c
libgo/runtime/mgc0.c
libgo/runtime/mheap.c
libgo/runtime/mprof.goc
libgo/runtime/msize.c
libgo/runtime/netpoll.goc
libgo/runtime/panic.c
libgo/runtime/proc.c
libgo/runtime/runtime.c
libgo/runtime/runtime.h
libgo/runtime/runtime1.goc
libgo/runtime/signal_unix.c

index e92aee31835ee3f5729e9387ae1d2d4fea25f32a..633dfcfdd8aae3f3bc1073147b11ad4ae98a9dc6 100644 (file)
@@ -1,4 +1,4 @@
-9c91e7eeb404b5b639cd6e80e2a38da948bb35ec
+394486a1cec9bbb81216311ed153179d9fe1c2c5
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 589ae66b61b0ab42823fd84d9870e5bb0b132b77..0a54a8972c5bcdeab201c4555ba3073ffd6fb2c5 100644 (file)
@@ -595,6 +595,16 @@ s-version: Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
        $(STAMP) $@
 
+runtime_sysinfo.go: s-runtime_sysinfo; @true
+s-runtime_sysinfo: sysinfo.go
+       rm -f tmp-runtime_sysinfo.go
+       echo 'package runtime' > tmp-runtime_sysinfo.go
+       echo >> tmp-runtime_sysinfo.go
+       grep 'const _sizeof_ucontext_t ' sysinfo.go >> tmp-runtime_sysinfo.go
+       grep 'type _sigset_t ' sysinfo.go >> tmp-runtime_sysinfo.go
+       $(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime_sysinfo.go runtime_sysinfo.go
+       $(STAMP) $@
+
 noinst_DATA = zstdpkglist.go
 
 # Generate the list of go std packages that were included in libgo
@@ -877,6 +887,13 @@ libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -fPIC
 libnetgo_a_SOURCES =
 libnetgo_a_LIBADD = netgo.o
 
+# Make sure runtime.inc is built before compiling any .c file.
+$(libgo_la_OBJECTS): runtime.inc
+$(libgo_llgo_la_OBJECTS): runtime.inc
+$(libgobegin_a_OBJECTS): runtime.inc
+$(libgobegin_llgo_a_OBJECTS): runtime.inc
+$(libgolibbegin_a_OBJECTS): runtime.inc
+
 LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
 
 GOCFLAGS = $(CFLAGS)
@@ -904,7 +921,7 @@ BUILDDEPS = \
 BUILDPACKAGE = \
        $(MKDIR_P) $(@D); \
        files=`echo $^ | sed -e 's/[^ ]*\.gox//g' -e 's/[^ ]*\.dep//'`; \
-       $(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` -o $@ $$files
+       $(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` $($(subst -,_,$(subst .,_,$(subst /,_,$@)))_GOCFLAGS) -o $@ $$files
 
 # Build deps for netgo.o.
 BUILDNETGODEPS = \
@@ -1006,7 +1023,7 @@ bytes.lo.dep: $(srcdir)/go/bytes/*.go
        $(BUILDDEPS)
 bytes.lo:
        $(BUILDPACKAGE)
-bytes/index.lo: go/bytes/indexbyte.c
+bytes/index.lo: go/bytes/indexbyte.c runtime.inc
        @$(MKDIR_P) bytes
        $(LTCOMPILE) -c -o bytes/index.lo $(srcdir)/go/bytes/indexbyte.c
 bytes/check: $(CHECK_DEPS)
@@ -1191,7 +1208,7 @@ reflect-go.lo:
        $(BUILDPACKAGE)
 reflect/check: $(CHECK_DEPS)
        @$(CHECK)
-reflect/makefunc_ffi_c.lo: go/reflect/makefunc_ffi_c.c
+reflect/makefunc_ffi_c.lo: go/reflect/makefunc_ffi_c.c runtime.inc
        @$(MKDIR_P) reflect
        $(LTCOMPILE) -c -o $@ $<
 .PHONY: reflect/check
@@ -1205,13 +1222,18 @@ regexp/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: regexp/check
 
-extra_go_files_runtime = version.go
+extra_go_files_runtime = runtime_sysinfo.go version.go
 
 @go_include@ runtime-go.lo.dep
-runtime-go.lo.dep: $(srcdir)/go/runtime/*.go
+runtime-go.lo.dep: $(srcdir)/go/runtime/*.go $(extra_go_files_runtime)
        $(BUILDDEPS)
+runtime_go_lo_GOCFLAGS = -fgo-c-header=runtime.inc.tmp -fgo-compiling-runtime
 runtime-go.lo:
        $(BUILDPACKAGE)
+runtime.inc: s-runtime-inc; @true
+s-runtime-inc: runtime-go.lo
+       $(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp runtime.inc
+       $(STAMP) $@
 runtime/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: runtime/check
@@ -1239,7 +1261,7 @@ strings.lo.dep: $(srcdir)/go/strings/*.go
        $(BUILDDEPS)
 strings.lo:
        $(BUILDPACKAGE)
-strings/index.lo: go/strings/indexbyte.c
+strings/index.lo: go/strings/indexbyte.c runtime.inc
        @$(MKDIR_P) strings
        $(LTCOMPILE) -c -o strings/index.lo $(srcdir)/go/strings/indexbyte.c
 strings/check: $(CHECK_DEPS)
@@ -2062,7 +2084,7 @@ log/syslog.lo.dep: $(srcdir)/go/log/syslog/*.go
        $(BUILDDEPS)
 log/syslog.lo:
        $(BUILDPACKAGE)
-log/syslog/syslog_c.lo: go/log/syslog/syslog_c.c log/syslog.lo
+log/syslog/syslog_c.lo: go/log/syslog/syslog_c.c runtime.inc log/syslog.lo
        @$(MKDIR_P) log/syslog
        $(LTCOMPILE) -c -o $@ $(srcdir)/go/log/syslog/syslog_c.c
 log/syslog/check: $(CHECK_DEPS)
@@ -2348,7 +2370,7 @@ sync/atomic.lo.dep: $(srcdir)/go/sync/atomic/*.go
        $(BUILDDEPS)
 sync/atomic.lo:
        $(BUILDPACKAGE)
-sync/atomic_c.lo: go/sync/atomic/atomic.c sync/atomic.lo
+sync/atomic_c.lo: go/sync/atomic/atomic.c runtime.inc sync/atomic.lo
        $(LTCOMPILE) -c -o $@ $(srcdir)/go/sync/atomic/atomic.c
 sync/atomic/check: $(CHECK_DEPS)
        @$(CHECK)
@@ -2427,17 +2449,17 @@ unicode/utf8/check: $(CHECK_DEPS)
 .PHONY: unicode/utf8/check
 
 @go_include@ syscall.lo.dep
-syscall.lo.dep: $(srcdir)/go/syscall/*.go
+syscall.lo.dep: $(srcdir)/go/syscall/*.go $(extra_go_files_syscall)
        $(BUILDDEPS)
 syscall.lo:
        $(BUILDPACKAGE)
-syscall/errno.lo: go/syscall/errno.c
+syscall/errno.lo: go/syscall/errno.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
-syscall/signame.lo: go/syscall/signame.c
+syscall/signame.lo: go/syscall/signame.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
-syscall/wait.lo: go/syscall/wait.c
+syscall/wait.lo: go/syscall/wait.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
 syscall/check: $(CHECK_DEPS)
index 568683a7b0ace53977478f19069172577a1b19a2..d9c510028b681cf5ca11896b390f699dc56a7ca2 100644 (file)
@@ -1162,7 +1162,7 @@ BUILDDEPS = \
 BUILDPACKAGE = \
        $(MKDIR_P) $(@D); \
        files=`echo $^ | sed -e 's/[^ ]*\.gox//g' -e 's/[^ ]*\.dep//'`; \
-       $(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` -o $@ $$files
+       $(LTGOCOMPILE) -I . -c -fgo-pkgpath=`echo $@ | sed -e 's/.lo$$//' -e 's/-go$$//'` $($(subst -,_,$(subst .,_,$(subst /,_,$@)))_GOCFLAGS) -o $@ $$files
 
 
 # Build deps for netgo.o.
@@ -1235,7 +1235,8 @@ CHECK_DEPS = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
 @HAVE_STAT_TIMESPEC_FALSE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os = 
 @HAVE_STAT_TIMESPEC_TRUE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os = --tag=solaristag
 @LIBGO_IS_SOLARIS_FALSE@matchargs_os = 
-extra_go_files_runtime = version.go
+extra_go_files_runtime = runtime_sysinfo.go version.go
+runtime_go_lo_GOCFLAGS = -fgo-c-header=runtime.inc.tmp -fgo-compiling-runtime
 @LIBGO_IS_BSD_TRUE@golang_org_x_net_route_lo = \
 @LIBGO_IS_BSD_TRUE@    golang_org/x/net/route/route.lo
 
@@ -3570,6 +3571,16 @@ s-version: Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh version.go.tmp version.go
        $(STAMP) $@
 
+runtime_sysinfo.go: s-runtime_sysinfo; @true
+s-runtime_sysinfo: sysinfo.go
+       rm -f tmp-runtime_sysinfo.go
+       echo 'package runtime' > tmp-runtime_sysinfo.go
+       echo >> tmp-runtime_sysinfo.go
+       grep 'const _sizeof_ucontext_t ' sysinfo.go >> tmp-runtime_sysinfo.go
+       grep 'type _sigset_t ' sysinfo.go >> tmp-runtime_sysinfo.go
+       $(SHELL) $(srcdir)/mvifdiff.sh tmp-runtime_sysinfo.go runtime_sysinfo.go
+       $(STAMP) $@
+
 # Generate the list of go std packages that were included in libgo
 zstdpkglist.go: s-zstdpkglist; @true
 s-zstdpkglist: Makefile
@@ -3639,6 +3650,13 @@ s-epoll: Makefile
        $(SHELL) $(srcdir)/mvifdiff.sh epoll.go.tmp epoll.go
        $(STAMP) $@
 
+# Make sure runtime.inc is built before compiling any .c file.
+$(libgo_la_OBJECTS): runtime.inc
+$(libgo_llgo_la_OBJECTS): runtime.inc
+$(libgobegin_a_OBJECTS): runtime.inc
+$(libgobegin_llgo_a_OBJECTS): runtime.inc
+$(libgolibbegin_a_OBJECTS): runtime.inc
+
 @go_include@ bufio.lo.dep
 bufio.lo.dep: $(srcdir)/go/bufio/*.go
        $(BUILDDEPS)
@@ -3653,7 +3671,7 @@ bytes.lo.dep: $(srcdir)/go/bytes/*.go
        $(BUILDDEPS)
 bytes.lo:
        $(BUILDPACKAGE)
-bytes/index.lo: go/bytes/indexbyte.c
+bytes/index.lo: go/bytes/indexbyte.c runtime.inc
        @$(MKDIR_P) bytes
        $(LTCOMPILE) -c -o bytes/index.lo $(srcdir)/go/bytes/indexbyte.c
 bytes/check: $(CHECK_DEPS)
@@ -3828,7 +3846,7 @@ reflect-go.lo:
        $(BUILDPACKAGE)
 reflect/check: $(CHECK_DEPS)
        @$(CHECK)
-reflect/makefunc_ffi_c.lo: go/reflect/makefunc_ffi_c.c
+reflect/makefunc_ffi_c.lo: go/reflect/makefunc_ffi_c.c runtime.inc
        @$(MKDIR_P) reflect
        $(LTCOMPILE) -c -o $@ $<
 .PHONY: reflect/check
@@ -3843,10 +3861,14 @@ regexp/check: $(CHECK_DEPS)
 .PHONY: regexp/check
 
 @go_include@ runtime-go.lo.dep
-runtime-go.lo.dep: $(srcdir)/go/runtime/*.go
+runtime-go.lo.dep: $(srcdir)/go/runtime/*.go $(extra_go_files_runtime)
        $(BUILDDEPS)
 runtime-go.lo:
        $(BUILDPACKAGE)
+runtime.inc: s-runtime-inc; @true
+s-runtime-inc: runtime-go.lo
+       $(SHELL) $(srcdir)/mvifdiff.sh runtime.inc.tmp runtime.inc
+       $(STAMP) $@
 runtime/check: $(CHECK_DEPS)
        @$(CHECK)
 .PHONY: runtime/check
@@ -3874,7 +3896,7 @@ strings.lo.dep: $(srcdir)/go/strings/*.go
        $(BUILDDEPS)
 strings.lo:
        $(BUILDPACKAGE)
-strings/index.lo: go/strings/indexbyte.c
+strings/index.lo: go/strings/indexbyte.c runtime.inc
        @$(MKDIR_P) strings
        $(LTCOMPILE) -c -o strings/index.lo $(srcdir)/go/strings/indexbyte.c
 strings/check: $(CHECK_DEPS)
@@ -4688,7 +4710,7 @@ log/syslog.lo.dep: $(srcdir)/go/log/syslog/*.go
        $(BUILDDEPS)
 log/syslog.lo:
        $(BUILDPACKAGE)
-log/syslog/syslog_c.lo: go/log/syslog/syslog_c.c log/syslog.lo
+log/syslog/syslog_c.lo: go/log/syslog/syslog_c.c runtime.inc log/syslog.lo
        @$(MKDIR_P) log/syslog
        $(LTCOMPILE) -c -o $@ $(srcdir)/go/log/syslog/syslog_c.c
 log/syslog/check: $(CHECK_DEPS)
@@ -4970,7 +4992,7 @@ sync/atomic.lo.dep: $(srcdir)/go/sync/atomic/*.go
        $(BUILDDEPS)
 sync/atomic.lo:
        $(BUILDPACKAGE)
-sync/atomic_c.lo: go/sync/atomic/atomic.c sync/atomic.lo
+sync/atomic_c.lo: go/sync/atomic/atomic.c runtime.inc sync/atomic.lo
        $(LTCOMPILE) -c -o $@ $(srcdir)/go/sync/atomic/atomic.c
 sync/atomic/check: $(CHECK_DEPS)
        @$(CHECK)
@@ -5049,17 +5071,17 @@ unicode/utf8/check: $(CHECK_DEPS)
 .PHONY: unicode/utf8/check
 
 @go_include@ syscall.lo.dep
-syscall.lo.dep: $(srcdir)/go/syscall/*.go
+syscall.lo.dep: $(srcdir)/go/syscall/*.go $(extra_go_files_syscall)
        $(BUILDDEPS)
 syscall.lo:
        $(BUILDPACKAGE)
-syscall/errno.lo: go/syscall/errno.c
+syscall/errno.lo: go/syscall/errno.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
-syscall/signame.lo: go/syscall/signame.c
+syscall/signame.lo: go/syscall/signame.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
-syscall/wait.lo: go/syscall/wait.c
+syscall/wait.lo: go/syscall/wait.c runtime.inc
        @$(MKDIR_P) syscall
        $(LTCOMPILE) -c -o $@ $<
 syscall/check: $(CHECK_DEPS)
diff --git a/libgo/go/runtime/mcache.go b/libgo/go/runtime/mcache.go
new file mode 100644 (file)
index 0000000..e383e0d
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2009 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 runtime
+
+// This is a temporary mcache.go for gccgo.
+// At some point it will be replaced by the one in the gc runtime package.
+
+import "unsafe"
+
+const (
+       // Computed constant. The definition of MaxSmallSize and the
+       // algorithm in msize.go produces some number of different allocation
+       // size classes. NumSizeClasses is that number. It's needed here
+       // because there are static arrays of this length; when msize runs its
+       // size choosing algorithm it double-checks that NumSizeClasses agrees.
+       _NumSizeClasses = 67
+)
+
+type mcachelist struct {
+       list  *mlink
+       nlist uint32
+}
+
+// Per-thread (in Go, per-P) cache for small objects.
+// No locking needed because it is per-thread (per-P).
+//
+// mcaches are allocated from non-GC'd memory, so any heap pointers
+// must be specially handled.
+type mcache struct {
+       // The following members are accessed on every malloc,
+       // so they are grouped here for better caching.
+       next_sample      int32   // trigger heap sample after allocating this many bytes
+       local_cachealloc uintptr // bytes allocated (or freed) from cache since last lock of heap
+
+       // Allocator cache for tiny objects w/o pointers.
+       // See "Tiny allocator" comment in malloc.go.
+
+       // tiny points to the beginning of the current tiny block, or
+       // nil if there is no current tiny block.
+       //
+       // tiny is a heap pointer. Since mcache is in non-GC'd memory,
+       // we handle it by clearing it in releaseAll during mark
+       // termination.
+       tiny     unsafe.Pointer
+       tinysize uintptr
+
+       // The rest is not accessed on every malloc.
+       alloc [_NumSizeClasses]*mspan     // spans to allocate from
+       free  [_NumSizeClasses]mcachelist // lists of explicitly freed objects
+
+       // Local allocator stats, flushed during GC.
+       local_nlookup    uintptr                  // number of pointer lookups
+       local_largefree  uintptr                  // bytes freed for large objects (>maxsmallsize)
+       local_nlargefree uintptr                  // number of frees for large objects (>maxsmallsize)
+       local_nsmallfree [_NumSizeClasses]uintptr // number of frees for small objects (<=maxsmallsize)
+}
+
+type mtypes struct {
+       compression byte
+       data        uintptr
+}
+
+type special struct {
+       next   *special
+       offset uint16
+       kind   byte
+}
+
+type mspan struct {
+       next     *mspan // next span in list, or nil if none
+       prev     *mspan // previous span's next field, or list head's first field if none
+       start    uintptr
+       npages   uintptr // number of pages in span
+       freelist *mlink
+
+       // sweep generation:
+       // if sweepgen == h->sweepgen - 2, the span needs sweeping
+       // if sweepgen == h->sweepgen - 1, the span is currently being swept
+       // if sweepgen == h->sweepgen, the span is swept and ready to use
+       // h->sweepgen is incremented by 2 after every GC
+
+       sweepgen    uint32
+       ref         uint16
+       sizeclass   uint8   // size class
+       incache     bool    // being used by an mcache
+       state       uint8   // mspaninuse etc
+       needzero    uint8   // needs to be zeroed before allocation
+       elemsize    uintptr // computed from sizeclass or from npages
+       unusedsince int64   // first time spotted by gc in mspanfree state
+       npreleased  uintptr // number of pages released to the os
+       limit       uintptr // end of data in span
+       types       mtypes
+       speciallock mutex    // guards specials list
+       specials    *special // linked list of special records sorted by offset.
+       freebuf     *mlink
+}
+
+type mlink struct {
+       next *mlink
+}
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
new file mode 100644 (file)
index 0000000..05ce513
--- /dev/null
@@ -0,0 +1,835 @@
+// Copyright 2009 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 runtime
+
+import (
+       "unsafe"
+)
+
+// defined constants
+const (
+       // G status
+       //
+       // Beyond indicating the general state of a G, the G status
+       // acts like a lock on the goroutine's stack (and hence its
+       // ability to execute user code).
+       //
+       // If you add to this list, add to the list
+       // of "okay during garbage collection" status
+       // in mgcmark.go too.
+
+       // _Gidle means this goroutine was just allocated and has not
+       // yet been initialized.
+       _Gidle = iota // 0
+
+       // _Grunnable means this goroutine is on a run queue. It is
+       // not currently executing user code. The stack is not owned.
+       _Grunnable // 1
+
+       // _Grunning means this goroutine may execute user code. The
+       // stack is owned by this goroutine. It is not on a run queue.
+       // It is assigned an M and a P.
+       _Grunning // 2
+
+       // _Gsyscall means this goroutine is executing a system call.
+       // It is not executing user code. The stack is owned by this
+       // goroutine. It is not on a run queue. It is assigned an M.
+       _Gsyscall // 3
+
+       // _Gwaiting means this goroutine is blocked in the runtime.
+       // It is not executing user code. It is not on a run queue,
+       // but should be recorded somewhere (e.g., a channel wait
+       // queue) so it can be ready()d when necessary. The stack is
+       // not owned *except* that a channel operation may read or
+       // write parts of the stack under the appropriate channel
+       // lock. Otherwise, it is not safe to access the stack after a
+       // goroutine enters _Gwaiting (e.g., it may get moved).
+       _Gwaiting // 4
+
+       // _Gmoribund_unused is currently unused, but hardcoded in gdb
+       // scripts.
+       _Gmoribund_unused // 5
+
+       // _Gdead means this goroutine is currently unused. It may be
+       // just exited, on a free list, or just being initialized. It
+       // is not executing user code. It may or may not have a stack
+       // allocated. The G and its stack (if any) are owned by the M
+       // that is exiting the G or that obtained the G from the free
+       // list.
+       _Gdead // 6
+
+       // _Genqueue_unused is currently unused.
+       _Genqueue_unused // 7
+
+       // _Gcopystack means this goroutine's stack is being moved. It
+       // is not executing user code and is not on a run queue. The
+       // stack is owned by the goroutine that put it in _Gcopystack.
+       _Gcopystack // 8
+
+       // _Gscan combined with one of the above states other than
+       // _Grunning indicates that GC is scanning the stack. The
+       // goroutine is not executing user code and the stack is owned
+       // by the goroutine that set the _Gscan bit.
+       //
+       // _Gscanrunning is different: it is used to briefly block
+       // state transitions while GC signals the G to scan its own
+       // stack. This is otherwise like _Grunning.
+       //
+       // atomicstatus&~Gscan gives the state the goroutine will
+       // return to when the scan completes.
+       _Gscan         = 0x1000
+       _Gscanrunnable = _Gscan + _Grunnable // 0x1001
+       _Gscanrunning  = _Gscan + _Grunning  // 0x1002
+       _Gscansyscall  = _Gscan + _Gsyscall  // 0x1003
+       _Gscanwaiting  = _Gscan + _Gwaiting  // 0x1004
+)
+
+const (
+       // P status
+       _Pidle    = iota
+       _Prunning // Only this P is allowed to change from _Prunning.
+       _Psyscall
+       _Pgcstop
+       _Pdead
+)
+
+// Mutual exclusion locks.  In the uncontended case,
+// as fast as spin locks (just a few user-level instructions),
+// but on the contention path they sleep in the kernel.
+// A zeroed Mutex is unlocked (no need to initialize each lock).
+type mutex struct {
+       // Futex-based impl treats it as uint32 key,
+       // while sema-based impl as M* waitm.
+       // Used to be a union, but unions break precise GC.
+       key uintptr
+}
+
+// sleep and wakeup on one-time events.
+// before any calls to notesleep or notewakeup,
+// must call noteclear to initialize the Note.
+// then, exactly one thread can call notesleep
+// and exactly one thread can call notewakeup (once).
+// once notewakeup has been called, the notesleep
+// will return.  future notesleep will return immediately.
+// subsequent noteclear must be called only after
+// previous notesleep has returned, e.g. it's disallowed
+// to call noteclear straight after notewakeup.
+//
+// notetsleep is like notesleep but wakes up after
+// a given number of nanoseconds even if the event
+// has not yet happened.  if a goroutine uses notetsleep to
+// wake up early, it must wait to call noteclear until it
+// can be sure that no other goroutine is calling
+// notewakeup.
+//
+// notesleep/notetsleep are generally called on g0,
+// notetsleepg is similar to notetsleep but is called on user g.
+type note struct {
+       // Futex-based impl treats it as uint32 key,
+       // while sema-based impl as M* waitm.
+       // Used to be a union, but unions break precise GC.
+       key uintptr
+}
+
+type funcval struct {
+       fn uintptr
+       // variable-size, fn-specific data here
+}
+
+type iface struct {
+       tab  unsafe.Pointer
+       data unsafe.Pointer
+}
+
+type eface struct {
+       _type *_type
+       data  unsafe.Pointer
+}
+
+func efaceOf(ep *interface{}) *eface {
+       return (*eface)(unsafe.Pointer(ep))
+}
+
+// The guintptr, muintptr, and puintptr are all used to bypass write barriers.
+// It is particularly important to avoid write barriers when the current P has
+// been released, because the GC thinks the world is stopped, and an
+// unexpected write barrier would not be synchronized with the GC,
+// which can lead to a half-executed write barrier that has marked the object
+// but not queued it. If the GC skips the object and completes before the
+// queuing can occur, it will incorrectly free the object.
+//
+// We tried using special assignment functions invoked only when not
+// holding a running P, but then some updates to a particular memory
+// word went through write barriers and some did not. This breaks the
+// write barrier shadow checking mode, and it is also scary: better to have
+// a word that is completely ignored by the GC than to have one for which
+// only a few updates are ignored.
+//
+// Gs, Ms, and Ps are always reachable via true pointers in the
+// allgs, allm, and allp lists or (during allocation before they reach those lists)
+// from stack variables.
+
+// A guintptr holds a goroutine pointer, but typed as a uintptr
+// to bypass write barriers. It is used in the Gobuf goroutine state
+// and in scheduling lists that are manipulated without a P.
+//
+// The Gobuf.g goroutine pointer is almost always updated by assembly code.
+// In one of the few places it is updated by Go code - func save - it must be
+// treated as a uintptr to avoid a write barrier being emitted at a bad time.
+// Instead of figuring out how to emit the write barriers missing in the
+// assembly manipulation, we change the type of the field to uintptr,
+// so that it does not require write barriers at all.
+//
+// Goroutine structs are published in the allg list and never freed.
+// That will keep the goroutine structs from being collected.
+// There is never a time that Gobuf.g's contain the only references
+// to a goroutine: the publishing of the goroutine in allg comes first.
+// Goroutine pointers are also kept in non-GC-visible places like TLS,
+// so I can't see them ever moving. If we did want to start moving data
+// in the GC, we'd need to allocate the goroutine structs from an
+// alternate arena. Using guintptr doesn't make that problem any worse.
+type guintptr uintptr
+
+//go:nosplit
+func (gp guintptr) ptr() *g { return (*g)(unsafe.Pointer(gp)) }
+
+//go:nosplit
+func (gp *guintptr) set(g *g) { *gp = guintptr(unsafe.Pointer(g)) }
+
+/*
+//go:nosplit
+func (gp *guintptr) cas(old, new guintptr) bool {
+       return atomic.Casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
+}
+*/
+
+type puintptr uintptr
+
+//go:nosplit
+func (pp puintptr) ptr() *p { return (*p)(unsafe.Pointer(pp)) }
+
+//go:nosplit
+func (pp *puintptr) set(p *p) { *pp = puintptr(unsafe.Pointer(p)) }
+
+type muintptr uintptr
+
+//go:nosplit
+func (mp muintptr) ptr() *m { return (*m)(unsafe.Pointer(mp)) }
+
+//go:nosplit
+func (mp *muintptr) set(m *m) { *mp = muintptr(unsafe.Pointer(m)) }
+
+// sudog represents a g in a wait list, such as for sending/receiving
+// on a channel.
+//
+// sudog is necessary because the g â†” synchronization object relation
+// is many-to-many. A g can be on many wait lists, so there may be
+// many sudogs for one g; and many gs may be waiting on the same
+// synchronization object, so there may be many sudogs for one object.
+//
+// sudogs are allocated from a special pool. Use acquireSudog and
+// releaseSudog to allocate and free them.
+/*
+Commented out for gccgo for now.
+
+type sudog struct {
+       // The following fields are protected by the hchan.lock of the
+       // channel this sudog is blocking on. shrinkstack depends on
+       // this.
+
+       g          *g
+       selectdone *uint32 // CAS to 1 to win select race (may point to stack)
+       next       *sudog
+       prev       *sudog
+       elem       unsafe.Pointer // data element (may point to stack)
+
+       // The following fields are never accessed concurrently.
+       // waitlink is only accessed by g.
+
+       releasetime int64
+       ticket      uint32
+       waitlink    *sudog // g.waiting list
+       c           *hchan // channel
+}
+*/
+
+type gcstats struct {
+       // the struct must consist of only uint64's,
+       // because it is casted to uint64[].
+       nhandoff    uint64
+       nhandoffcnt uint64
+       nprocyield  uint64
+       nosyield    uint64
+       nsleep      uint64
+}
+
+/*
+Not used by gccgo.
+
+type libcall struct {
+       fn   uintptr
+       n    uintptr // number of parameters
+       args uintptr // parameters
+       r1   uintptr // return values
+       r2   uintptr
+       err  uintptr // error number
+}
+
+*/
+
+/*
+Not used by gccgo.
+
+// describes how to handle callback
+type wincallbackcontext struct {
+       gobody       unsafe.Pointer // go function to call
+       argsize      uintptr        // callback arguments size (in bytes)
+       restorestack uintptr        // adjust stack on return by (in bytes) (386 only)
+       cleanstack   bool
+}
+*/
+
+/*
+Not used by gccgo.
+
+// Stack describes a Go execution stack.
+// The bounds of the stack are exactly [lo, hi),
+// with no implicit data structures on either side.
+type stack struct {
+       lo uintptr
+       hi uintptr
+}
+
+// stkbar records the state of a G's stack barrier.
+type stkbar struct {
+       savedLRPtr uintptr // location overwritten by stack barrier PC
+       savedLRVal uintptr // value overwritten at savedLRPtr
+}
+*/
+
+type g struct {
+       // Stack parameters.
+       // stack describes the actual stack memory: [stack.lo, stack.hi).
+       // stackguard0 is the stack pointer compared in the Go stack growth prologue.
+       // It is stack.lo+StackGuard normally, but can be StackPreempt to trigger a preemption.
+       // stackguard1 is the stack pointer compared in the C stack growth prologue.
+       // It is stack.lo+StackGuard on g0 and gsignal stacks.
+       // It is ~0 on other goroutine stacks, to trigger a call to morestackc (and crash).
+       // Not for gccgo: stack       stack   // offset known to runtime/cgo
+       // Not for gccgo: stackguard0 uintptr // offset known to liblink
+       // Not for gccgo: stackguard1 uintptr // offset known to liblink
+
+       _panic *_panic // innermost panic - offset known to liblink
+       _defer *_defer // innermost defer
+       m      *m      // current m; offset known to arm liblink
+       // Not for gccgo: stackAlloc     uintptr // stack allocation is [stack.lo,stack.lo+stackAlloc)
+       // Not for gccgo: sched          gobuf
+       // Not for gccgo: syscallsp      uintptr        // if status==Gsyscall, syscallsp = sched.sp to use during gc
+       // Not for gccgo: syscallpc      uintptr        // if status==Gsyscall, syscallpc = sched.pc to use during gc
+       // Not for gccgo: stkbar         []stkbar       // stack barriers, from low to high (see top of mstkbar.go)
+       // Not for gccgo: stkbarPos      uintptr        // index of lowest stack barrier not hit
+       // Not for gccgo: stktopsp       uintptr        // expected sp at top of stack, to check in traceback
+       param        unsafe.Pointer // passed parameter on wakeup
+       atomicstatus uint32
+       // Not for gccgo: stackLock      uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
+       goid           int64
+       waitsince      int64  // approx time when the g become blocked
+       waitreason     string // if status==Gwaiting
+       schedlink      guintptr
+       preempt        bool     // preemption signal, duplicates stackguard0 = stackpreempt
+       paniconfault   bool     // panic (instead of crash) on unexpected fault address
+       preemptscan    bool     // preempted g does scan for gc
+       gcscandone     bool     // g has scanned stack; protected by _Gscan bit in status
+       gcscanvalid    bool     // false at start of gc cycle, true if G has not run since last scan; transition from true to false by calling queueRescan and false to true by calling dequeueRescan
+       throwsplit     bool     // must not split stack
+       raceignore     int8     // ignore race detection events
+       sysblocktraced bool     // StartTrace has emitted EvGoInSyscall about this goroutine
+       sysexitticks   int64    // cputicks when syscall has returned (for tracing)
+       traceseq       uint64   // trace event sequencer
+       tracelastp     puintptr // last P emitted an event for this goroutine
+       lockedm        *m
+       sig            uint32
+
+       // Temporary gccgo field.
+       writenbuf int32
+       // Not for gccgo yet: writebuf       []byte
+       // Temporary different type for gccgo.
+       writebuf *byte
+
+       sigcode0 uintptr
+       sigcode1 uintptr
+       sigpc    uintptr
+       gopc     uintptr // pc of go statement that created this goroutine
+       startpc  uintptr // pc of goroutine function
+       racectx  uintptr
+       // Not for gccgo for now: waiting        *sudog    // sudog structures this g is waiting on (that have a valid elem ptr); in lock order
+       // Not for gccgo: cgoCtxt        []uintptr // cgo traceback context
+
+       // Per-G GC state
+
+       // gcRescan is this G's index in work.rescan.list. If this is
+       // -1, this G is not on the rescan list.
+       //
+       // If gcphase != _GCoff and this G is visible to the garbage
+       // collector, writes to this are protected by work.rescan.lock.
+       gcRescan int32
+
+       // gcAssistBytes is this G's GC assist credit in terms of
+       // bytes allocated. If this is positive, then the G has credit
+       // to allocate gcAssistBytes bytes without assisting. If this
+       // is negative, then the G must correct this by performing
+       // scan work. We track this in bytes to make it fast to update
+       // and check for debt in the malloc hot path. The assist ratio
+       // determines how this corresponds to scan work debt.
+       gcAssistBytes int64
+
+       // Remaining fields are specific to gccgo.
+
+       exception unsafe.Pointer // current exception being thrown
+       isforeign bool           // whether current exception is not from Go
+
+       // Fields that hold stack and context information if status is Gsyscall
+       gcstack       unsafe.Pointer
+       gcstacksize   uintptr
+       gcnextsegment unsafe.Pointer
+       gcnextsp      unsafe.Pointer
+       gcinitialsp   unsafe.Pointer
+       gcregs        _ucontext_t
+
+       entry    unsafe.Pointer // goroutine entry point
+       fromgogo bool           // whether entered from gogo function
+
+       issystem     bool // do not output in stack dump
+       isbackground bool // ignore in deadlock detector
+
+       traceback *traceback // stack traceback buffer
+
+       context      _ucontext_t        // saved context for setcontext
+       stackcontext [10]unsafe.Pointer // split-stack context
+}
+
+type m struct {
+       g0 *g // goroutine with scheduling stack
+       // Not for gccgo: morebuf gobuf  // gobuf arg to morestack
+       // Not for gccgo: divmod  uint32 // div/mod denominator for arm - known to liblink
+
+       // Fields not known to debuggers.
+       procid  uint64 // for debuggers, but offset not hard-coded
+       gsignal *g     // signal-handling g
+       sigmask sigset // storage for saved signal mask
+       // Not for gccgo: tls           [6]uintptr // thread-local storage (for x86 extern register)
+       mstartfn    uintptr
+       curg        *g       // current running goroutine
+       caughtsig   guintptr // goroutine running during fatal signal
+       p           puintptr // attached p for executing go code (nil if not executing go code)
+       nextp       puintptr
+       id          int32
+       mallocing   int32
+       throwing    int32
+       preemptoff  string // if != "", keep curg running on this m
+       locks       int32
+       softfloat   int32
+       dying       int32
+       profilehz   int32
+       helpgc      int32
+       spinning    bool // m is out of work and is actively looking for work
+       blocked     bool // m is blocked on a note
+       inwb        bool // m is executing a write barrier
+       newSigstack bool // minit on C thread called sigaltstack
+       printlock   int8
+       fastrand    uint32
+       ncgocall    uint64 // number of cgo calls in total
+       ncgo        int32  // number of cgo calls currently in progress
+       // Not for gccgo: cgoCallersUse uint32      // if non-zero, cgoCallers in use temporarily
+       // Not for gccgo: cgoCallers    *cgoCallers // cgo traceback if crashing in cgo call
+       park        note
+       alllink     *m // on allm
+       schedlink   muintptr
+       mcache      *mcache
+       lockedg     *g
+       createstack [32]location // stack that created this thread.
+       // Not for gccgo: freglo        [16]uint32  // d[i] lsb and f[i]
+       // Not for gccgo: freghi        [16]uint32  // d[i] msb and f[i+16]
+       // Not for gccgo: fflag         uint32      // floating point compare flags
+       locked        uint32  // tracking for lockosthread
+       nextwaitm     uintptr // next m waiting for lock
+       gcstats       gcstats
+       needextram    bool
+       traceback     uint8
+       waitunlockf   unsafe.Pointer // todo go func(*g, unsafe.pointer) bool
+       waitlock      unsafe.Pointer
+       waittraceev   byte
+       waittraceskip int
+       startingtrace bool
+       syscalltick   uint32
+       // Not for gccgo: thread        uintptr // thread handle
+
+       // these are here because they are too large to be on the stack
+       // of low-level NOSPLIT functions.
+       // Not for gccgo: libcall   libcall
+       // Not for gccgo: libcallpc uintptr // for cpu profiler
+       // Not for gccgo: libcallsp uintptr
+       // Not for gccgo: libcallg  guintptr
+       // Not for gccgo: syscall   libcall // stores syscall parameters on windows
+
+       // Not for gccgo: mOS
+
+       // Remaining fields are specific to gccgo.
+
+       gsignalstack     unsafe.Pointer // stack for gsignal
+       gsignalstacksize uintptr
+
+       dropextram bool // drop after call is done
+
+       gcing int32
+
+       waitsema uintptr // semaphore on systems that don't use futexes
+
+       cgomal *cgoMal // allocations via _cgo_allocate
+}
+
+type p struct {
+       lock mutex
+
+       id          int32
+       status      uint32 // one of pidle/prunning/...
+       link        puintptr
+       schedtick   uint32   // incremented on every scheduler call
+       syscalltick uint32   // incremented on every system call
+       m           muintptr // back-link to associated m (nil if idle)
+       mcache      *mcache
+       // Not for gccgo: racectx     uintptr
+
+       // Not for gccgo yet: deferpool    [5][]*_defer // pool of available defer structs of different sizes (see panic.go)
+       // Not for gccgo yet: deferpoolbuf [5][32]*_defer
+       // Temporary gccgo type for deferpool field.
+       deferpool *_defer
+
+       // Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen.
+       goidcache    uint64
+       goidcacheend uint64
+
+       // Queue of runnable goroutines. Accessed without lock.
+       runqhead uint32
+       runqtail uint32
+       runq     [256]guintptr
+       // runnext, if non-nil, is a runnable G that was ready'd by
+       // the current G and should be run next instead of what's in
+       // runq if there's time remaining in the running G's time
+       // slice. It will inherit the time left in the current time
+       // slice. If a set of goroutines is locked in a
+       // communicate-and-wait pattern, this schedules that set as a
+       // unit and eliminates the (potentially large) scheduling
+       // latency that otherwise arises from adding the ready'd
+       // goroutines to the end of the run queue.
+       runnext guintptr
+
+       // Available G's (status == Gdead)
+       gfree    *g
+       gfreecnt int32
+
+       // Not for gccgo for now: sudogcache []*sudog
+       // Not for gccgo for now: sudogbuf   [128]*sudog
+
+       // Not for gccgo for now: tracebuf traceBufPtr
+
+       // Not for gccgo for now: palloc persistentAlloc // per-P to avoid mutex
+
+       // Per-P GC state
+       // Not for gccgo for now: gcAssistTime     int64 // Nanoseconds in assistAlloc
+       // Not for gccgo for now: gcBgMarkWorker   guintptr
+       // Not for gccgo for now: gcMarkWorkerMode gcMarkWorkerMode
+
+       // gcw is this P's GC work buffer cache. The work buffer is
+       // filled by write barriers, drained by mutator assists, and
+       // disposed on certain GC state transitions.
+       // Not for gccgo for now: gcw gcWork
+
+       runSafePointFn uint32 // if 1, run sched.safePointFn at next safe point
+
+       pad [64]byte
+}
+
+const (
+       // The max value of GOMAXPROCS.
+       // There are no fundamental restrictions on the value.
+       _MaxGomaxprocs = 1 << 8
+)
+
+/*
+Commented out for gccgo for now.
+
+type schedt struct {
+       // accessed atomically. keep at top to ensure alignment on 32-bit systems.
+       goidgen  uint64
+       lastpoll uint64
+
+       lock mutex
+
+       midle        muintptr // idle m's waiting for work
+       nmidle       int32    // number of idle m's waiting for work
+       nmidlelocked int32    // number of locked 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.
+
+       // Global runnable queue.
+       runqhead guintptr
+       runqtail guintptr
+       runqsize int32
+
+       // Global cache of dead G's.
+       gflock       mutex
+       gfreeStack   *g
+       gfreeNoStack *g
+       ngfree       int32
+
+       // Central cache of sudog structs.
+       sudoglock  mutex
+       sudogcache *sudog
+
+       // Central pool of available defer structs of different sizes.
+       deferlock mutex
+       deferpool [5]*_defer
+
+       gcwaiting  uint32 // gc is waiting to run
+       stopwait   int32
+       stopnote   note
+       sysmonwait uint32
+       sysmonnote note
+
+       // safepointFn should be called on each P at the next GC
+       // safepoint if p.runSafePointFn is set.
+       safePointFn   func(*p)
+       safePointWait int32
+       safePointNote note
+
+       profilehz int32 // cpu profiling rate
+
+       procresizetime int64 // nanotime() of last change to gomaxprocs
+       totaltime      int64 // âˆ«gomaxprocs dt up to procresizetime
+}
+*/
+
+// The m.locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
+// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
+// External locks are not recursive; a second lock is silently ignored.
+// The upper bits of m.locked record the nesting depth of calls to lockOSThread
+// (counting up by LockInternal), popped by unlockOSThread (counting down by LockInternal).
+// Internal locks can be recursive. For instance, a lock for cgo can occur while the main
+// goroutine is holding the lock during the initialization phase.
+const (
+       _LockExternal = 1
+       _LockInternal = 2
+)
+
+const (
+       _SigNotify   = 1 << iota // let signal.Notify have signal, even if from kernel
+       _SigKill                 // if signal.Notify doesn't take it, exit quietly
+       _SigThrow                // if signal.Notify doesn't take it, exit loudly
+       _SigPanic                // if the signal is from the kernel, panic
+       _SigDefault              // if the signal isn't explicitly requested, don't monitor it
+       _SigHandling             // our signal handler is registered
+       _SigGoExit               // cause all runtime procs to exit (only used on Plan 9).
+       _SigSetStack             // add SA_ONSTACK to libc handler
+       _SigUnblock              // unblocked in minit
+)
+
+/*
+gccgo does not use this.
+
+// Layout of in-memory per-function information prepared by linker
+// See https://golang.org/s/go12symtab.
+// Keep in sync with linker
+// and with package debug/gosym and with symtab.go in package runtime.
+type _func struct {
+       entry   uintptr // start pc
+       nameoff int32   // function name
+
+       args int32 // in/out args size
+       _    int32 // previously legacy frame size; kept for layout compatibility
+
+       pcsp      int32
+       pcfile    int32
+       pcln      int32
+       npcdata   int32
+       nfuncdata int32
+}
+
+*/
+
+// Lock-free stack node.
+// // Also known to export_test.go.
+type lfnode struct {
+       next    uint64
+       pushcnt uintptr
+}
+
+type forcegcstate struct {
+       lock mutex
+       g    *g
+       idle uint32
+}
+
+/*
+// startup_random_data holds random bytes initialized at startup. These come from
+// the ELF AT_RANDOM auxiliary vector (vdso_linux_amd64.go or os_linux_386.go).
+var startupRandomData []byte
+
+// extendRandom extends the random numbers in r[:n] to the whole slice r.
+// Treats n<0 as n==0.
+func extendRandom(r []byte, n int) {
+       if n < 0 {
+               n = 0
+       }
+       for n < len(r) {
+               // Extend random bits using hash function & time seed
+               w := n
+               if w > 16 {
+                       w = 16
+               }
+               h := memhash(unsafe.Pointer(&r[n-w]), uintptr(nanotime()), uintptr(w))
+               for i := 0; i < sys.PtrSize && n < len(r); i++ {
+                       r[n] = byte(h)
+                       n++
+                       h >>= 8
+               }
+       }
+}
+*/
+
+// deferred subroutine calls
+// This is the gccgo version.
+type _defer struct {
+       // The next entry in the stack.
+       next *_defer
+
+       // The stack variable for the function which called this defer
+       // statement.  This is set to true if we are returning from
+       // that function, false if we are panicing through it.
+       frame *bool
+
+       // The value of the panic stack when this function is
+       // deferred.  This function can not recover this value from
+       // the panic stack.  This can happen if a deferred function
+       // has a defer statement itself.
+       _panic *_panic
+
+       // The function to call.
+       pfn uintptr
+
+       // The argument to pass to the function.
+       arg unsafe.Pointer
+
+       // The return address that a recover thunk matches against.
+       // This is set by __go_set_defer_retaddr which is called by
+       // the thunks created by defer statements.
+       retaddr uintptr
+
+       // Set to true if a function created by reflect.MakeFunc is
+       // permitted to recover.  The return address of such a
+       // function function will be somewhere in libffi, so __retaddr
+       // is not useful.
+       makefunccanrecover bool
+
+       // Set to true if this defer stack entry is not part of the
+       // defer pool.
+       special bool
+}
+
+// panics
+// This is the gccgo version.
+type _panic struct {
+       // The next entry in the stack.
+       next *_panic
+
+       // The value associated with this panic.
+       arg interface{}
+
+       // Whether this panic has been recovered.
+       recovered bool
+
+       // Whether this panic was pushed on the stack because of an
+       // exception thrown in some other language.
+       isforeign bool
+}
+
+const (
+       _TraceRuntimeFrames = 1 << iota // include frames for internal runtime functions.
+       _TraceTrap                      // the initial PC, SP are from a trap, not a return PC from a call
+       _TraceJumpStack                 // if traceback is on a systemstack, resume trace at g that called into it
+)
+
+// The maximum number of frames we print for a traceback
+const _TracebackMaxFrames = 100
+
+var (
+//     emptystring string
+//     allglen     uintptr
+//     allm        *m
+//     allp        [_MaxGomaxprocs + 1]*p
+//     gomaxprocs  int32
+//     panicking   uint32
+//     ncpu        int32
+//     forcegc     forcegcstate
+//     sched       schedt
+//     newprocs    int32
+
+// Information about what cpu features are available.
+// Set on startup in asm_{x86,amd64}.s.
+//     cpuid_ecx         uint32
+//     cpuid_edx         uint32
+//     cpuid_ebx7        uint32
+//     lfenceBeforeRdtsc bool
+//     support_avx       bool
+//     support_avx2      bool
+
+//     goarm                uint8 // set by cmd/link on arm systems
+//     framepointer_enabled bool  // set by cmd/link
+)
+
+// Set by the linker so the runtime can determine the buildmode.
+var (
+//     islibrary bool // -buildmode=c-shared
+//     isarchive bool // -buildmode=c-archive
+)
+
+// Types that are only used by gccgo.
+
+// _ucontext_t is a Go version of the C ucontext_t type, used by getcontext.
+// _sizeof_ucontext_t is defined by the Makefile from <ucontext.h>.
+type _ucontext_t [_sizeof_ucontext_t / unsafe.Sizeof(uintptr(0))]unsafe.Pointer
+
+// traceback is used to collect stack traces from other goroutines.
+type traceback struct {
+       gp     *g
+       locbuf [_TracebackMaxFrames]location
+       c      int
+}
+
+// location is a location in the program, used for backtraces.
+type location struct {
+       pc       uintptr
+       filename string
+       function string
+       lineno   int
+}
+
+// cgoMal tracks allocations made by _cgo_allocate
+// FIXME: _cgo_allocate has been removed from gc and can probably be
+// removed from gccgo too.
+type cgoMal struct {
+       next  *cgoMal
+       alloc unsafe.Pointer
+}
+
+// sigset is the Go version of the C type sigset_t.
+// _sigset_t is defined by the Makefile from <signal.h>.
+type sigset _sigset_t
diff --git a/libgo/go/runtime/type.go b/libgo/go/runtime/type.go
new file mode 100644 (file)
index 0000000..fb5f034
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2009 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.
+
+// Runtime type representation.
+
+package runtime
+
+import "unsafe"
+
+type _type struct {
+       kind       uint8
+       align      int8
+       fieldAlign uint8
+       _          uint8
+       size       uintptr
+       hash       uint32
+
+       hashfn  func(unsafe.Pointer, uintptr) uintptr
+       equalfn func(unsafe.Pointer, unsafe.Pointer, uintptr) bool
+
+       gc     unsafe.Pointer
+       string *string
+       *uncommonType
+       ptrToThis *_type
+}
+
+type method struct {
+       name    *string
+       pkgPath *string
+       mtyp    *_type
+       typ     *_type
+       tfn     unsafe.Pointer
+}
+
+type uncommonType struct {
+       name    *string
+       pkgPath *string
+       methods []method
+}
+
+type imethod struct {
+       name    *string
+       pkgPath *string
+       typ     *_type
+}
+
+type interfaceType struct {
+       typ     _type
+       methods []imethod
+}
+
+type mapType struct {
+       typ  _type
+       key  *_type
+       elem *_type
+}
+
+type arrayType struct {
+       typ   _type
+       elem  *_type
+       slice *_type
+       len   uintptr
+}
+
+type chanType struct {
+       typ  _type
+       elem *_type
+       dir  uintptr
+}
+
+type slicetype struct {
+       typ  _type
+       elem *_type
+}
+
+type functype struct {
+       typ       _type
+       dotdotdot bool
+       in        []*_type
+       out       []*_type
+}
+
+type ptrtype struct {
+       typ  _type
+       elem *_type
+}
+
+type structfield struct {
+       name    *string // nil for embedded fields
+       pkgPath *string // nil for exported Names; otherwise import path
+       typ     *_type  // type of field
+       tag     *string // nil if no tag
+       offset  uintptr // byte offset of field within struct
+}
+
+type structtype struct {
+       typ    _type
+       fields []structfield
+}
index ac5f08631995d34ae3e09dafc4665cf413c726a4..10e38036c60ba1030e8cd62749e60f299c33106f 100755 (executable)
@@ -29,6 +29,7 @@ cat > sysinfo.c <<EOF
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <ucontext.h>
 #include <netinet/in.h>
 /* <netinet/tcp.h> needs u_char/u_short, but <sys/bsd_types> is only
    included by <netinet/in.h> if _SGIAPI (i.e. _SGI_SOURCE
index 610bcf5ec4e8d246f34fb3162a6dc5ae26df9cf4..598c2617840f33c231dcb50d68cb728b77c1d6ca 100644 (file)
@@ -36,7 +36,6 @@ void
 syscall_cgocall ()
 {
   M* m;
-  G* g;
 
   if (runtime_needextram && runtime_cas (&runtime_needextram, 1, 0))
     runtime_newextram ();
@@ -45,8 +44,7 @@ syscall_cgocall ()
 
   m = runtime_m ();
   ++m->ncgocall;
-  g = runtime_g ();
-  ++g->ncgo;
+  ++m->ncgo;
   runtime_entersyscall ();
 }
 
@@ -59,18 +57,18 @@ syscall_cgocalldone ()
 
   g = runtime_g ();
   __go_assert (g != NULL);
-  --g->ncgo;
-  if (g->ncgo == 0)
+  --g->m->ncgo;
+  if (g->m->ncgo == 0)
     {
       /* We are going back to Go, and we are not in a recursive call.
         Let the garbage collector clean up any unreferenced
         memory.  */
-      g->cgomal = NULL;
+      g->m->cgomal = NULL;
     }
 
   /* If we are invoked because the C function called _cgo_panic, then
      _cgo_panic will already have exited syscall mode.  */
-  if (g->status == Gsyscall)
+  if (g->atomicstatus == _Gsyscall)
     runtime_exitsyscall ();
 
   runtime_unlockOSThread();
@@ -93,7 +91,7 @@ syscall_cgocallback ()
 
   runtime_exitsyscall ();
 
-  if (runtime_g ()->ncgo == 0)
+  if (runtime_m ()->ncgo == 0)
     {
       /* The C call to Go came from a thread not currently running any
         Go.  In the case of -buildmode=c-archive or c-shared, this
@@ -119,7 +117,7 @@ syscall_cgocallbackdone ()
 
   runtime_entersyscall ();
   mp = runtime_m ();
-  if (mp->dropextram && runtime_g ()->ncgo == 0)
+  if (mp->dropextram && mp->ncgo == 0)
     {
       mp->dropextram = false;
       runtime_dropm ();
@@ -133,16 +131,16 @@ void *
 alloc_saved (size_t n)
 {
   void *ret;
-  G *g;
+  M *m;
   CgoMal *c;
 
   ret = __go_alloc (n);
 
-  g = runtime_g ();
+  m = runtime_m ();
   c = (CgoMal *) __go_alloc (sizeof (CgoMal));
-  c->next = g->cgomal;
+  c->next = m->cgomal;
   c->alloc = ret;
-  g->cgomal = c;
+  m->cgomal = c;
 
   return ret;
 }
index 3a48fe1130e265c7080a7a6c6ea702fbe189acf0..f3e14bd0b966e4695ee77b4aa9fab2e85dc615ef 100644 (file)
@@ -9,7 +9,6 @@
 #include "runtime.h"
 #include "go-alloc.h"
 #include "go-panic.h"
-#include "go-defer.h"
 
 /* This function is called each time we need to defer a call.  */
 
@@ -17,19 +16,19 @@ void
 __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
 {
   G *g;
-  struct __go_defer_stack *n;
+  Defer *n;
 
   g = runtime_g ();
   n = runtime_newdefer ();
-  n->__next = g->defer;
-  n->__frame = frame;
-  n->__panic = g->panic;
-  n->__pfn = pfn;
-  n->__arg = arg;
-  n->__retaddr = NULL;
-  n->__makefunc_can_recover = 0;
-  n->__special = 0;
-  g->defer = n;
+  n->next = g->_defer;
+  n->frame = frame;
+  n->_panic = g->_panic;
+  n->pfn = (uintptr) pfn;
+  n->arg = arg;
+  n->retaddr = 0;
+  n->makefunccanrecover = 0;
+  n->special = 0;
+  g->_defer = n;
 }
 
 /* This function is called when we want to undefer the stack.  */
@@ -40,19 +39,19 @@ __go_undefer (_Bool *frame)
   G *g;
 
   g = runtime_g ();
-  while (g->defer != NULL && g->defer->__frame == frame)
+  while (g->_defer != NULL && g->_defer->frame == frame)
     {
-      struct __go_defer_stack *d;
+      Defer *d;
       void (*pfn) (void *);
 
-      d = g->defer;
-      pfn = d->__pfn;
-      d->__pfn = NULL;
+      d = g->_defer;
+      pfn = (void (*) (void *)) d->pfn;
+      d->pfn = 0;
 
       if (pfn != NULL)
-       (*pfn) (d->__arg);
+       (*pfn) (d->arg);
 
-      g->defer = d->__next;
+      g->_defer = d->next;
 
       /* This may be called by a cgo callback routine to defer the
         call to syscall.CgocallBackDone, in which case we will not
@@ -79,7 +78,7 @@ __go_set_defer_retaddr (void *retaddr)
   G *g;
 
   g = runtime_g ();
-  if (g->defer != NULL)
-    g->defer->__retaddr = __builtin_extract_return_addr (retaddr);
+  if (g->_defer != NULL)
+    g->_defer->retaddr = (uintptr) __builtin_extract_return_addr (retaddr);
   return 0;
 }
diff --git a/libgo/runtime/go-defer.h b/libgo/runtime/go-defer.h
deleted file mode 100644 (file)
index acf2d40..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* go-defer.h -- the defer stack.
-
-   Copyright 2010 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.  */
-
-struct __go_panic_stack;
-
-/* The defer stack is a list of these structures.  */
-
-struct __go_defer_stack
-{
-  /* The next entry in the stack.  */
-  struct __go_defer_stack *__next;
-
-  /* The stack variable for the function which called this defer
-     statement.  This is set to 1 if we are returning from that
-     function, 0 if we are panicing through it.  */
-  _Bool *__frame;
-
-  /* The value of the panic stack when this function is deferred.
-     This function can not recover this value from the panic stack.
-     This can happen if a deferred function has a defer statement
-     itself.  */
-  struct __go_panic_stack *__panic;
-
-  /* The function to call.  */
-  void (*__pfn) (void *);
-
-  /* The argument to pass to the function.  */
-  void *__arg;
-
-  /* The return address that a recover thunk matches against.  This is
-     set by __go_set_defer_retaddr which is called by the thunks
-     created by defer statements.  */
-  const void *__retaddr;
-
-  /* Set to true if a function created by reflect.MakeFunc is
-     permitted to recover.  The return address of such a function
-     function will be somewhere in libffi, so __retaddr is not
-     useful.  */
-  _Bool __makefunc_can_recover;
-
-  /* Set to true if this defer stack entry is not part of the defer
-     pool.  */
-  _Bool __special;
-};
index 78ef287cf00a05342ec65ac83b4f1ba19fe92971..408ef2a75f5d8bd386aa37a7d7df8eeb4e4891bb 100644 (file)
@@ -8,7 +8,6 @@
 
 #include "runtime.h"
 #include "go-panic.h"
-#include "go-defer.h"
 
 /* This is called when a call to recover is deferred.  That is,
    something like
@@ -82,7 +81,7 @@ __go_deferred_recover ()
   G *g;
 
   g = runtime_g ();
-  if (g->defer == NULL || g->defer->__panic != g->panic)
+  if (g->_defer == NULL || g->_defer->_panic != g->_panic)
     {
       struct __go_empty_interface ret;
 
index 77975c6e083a29fa01a890e94bcf591a87940d14..436a96626b8900b0afa6ff78d68bcd73eb87e273 100644 (file)
 #include "arch.h"
 #include "malloc.h"
 #include "go-alloc.h"
-#include "go-defer.h"
 #include "go-panic.h"
 #include "interface.h"
 
 /* Print the panic stack.  This is used when there is no recover.  */
 
 static void
-__printpanics (struct __go_panic_stack *p)
+__printpanics (Panic *p)
 {
-  if (p->__next != NULL)
+  if (p->next != NULL)
     {
-      __printpanics (p->__next);
+      __printpanics (p->next);
       runtime_printf ("\t");
     }
   runtime_printf ("panic: ");
-  runtime_printany (p->__arg);
-  if (p->__was_recovered)
+  runtime_printany (p->arg);
+  if (p->recovered)
     runtime_printf (" [recovered]");
   runtime_printf ("\n");
 }
@@ -39,39 +38,39 @@ void
 __go_panic (struct __go_empty_interface arg)
 {
   G *g;
-  struct __go_panic_stack *n;
+  Panic *n;
 
   g = runtime_g ();
 
-  n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack));
-  n->__arg = arg;
-  n->__next = g->panic;
-  g->panic = n;
+  n = (Panic *) __go_alloc (sizeof (Panic));
+  n->arg = arg;
+  n->next = g->_panic;
+  g->_panic = n;
 
   /* Run all the defer functions.  */
 
   while (1)
     {
-      struct __go_defer_stack *d;
+      Defer *d;
       void (*pfn) (void *);
 
-      d = g->defer;
+      d = g->_defer;
       if (d == NULL)
        break;
 
-      pfn = d->__pfn;
-      d->__pfn = NULL;
+      pfn = (void (*) (void *)) d->pfn;
+      d->pfn = 0;
 
       if (pfn != NULL)
        {
-         (*pfn) (d->__arg);
+         (*pfn) (d->arg);
 
-         if (n->__was_recovered)
+         if (n->recovered)
            {
              /* Some defer function called recover.  That means that
                 we should stop running this panic.  */
 
-             g->panic = n->__next;
+             g->_panic = n->next;
              __go_free (n);
 
              /* Now unwind the stack by throwing an exception.  The
@@ -91,10 +90,10 @@ __go_panic (struct __go_empty_interface arg)
             it did not call recover, we know that we are not
             returning from the calling function--we are panicing
             through it.  */
-         *d->__frame = 0;
+         *d->frame = 0;
        }
 
-      g->defer = d->__next;
+      g->_defer = d->next;
 
       /* This may be called by a cgo callback routine to defer the
         call to syscall.CgocallBackDone, in which case we will not
@@ -107,6 +106,6 @@ __go_panic (struct __go_empty_interface arg)
   /* The panic was not recovered.  */
 
   runtime_startpanic ();
-  __printpanics (g->panic);
+  __printpanics (g->_panic);
   runtime_dopanic (0);
 }
index d29fe88b57a4396a86ead6513a453c88d26bbe30..1b172d92db9cf2910d2c1cf0cf68f8b1ca86e113 100644 (file)
 
 struct String;
 struct __go_type_descriptor;
-struct __go_defer_stack;
-
-/* The stack of panic calls.  */
-
-struct __go_panic_stack
-{
-  /* The next entry in the stack.  */
-  struct __go_panic_stack *__next;
-
-  /* The value associated with this panic.  */
-  struct __go_empty_interface __arg;
-
-  /* Whether this panic has been recovered.  */
-  _Bool __was_recovered;
-
-  /* Whether this panic was pushed on the stack because of an
-     exception thrown in some other language.  */
-  _Bool __is_foreign;
-};
 
 extern void __go_panic (struct __go_empty_interface)
   __attribute__ ((noreturn));
@@ -42,8 +23,8 @@ extern _Bool __go_can_recover (void *);
 
 extern void __go_makefunc_can_recover (void *retaddr);
 
-struct Location;
-extern void __go_makefunc_ffi_can_recover (struct Location *, int);
+struct location;
+extern void __go_makefunc_ffi_can_recover (struct location *, int);
 
 extern void __go_makefunc_returning (void);
 
index fc66f61cab325c3dabba03bdfc266d5a15909d8f..4d2f0f9fc39b084bb9b9deba55656fe7c3706eb0 100644 (file)
@@ -7,33 +7,32 @@
 #include "runtime.h"
 #include "interface.h"
 #include "go-panic.h"
-#include "go-defer.h"
 
 /* If the top of the defer stack can be recovered, then return it.
    Otherwise return NULL.  */
 
-static struct __go_defer_stack *
+static Defer *
 current_defer ()
 {
   G *g;
-  struct __go_defer_stack *d;
+  Defer *d;
 
   g = runtime_g ();
 
-  d = g->defer;
+  d = g->_defer;
   if (d == NULL)
     return NULL;
 
   /* The panic which would be recovered is the one on the top of the
      panic stack.  We do not want to recover it if that panic was on
      the top of the panic stack when this function was deferred.  */
-  if (d->__panic == g->panic)
+  if (d->_panic == g->_panic)
     return NULL;
 
   /* The deferred thunk will call _go_set_defer_retaddr.  If this has
      not happened, then we have not been called via defer, and we can
      not recover.  */
-  if (d->__retaddr == NULL)
+  if (d->retaddr == 0)
     return NULL;
 
   return d;
@@ -48,7 +47,7 @@ current_defer ()
 _Bool
 __go_can_recover (void *retaddr)
 {
-  struct __go_defer_stack *d;
+  Defer *d;
   const char* ret;
   const char* dret;
   Location locs[16];
@@ -64,7 +63,7 @@ __go_can_recover (void *retaddr)
 
   ret = (const char *) __builtin_extract_return_addr (retaddr);
 
-  dret = (const char *) d->__retaddr;
+  dret = (const char *) (uintptr) d->retaddr;
   if (ret <= dret && ret + 16 >= dret)
     return 1;
 
@@ -111,7 +110,7 @@ __go_can_recover (void *retaddr)
   /* If the function calling recover was created by reflect.MakeFunc,
      then __go_makefunc_can_recover or __go_makefunc_ffi_can_recover
      will have set the __makefunc_can_recover field.  */
-  if (!d->__makefunc_can_recover)
+  if (!d->makefunccanrecover)
     return 0;
 
   /* We look up the stack, ignoring libffi functions and functions in
@@ -178,7 +177,7 @@ __go_can_recover (void *retaddr)
 void
 __go_makefunc_can_recover (void *retaddr)
 {
-  struct __go_defer_stack *d;
+  Defer *d;
 
   d = current_defer ();
   if (d == NULL)
@@ -186,24 +185,24 @@ __go_makefunc_can_recover (void *retaddr)
 
   /* If we are already in a call stack of MakeFunc functions, there is
      nothing we can usefully check here.  */
-  if (d->__makefunc_can_recover)
+  if (d->makefunccanrecover)
     return;
 
   if (__go_can_recover (retaddr))
-    d->__makefunc_can_recover = 1;
+    d->makefunccanrecover = 1;
 }
 
 /* This function is called when code is about to enter a function
    created by the libffi version of reflect.MakeFunc.  This function
    is passed the names of the callers of the libffi code that called
    the stub.  It uses to decide whether it is permitted to call
-   recover, and sets d->__makefunc_can_recover so that __go_recover
-   can make the same decision.  */
+   recover, and sets d->makefunccanrecover so that __go_recover can
+   make the same decision.  */
 
 void
-__go_makefunc_ffi_can_recover (struct Location *loc, int n)
+__go_makefunc_ffi_can_recover (struct location *loc, int n)
 {
-  struct __go_defer_stack *d;
+  Defer *d;
   const byte *name;
   intgo len;
 
@@ -213,7 +212,7 @@ __go_makefunc_ffi_can_recover (struct Location *loc, int n)
 
   /* If we are already in a call stack of MakeFunc functions, there is
      nothing we can usefully check here.  */
-  if (d->__makefunc_can_recover)
+  if (d->makefunccanrecover)
     return;
 
   /* LOC points to the caller of our caller.  That will be a thunk.
@@ -228,26 +227,26 @@ __go_makefunc_ffi_can_recover (struct Location *loc, int n)
   if (len > 4
       && __builtin_strchr ((const char *) name, '.') == NULL
       && __builtin_strncmp ((const char *) name, "__go_", 4) == 0)
-    d->__makefunc_can_recover = 1;
+    d->makefunccanrecover = 1;
 }
 
 /* This function is called when code is about to exit a function
    created by reflect.MakeFunc.  It is called by the function stub
-   used by MakeFunc.  It clears the __makefunc_can_recover field.
-   It's OK to always clear this field, because __go_can_recover will
-   only be called by a stub created for a function that calls recover.
-   That stub will not call a function created by reflect.MakeFunc, so
-   by the time we get here any caller higher up on the call stack no
+   used by MakeFunc.  It clears the makefunccanrecover field.  It's OK
+   to always clear this field, because __go_can_recover will only be
+   called by a stub created for a function that calls recover.  That
+   stub will not call a function created by reflect.MakeFunc, so by
+   the time we get here any caller higher up on the call stack no
    longer needs the information.  */
 
 void
 __go_makefunc_returning (void)
 {
-  struct __go_defer_stack *d;
+  Defer *d;
 
-  d = runtime_g ()->defer;
+  d = runtime_g ()->_defer;
   if (d != NULL)
-    d->__makefunc_can_recover = 0;
+    d->makefunccanrecover = 0;
 }
 
 /* This is only called when it is valid for the caller to recover the
@@ -257,11 +256,11 @@ struct __go_empty_interface
 __go_recover ()
 {
   G *g;
-  struct __go_panic_stack *p;
+  Panic *p;
 
   g = runtime_g ();
 
-  if (g->panic == NULL || g->panic->__was_recovered)
+  if (g->_panic == NULL || g->_panic->recovered)
     {
       struct __go_empty_interface ret;
 
@@ -269,7 +268,7 @@ __go_recover ()
       ret.__object = NULL;
       return ret;
     }
-  p = g->panic;
-  p->__was_recovered = 1;
-  return p->__arg;
+  p = g->_panic;
+  p->recovered = 1;
+  return p->arg;
 }
index a948c31cca096ae7c1c2a497a2b37f813742c444..0aef2fc9b08782f8d46744981cc6a191f2aeb78a 100644 (file)
@@ -26,11 +26,11 @@ extern void __splitstack_setcontext(void *context[10]);
 
 #endif
 
-#define N SigNotify
-#define K SigKill
-#define T SigThrow
-#define P SigPanic
-#define D SigDefault
+#define N _SigNotify
+#define K _SigKill
+#define T _SigThrow
+#define P _SigPanic
+#define D _SigDefault
 
 /* Signal actions.  This collects the sigtab tables for several
    different targets from the master library.  SIGKILL and SIGSTOP are
@@ -182,14 +182,14 @@ runtime_sighandler (int sig, Siginfo *info,
 #ifdef SA_SIGINFO
       notify = info != NULL && info->si_code == SI_USER;
 #endif
-      if (notify || (t->flags & SigNotify) != 0)
+      if (notify || (t->flags & _SigNotify) != 0)
        {
          if (__go_sigsend (sig))
            return;
        }
-      if ((t->flags & SigKill) != 0)
+      if ((t->flags & _SigKill) != 0)
        runtime_exit (2);
-      if ((t->flags & SigThrow) == 0)
+      if ((t->flags & _SigThrow) == 0)
        return;
 
       runtime_startpanic ();
@@ -320,7 +320,7 @@ sig_panic_info_handler (int sig, Siginfo *info, void *context)
 #endif
     }
 
-  /* All signals with SigPanic should be in cases above, and this
+  /* All signals with _SigPanic should be in cases above, and this
      handler should only be invoked for those signals.  */
   __builtin_unreachable ();
 }
@@ -365,7 +365,7 @@ sig_panic_handler (int sig)
 #endif
     }
 
-  /* All signals with SigPanic should be in cases above, and this
+  /* All signals with _SigPanic should be in cases above, and this
      handler should only be invoked for those signals.  */
   __builtin_unreachable ();
 }
@@ -406,7 +406,7 @@ sig_tramp_info (int sig, Siginfo *info, void *context)
       /* We are running on the signal stack.  Set the split stack
         context so that the stack guards are checked correctly.  */
 #ifdef USING_SPLIT_STACK
-      __splitstack_setcontext (&mp->gsignal->stack_context[0]);
+      __splitstack_setcontext (&mp->gsignal->stackcontext[0]);
 #endif
     }
 
@@ -451,7 +451,7 @@ runtime_setsig (int32 i, GoSighandler *fn, bool restart)
 
   t = &runtime_sigtab[i];
 
-  if ((t->flags & SigPanic) == 0)
+  if ((t->flags & _SigPanic) == 0)
     {
 #ifdef SA_SIGINFO
       sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
index 87d9eb3ef4e96ea13bf69c1dd13b3b733a815ff3..ea11e4e3b1d937a556076cffc42073ba480bfd47 100644 (file)
@@ -15,7 +15,6 @@
 
 #include "runtime.h"
 #include "go-alloc.h"
-#include "go-defer.h"
 #include "go-panic.h"
 
 /* The code for a Go exception.  */
@@ -57,43 +56,42 @@ __go_check_defer (_Bool *frame)
       /* Some other language has thrown an exception.  We know there
         are no defer handlers, so there is nothing to do.  */
     }
-  else if (g->is_foreign)
+  else if (g->isforeign)
     {
-      struct __go_panic_stack *n;
-      _Bool was_recovered;
+      Panic *n;
+      _Bool recovered;
 
       /* Some other language has thrown an exception.  We need to run
         the local defer handlers.  If they call recover, we stop
         unwinding the stack here.  */
 
-      n = ((struct __go_panic_stack *)
-          __go_alloc (sizeof (struct __go_panic_stack)));
+      n = (Panic *) __go_alloc (sizeof (Panic));
 
-      n->__arg.__type_descriptor = NULL;
-      n->__arg.__object = NULL;
-      n->__was_recovered = 0;
-      n->__is_foreign = 1;
-      n->__next = g->panic;
-      g->panic = n;
+      n->arg.__type_descriptor = NULL;
+      n->arg.__object = NULL;
+      n->recovered = 0;
+      n->isforeign = 1;
+      n->next = g->_panic;
+      g->_panic = n;
 
       while (1)
        {
-         struct __go_defer_stack *d;
+         Defer *d;
          void (*pfn) (void *);
 
-         d = g->defer;
-         if (d == NULL || d->__frame != frame || d->__pfn == NULL)
+         d = g->_defer;
+         if (d == NULL || d->frame != frame || d->pfn == 0)
            break;
 
-         pfn = d->__pfn;
-         g->defer = d->__next;
+         pfn = (void (*) (void *)) d->pfn;
+         g->_defer = d->next;
 
-         (*pfn) (d->__arg);
+         (*pfn) (d->arg);
 
          if (runtime_m () != NULL)
            runtime_freedefer (d);
 
-         if (n->__was_recovered)
+         if (n->recovered)
            {
              /* The recover function caught the panic thrown by some
                 other language.  */
@@ -101,11 +99,11 @@ __go_check_defer (_Bool *frame)
            }
        }
 
-      was_recovered = n->__was_recovered;
-      g->panic = n->__next;
+      recovered = n->recovered;
+      g->_panic = n->next;
       __go_free (n);
 
-      if (was_recovered)
+      if (recovered)
        {
          /* Just return and continue executing Go code.  */
          *frame = 1;
@@ -115,17 +113,17 @@ __go_check_defer (_Bool *frame)
       /* We are panicing through this function.  */
       *frame = 0;
     }
-  else if (g->defer != NULL
-          && g->defer->__pfn == NULL
-          && g->defer->__frame == frame)
+  else if (g->_defer != NULL
+          && g->_defer->pfn == 0
+          && g->_defer->frame == frame)
     {
-      struct __go_defer_stack *d;
+      Defer *d;
 
       /* This is the defer function which called recover.  Simply
         return to stop the stack unwind, and let the Go code continue
         to execute.  */
-      d = g->defer;
-      g->defer = d->__next;
+      d = g->_defer;
+      g->_defer = d->next;
 
       if (runtime_m () != NULL)
        runtime_freedefer (d);
@@ -432,7 +430,7 @@ PERSONALITY_FUNCTION (int version,
   else
     {
       g->exception = ue_header;
-      g->is_foreign = is_foreign;
+      g->isforeign = is_foreign;
     }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
index 52a91e87da76d6394608a40a3b55388bec50a839..18fe913c4eb1b3759fe43f552e0a99842b1ebca9 100644 (file)
@@ -14,7 +14,6 @@
 #include "malloc.h"
 #include "mgc0.h"
 #include "go-type.h"
-#include "go-defer.h"
 #include "go-panic.h"
 
 #define hash __hash
@@ -265,15 +264,15 @@ dumpgoroutine(G *gp)
        dumpint((uintptr)0);
        dumpint(gp->goid);
        dumpint(gp->gopc);
-       dumpint(gp->status);
+       dumpint(gp->atomicstatus);
        dumpbool(gp->issystem);
        dumpbool(gp->isbackground);
        dumpint(gp->waitsince);
-       dumpcstr((const int8 *)gp->waitreason);
+       dumpstr(gp->waitreason);
        dumpint((uintptr)0);
        dumpint((uintptr)gp->m);
-       dumpint((uintptr)gp->defer);
-       dumpint((uintptr)gp->panic);
+       dumpint((uintptr)gp->_defer);
+       dumpint((uintptr)gp->_panic);
 
        // dump stack
        // child.args.n = -1;
@@ -285,24 +284,24 @@ dumpgoroutine(G *gp)
        // runtime_gentraceback(pc, sp, lr, gp, 0, nil, 0x7fffffff, dumpframe, &child, false);
 
        // dump defer & panic records
-       for(d = gp->defer; d != nil; d = d->__next) {
+       for(d = gp->_defer; d != nil; d = d->next) {
                dumpint(TagDefer);
                dumpint((uintptr)d);
                dumpint((uintptr)gp);
-               dumpint((uintptr)d->__arg);
-               dumpint((uintptr)d->__frame);
-               dumpint((uintptr)d->__pfn);
+               dumpint((uintptr)d->arg);
+               dumpint((uintptr)d->frame);
+               dumpint((uintptr)d->pfn);
                dumpint((uintptr)0);
-               dumpint((uintptr)d->__next);
+               dumpint((uintptr)d->next);
        }
-       for (p = gp->panic; p != nil; p = p->__next) {
+       for (p = gp->_panic; p != nil; p = p->next) {
                dumpint(TagPanic);
                dumpint((uintptr)p);
                dumpint((uintptr)gp);
-               dumpint((uintptr)p->__arg.__type_descriptor);
-               dumpint((uintptr)p->__arg.__object);
+               dumpint((uintptr)p->arg.__type_descriptor);
+               dumpint((uintptr)p->arg.__object);
                dumpint((uintptr)0);
-               dumpint((uintptr)p->__next);
+               dumpint((uintptr)p->next);
        }
 }
 
@@ -315,15 +314,15 @@ dumpgs(void)
        // goroutines & stacks
        for(i = 0; i < runtime_allglen; i++) {
                gp = runtime_allg[i];
-               switch(gp->status){
+               switch(gp->atomicstatus){
                default:
-                       runtime_printf("unexpected G.status %d\n", gp->status);
+                       runtime_printf("unexpected G.status %d\n", gp->atomicstatus);
                        runtime_throw("mark - bad status");
-               case Gdead:
+               case _Gdead:
                        break;
-               case Grunnable:
-               case Gsyscall:
-               case Gwaiting:
+               case _Grunnable:
+               case _Gsyscall:
+               case _Gwaiting:
                        dumpgoroutine(gp);
                        break;
                }
@@ -602,7 +601,7 @@ mdump(G *gp)
        flush();
 
        gp->param = nil;
-       gp->status = Grunning;
+       gp->atomicstatus = _Grunning;
        runtime_gogo(gp);
 }
 
@@ -632,8 +631,8 @@ runtime_debug_WriteHeapDump(uintptr fd)
 
        // Call dump routine on M stack.
        g = runtime_g();
-       g->status = Gwaiting;
-       g->waitreason = "dumping heap";
+       g->atomicstatus = _Gwaiting;
+       g->waitreason = runtime_gostringnocopy((const byte*)"dumping heap");
        runtime_mcall(mdump);
 
        // Reset dump file.
index ef611fb36ad5b68bea63e2ec3e49631821cc85a3..06ac6e7f90d265392093d43f89b745f41c8754c0 100644 (file)
@@ -73,7 +73,7 @@ unlocked:
                        // for this lock, chained through m->nextwaitm.
                        // Queue this M.
                        for(;;) {
-                               m->nextwaitm = (void*)(v&~LOCKED);
+                               m->nextwaitm = v&~LOCKED;
                                if(runtime_casp((void**)&l->key, (void*)v, (void*)((uintptr)m|LOCKED)))
                                        break;
                                v = (uintptr)runtime_atomicloadp((void**)&l->key);
@@ -104,7 +104,7 @@ runtime_unlock(Lock *l)
                        // Other M's are waiting for the lock.
                        // Dequeue an M.
                        mp = (void*)(v&~LOCKED);
-                       if(runtime_casp((void**)&l->key, (void*)v, mp->nextwaitm)) {
+                       if(runtime_cas(&l->key, v, mp->nextwaitm)) {
                                // Dequeued an M.  Wake it.
                                runtime_semawakeup(mp);
                                break;
index c111a0eeefd6c6a49e002f3f38e2ce01e7801bee..fbb7b744eeb18bef1e4596072f72bd60f0032dcc 100644 (file)
@@ -92,11 +92,11 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
                return &runtime_zerobase;
        }
 
-       m = runtime_m();
        g = runtime_g();
+       m = g->m;
 
        incallback = false;
-       if(m->mcache == nil && g->ncgo > 0) {
+       if(m->mcache == nil && m->ncgo > 0) {
                // For gccgo this case can occur when a cgo or SWIG function
                // has an interface return type and the function
                // returns a non-pointer, so memory allocation occurs
@@ -165,11 +165,11 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
                                        tiny = (byte*)ROUND((uintptr)tiny, 4);
                                else if((size&1) == 0)
                                        tiny = (byte*)ROUND((uintptr)tiny, 2);
-                               size1 = size + (tiny - c->tiny);
+                               size1 = size + (tiny - (byte*)c->tiny);
                                if(size1 <= tinysize) {
                                        // The object fits into existing tiny block.
                                        v = (MLink*)tiny;
-                                       c->tiny += size1;
+                                       c->tiny = (byte*)c->tiny + size1;
                                        c->tinysize -= size1;
                                        m->mallocing = 0;
                                        m->locks--;
@@ -281,7 +281,7 @@ largealloc(uint32 flag, uintptr *sizep)
        s = runtime_MHeap_Alloc(&runtime_mheap, npages, 0, 1, !(flag & FlagNoZero));
        if(s == nil)
                runtime_throw("out of memory");
-       s->limit = (byte*)(s->start<<PageShift) + size;
+       s->limit = (uintptr)((byte*)(s->start<<PageShift) + size);
        *sizep = npages<<PageShift;
        v = (void*)(s->start << PageShift);
        // setup for mark sweep
@@ -475,7 +475,7 @@ runtime_purgecachedstats(MCache *c)
 
        // Protected by either heap or GC lock.
        h = &runtime_mheap;
-       mstats.heap_alloc += c->local_cachealloc;
+       mstats.heap_alloc += (intptr)c->local_cachealloc;
        c->local_cachealloc = 0;
        mstats.nlookup += c->local_nlookup;
        c->local_nlookup = 0;
@@ -493,7 +493,7 @@ extern uintptr runtime_sizeof_C_MStats
   __asm__ (GOSYM_PREFIX "runtime.Sizeof_C_MStats");
 
 // Size of the trailing by_size array differs between Go and C,
-// NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+// _NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
 // sizeof_C_MStats is what C thinks about size of Go struct.
 
 // Initialized in mallocinit because it's defined in go/runtime/mem.go.
@@ -511,7 +511,7 @@ runtime_mallocinit(void)
        uint64 i;
        bool reserved;
 
-       runtime_sizeof_C_MStats = sizeof(MStats) - (NumSizeClasses - 61) * sizeof(mstats.by_size[0]);
+       runtime_sizeof_C_MStats = sizeof(MStats) - (_NumSizeClasses - 61) * sizeof(mstats.by_size[0]);
 
        p = nil;
        p_size = 0;
index 065f74a9b58fe83e97a39c9e41534215fc248066..acd919f7abefd1aa1ad2cea1f9c2d52b5b4d21d7 100644 (file)
 
 typedef struct MCentral        MCentral;
 typedef struct MHeap   MHeap;
-typedef struct MSpan   MSpan;
+typedef struct mspan   MSpan;
 typedef struct MStats  MStats;
-typedef struct MLink   MLink;
-typedef struct MTypes  MTypes;
-typedef struct GCStats GCStats;
+typedef struct mlink   MLink;
+typedef struct mtypes  MTypes;
+typedef struct gcstats GCStats;
 
 enum
 {
@@ -100,10 +100,10 @@ enum
 {
        // Computed constant.  The definition of MaxSmallSize and the
        // algorithm in msize.c produce some number of different allocation
-       // size classes.  NumSizeClasses is that number.  It's needed here
+       // size classes.  _NumSizeClasses is that number.  It's needed here
        // because there are static arrays of this length; when msize runs its
        // size choosing algorithm it double-checks that NumSizeClasses agrees.
-       NumSizeClasses = 67,
+       // _NumSizeClasses is defined in runtime2.go as 67.
 
        // Tunable constants.
        MaxSmallSize = 32<<10,
@@ -148,13 +148,6 @@ enum
 #else
 #define        MaxMem  ((uintptr)-1)
 #endif
-
-// A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
-struct MLink
-{
-       MLink *next;
-};
-
 // SysAlloc obtains a large chunk of zeroed memory from the
 // operating system, typically on the order of a hundred kilobytes
 // or a megabyte.
@@ -274,7 +267,7 @@ struct MStats
                uint32 size;
                uint64 nmalloc;
                uint64 nfree;
-       } by_size[NumSizeClasses];
+       } by_size[_NumSizeClasses];
 };
 
 extern MStats mstats
@@ -284,7 +277,7 @@ void        runtime_updatememstats(GCStats *stats);
 // Size classes.  Computed and initialized by InitSizes.
 //
 // SizeToClass(0 <= n <= MaxSmallSize) returns the size class,
-//     1 <= sizeclass < NumSizeClasses, for n.
+//     1 <= sizeclass < _NumSizeClasses, for n.
 //     Size class 0 is reserved to mean "not small".
 //
 // class_to_size[i] = largest size in class i
@@ -293,41 +286,14 @@ void      runtime_updatememstats(GCStats *stats);
 
 int32  runtime_SizeToClass(int32);
 uintptr        runtime_roundupsize(uintptr);
-extern int32   runtime_class_to_size[NumSizeClasses];
-extern int32   runtime_class_to_allocnpages[NumSizeClasses];
+extern int32   runtime_class_to_size[_NumSizeClasses];
+extern int32   runtime_class_to_allocnpages[_NumSizeClasses];
 extern int8    runtime_size_to_class8[1024/8 + 1];
 extern int8    runtime_size_to_class128[(MaxSmallSize-1024)/128 + 1];
 extern void    runtime_InitSizes(void);
 
 
-typedef struct MCacheList MCacheList;
-struct MCacheList
-{
-       MLink *list;
-       uint32 nlist;
-};
-
-// Per-thread (in Go, per-P) cache for small objects.
-// No locking needed because it is per-thread (per-P).
-struct MCache
-{
-       // The following members are accessed on every malloc,
-       // so they are grouped here for better caching.
-       int32 next_sample;              // trigger heap sample after allocating this many bytes
-       intptr local_cachealloc;        // bytes allocated (or freed) from cache since last lock of heap
-       // Allocator cache for tiny objects w/o pointers.
-       // See "Tiny allocator" comment in malloc.goc.
-       byte*   tiny;
-       uintptr tinysize;
-       // The rest is not accessed on every malloc.
-       MSpan*  alloc[NumSizeClasses];  // spans to allocate from
-       MCacheList free[NumSizeClasses];// lists of explicitly freed objects
-       // Local allocator stats, flushed during GC.
-       uintptr local_nlookup;          // number of pointer lookups
-       uintptr local_largefree;        // bytes freed for large objects (>MaxSmallSize)
-       uintptr local_nlargefree;       // number of frees for large objects (>MaxSmallSize)
-       uintptr local_nsmallfree[NumSizeClasses];       // number of frees for small objects (<=MaxSmallSize)
-};
+typedef struct mcachelist MCacheList;
 
 MSpan* runtime_MCache_Refill(MCache *c, int32 sizeclass);
 void   runtime_MCache_Free(MCache *c, MLink *p, int32 sizeclass, uintptr size);
@@ -364,11 +330,6 @@ enum
        MTypes_Words = 2,
        MTypes_Bytes = 3,
 };
-struct MTypes
-{
-       byte    compression;    // one of MTypes_*
-       uintptr data;
-};
 
 enum
 {
@@ -380,13 +341,7 @@ enum
        // if that happens.
 };
 
-typedef struct Special Special;
-struct Special
-{
-       Special*        next;   // linked list in span
-       uint16          offset; // span offset of object
-       byte            kind;   // kind of Special
-};
+typedef struct special Special;
 
 // The described object has a finalizer set for it.
 typedef struct SpecialFinalizer SpecialFinalizer;
@@ -415,33 +370,6 @@ enum
        MSpanListHead,
        MSpanDead,
 };
-struct MSpan
-{
-       MSpan   *next;          // in a span linked list
-       MSpan   *prev;          // in a span linked list
-       PageID  start;          // starting page number
-       uintptr npages;         // number of pages in span
-       MLink   *freelist;      // list of free objects
-       // sweep generation:
-       // if sweepgen == h->sweepgen - 2, the span needs sweeping
-       // if sweepgen == h->sweepgen - 1, the span is currently being swept
-       // if sweepgen == h->sweepgen, the span is swept and ready to use
-       // h->sweepgen is incremented by 2 after every GC
-       uint32  sweepgen;
-       uint16  ref;            // capacity - number of objects in freelist
-       uint8   sizeclass;      // size class
-       bool    incache;        // being used by an MCache
-       uint8   state;          // MSpanInUse etc
-       uint8   needzero;       // needs to be zeroed before allocation
-       uintptr elemsize;       // computed from sizeclass or from npages
-       int64   unusedsince;    // First time spotted by GC in MSpanFree state
-       uintptr npreleased;     // number of pages released to the OS
-       byte    *limit;         // end of data in span
-       MTypes  types;          // types of allocated objects in this span
-       Lock    specialLock;    // guards specials list
-       Special *specials;      // linked list of special records sorted by offset.
-       MLink   *freebuf;       // objects freed explicitly, not incorporated into freelist yet
-};
 
 void   runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages);
 void   runtime_MSpan_EnsureSwept(MSpan *span);
@@ -509,7 +437,7 @@ struct MHeap
        struct {
                MCentral;
                byte pad[64];
-       } central[NumSizeClasses];
+       } central[_NumSizeClasses];
 
        FixAlloc spanalloc;     // allocator for Span*
        FixAlloc cachealloc;    // allocator for MCache*
@@ -520,7 +448,7 @@ struct MHeap
        // Malloc stats.
        uint64 largefree;       // bytes freed for large objects (>MaxSmallSize)
        uint64 nlargefree;      // number of frees for large objects (>MaxSmallSize)
-       uint64 nsmallfree[NumSizeClasses];      // number of frees for small objects (<=MaxSmallSize)
+       uint64 nsmallfree[_NumSizeClasses];     // number of frees for small objects (<=MaxSmallSize)
 };
 extern MHeap runtime_mheap;
 
index 746711a0d3bdba2adcce4077a3512350a4cfa1a8..439627146951a47a0d3682edb73feef8c1cf965a 100644 (file)
@@ -27,7 +27,7 @@ runtime_allocmcache(void)
        c = runtime_FixAlloc_Alloc(&runtime_mheap.cachealloc);
        runtime_unlock(&runtime_mheap);
        runtime_memclr((byte*)c, sizeof(*c));
-       for(i = 0; i < NumSizeClasses; i++)
+       for(i = 0; i < _NumSizeClasses; i++)
                c->alloc[i] = &emptymspan;
 
        // Set first allocation sample size.
@@ -115,7 +115,7 @@ runtime_MCache_ReleaseAll(MCache *c)
        MSpan *s;
        MCacheList *l;
 
-       for(i=0; i<NumSizeClasses; i++) {
+       for(i=0; i<_NumSizeClasses; i++) {
                s = c->alloc[i];
                if(s != &emptymspan) {
                        runtime_MCentral_UncacheSpan(&runtime_mheap.central[i], s);
index e41a83fbf03383d9ad25caedbe63e239f321ec3a..62e2c2d7dfb5d57f022c6f41eddc62bf392eb9db 100644 (file)
@@ -272,7 +272,7 @@ MCentral_Grow(MCentral *c)
        // Carve span into sequence of blocks.
        tailp = &s->freelist;
        p = (byte*)(s->start << PageShift);
-       s->limit = p + size*n;
+       s->limit = (uintptr)(p + size*n);
        for(i=0; i<n; i++) {
                v = (MLink*)p;
                *tailp = v;
index d7d0b27ba9c3fa07b5f72d3b2e64a4f907d8ba7a..1f6a40cd630724404717438df4c91cf242eb6789 100644 (file)
@@ -321,7 +321,7 @@ markonly(const void *obj)
        x = k;
        x -= (uintptr)runtime_mheap.arena_start>>PageShift;
        s = runtime_mheap.spans[x];
-       if(s == nil || k < s->start || (const byte*)obj >= s->limit || s->state != MSpanInUse)
+       if(s == nil || k < s->start || (uintptr)obj >= s->limit || s->state != MSpanInUse)
                return false;
        p = (byte*)((uintptr)s->start<<PageShift);
        if(s->sizeclass == 0) {
@@ -517,7 +517,7 @@ flushptrbuf(Scanbuf *sbuf)
                x = k;
                x -= (uintptr)arena_start>>PageShift;
                s = runtime_mheap.spans[x];
-               if(s == nil || k < s->start || obj >= s->limit || s->state != MSpanInUse)
+               if(s == nil || k < s->start || (uintptr)obj >= s->limit || s->state != MSpanInUse)
                        continue;
                p = (byte*)((uintptr)s->start<<PageShift);
                if(s->sizeclass == 0) {
@@ -651,8 +651,8 @@ static uintptr defaultProg[2] = {PtrSize, GC_DEFAULT_PTR};
 static uintptr chanProg[2] = {0, GC_CHAN};
 
 // Local variables of a program fragment or loop
-typedef struct Frame Frame;
-struct Frame {
+typedef struct GCFrame GCFrame;
+struct GCFrame {
        uintptr count, elemsize, b;
        const uintptr *loop_or_ret;
 };
@@ -731,7 +731,7 @@ scanblock(Workbuf *wbuf, bool keepworking)
        const Type *t, *et;
        Slice *sliceptr;
        String *stringptr;
-       Frame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4];
+       GCFrame *stack_ptr, stack_top, stack[GC_STACK_CAPACITY+4];
        BufferList *scanbuffers;
        Scanbuf sbuf;
        Eface *eface;
@@ -1057,7 +1057,7 @@ scanblock(Workbuf *wbuf, bool keepworking)
 
                        // Stack push.
                        *stack_ptr-- = stack_top;
-                       stack_top = (Frame){count, elemsize, i, pc};
+                       stack_top = (GCFrame){count, elemsize, i, pc};
                        continue;
 
                case GC_ARRAY_NEXT:
@@ -1074,7 +1074,7 @@ scanblock(Workbuf *wbuf, bool keepworking)
                case GC_CALL:
                        // Stack push.
                        *stack_ptr-- = stack_top;
-                       stack_top = (Frame){1, 0, stack_top.b + pc[1], pc+3 /*return address*/};
+                       stack_top = (GCFrame){1, 0, stack_top.b + pc[1], pc+3 /*return address*/};
                        pc = (const uintptr*)((const byte*)pc + *(const int32*)(pc+2));  // target of the CALL instruction
                        continue;
 
@@ -1357,7 +1357,7 @@ markroot(ParFor *desc, uint32 i)
                gp = runtime_allg[i - RootCount];
                // remember when we've first observed the G blocked
                // needed only to output in traceback
-               if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince == 0)
+               if((gp->atomicstatus == _Gwaiting || gp->atomicstatus == _Gsyscall) && gp->waitsince == 0)
                        gp->waitsince = work.tstart;
                addstackroots(gp, &wbuf);
                break;
@@ -1472,17 +1472,17 @@ handoff(Workbuf *b)
 static void
 addstackroots(G *gp, Workbuf **wbufp)
 {
-       switch(gp->status){
+       switch(gp->atomicstatus){
        default:
-               runtime_printf("unexpected G.status %d (goroutine %p %D)\n", gp->status, gp, gp->goid);
+               runtime_printf("unexpected G.status %d (goroutine %p %D)\n", gp->atomicstatus, gp, gp->goid);
                runtime_throw("mark - bad status");
-       case Gdead:
+       case _Gdead:
                return;
-       case Grunning:
+       case _Grunning:
                runtime_throw("mark - world not stopped");
-       case Grunnable:
-       case Gsyscall:
-       case Gwaiting:
+       case _Grunnable:
+       case _Gsyscall:
+       case _Gwaiting:
                break;
        }
 
@@ -1512,12 +1512,12 @@ addstackroots(G *gp, Workbuf **wbufp)
                // the system call instead, since that won't change underfoot.
                if(gp->gcstack != nil) {
                        sp = gp->gcstack;
-                       spsize = gp->gcstack_size;
-                       next_segment = gp->gcnext_segment;
-                       next_sp = gp->gcnext_sp;
-                       initial_sp = gp->gcinitial_sp;
+                       spsize = gp->gcstacksize;
+                       next_segment = gp->gcnextsegment;
+                       next_sp = gp->gcnextsp;
+                       initial_sp = gp->gcinitialsp;
                } else {
-                       sp = __splitstack_find_context(&gp->stack_context[0],
+                       sp = __splitstack_find_context(&gp->stackcontext[0],
                                                       &spsize, &next_segment,
                                                       &next_sp, &initial_sp);
                }
@@ -1543,11 +1543,11 @@ addstackroots(G *gp, Workbuf **wbufp)
        } else {
                // Scanning another goroutine's stack.
                // The goroutine is usually asleep (the world is stopped).
-               bottom = (byte*)gp->gcnext_sp;
+               bottom = (byte*)gp->gcnextsp;
                if(bottom == nil)
                        return;
        }
-       top = (byte*)gp->gcinitial_sp + gp->gcstack_size;
+       top = (byte*)gp->gcinitialsp + gp->gcstacksize;
        if(top > bottom)
                enqueue1(wbufp, (Obj){bottom, top - bottom, 0});
        else
@@ -2186,8 +2186,8 @@ runtime_gc(int32 force)
                // switch to g0, call gc(&a), then switch back
                g = runtime_g();
                g->param = &a;
-               g->status = Gwaiting;
-               g->waitreason = "garbage collection";
+               g->atomicstatus = _Gwaiting;
+               g->waitreason = runtime_gostringnocopy((const byte*)"garbage collection");
                runtime_mcall(mgc);
                m = runtime_m();
        }
@@ -2214,7 +2214,7 @@ mgc(G *gp)
 {
        gc(gp->param);
        gp->param = nil;
-       gp->status = Grunning;
+       gp->atomicstatus = _Grunning;
        runtime_gogo(gp);
 }
 
@@ -2404,7 +2404,7 @@ runtime_ReadMemStats(MStats *stats)
        runtime_stoptheworld();
        runtime_updatememstats(nil);
        // Size of the trailing by_size array differs between Go and C,
-       // NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
+       // _NumSizeClasses was changed, but we can not change Go struct because of backward compatibility.
        runtime_memmove(stats, &mstats, runtime_sizeof_C_MStats);
        m->gcing = 0;
        m->locks++;
index 793915ef44c6682b17a537ed479854bf3512c089..04dc971d688489a7cdcaf58847a215905e9b3595 100644 (file)
@@ -176,7 +176,7 @@ runtime_MHeap_Alloc(MHeap *h, uintptr npage, int32 sizeclass, bool large, bool n
        MSpan *s;
 
        runtime_lock(h);
-       mstats.heap_alloc += runtime_m()->mcache->local_cachealloc;
+       mstats.heap_alloc += (intptr)runtime_m()->mcache->local_cachealloc;
        runtime_m()->mcache->local_cachealloc = 0;
        s = MHeap_AllocLocked(h, npage, sizeclass);
        if(s != nil) {
@@ -377,7 +377,7 @@ runtime_MHeap_LookupMaybe(MHeap *h, void *v)
        q = p;
        q -= (uintptr)h->arena_start >> PageShift;
        s = h->spans[q];
-       if(s == nil || p < s->start || (byte*)v >= s->limit || s->state != MSpanInUse)
+       if(s == nil || p < s->start || (uintptr)v >= s->limit || s->state != MSpanInUse)
                return nil;
        return s;
 }
@@ -387,7 +387,7 @@ void
 runtime_MHeap_Free(MHeap *h, MSpan *s, int32 acct)
 {
        runtime_lock(h);
-       mstats.heap_alloc += runtime_m()->mcache->local_cachealloc;
+       mstats.heap_alloc += (intptr)runtime_m()->mcache->local_cachealloc;
        runtime_m()->mcache->local_cachealloc = 0;
        mstats.heap_inuse -= s->npages<<PageShift;
        if(acct) {
@@ -597,7 +597,7 @@ runtime_MSpan_Init(MSpan *span, PageID start, uintptr npages)
        span->unusedsince = 0;
        span->npreleased = 0;
        span->types.compression = MTypes_Empty;
-       span->specialLock.key = 0;
+       span->speciallock.key = 0;
        span->specials = nil;
        span->needzero = 0;
        span->freebuf = nil;
@@ -681,13 +681,13 @@ addspecial(void *p, Special *s)
        offset = (uintptr)p - (span->start << PageShift);
        kind = s->kind;
 
-       runtime_lock(&span->specialLock);
+       runtime_lock(&span->speciallock);
 
        // Find splice point, check for existing record.
        t = &span->specials;
        while((x = *t) != nil) {
                if(offset == x->offset && kind == x->kind) {
-                       runtime_unlock(&span->specialLock);
+                       runtime_unlock(&span->speciallock);
                        runtime_m()->locks--;
                        return false; // already exists
                }
@@ -699,7 +699,7 @@ addspecial(void *p, Special *s)
        s->offset = offset;
        s->next = x;
        *t = s;
-       runtime_unlock(&span->specialLock);
+       runtime_unlock(&span->speciallock);
        runtime_m()->locks--;
        return true;
 }
@@ -725,20 +725,20 @@ removespecial(void *p, byte kind)
 
        offset = (uintptr)p - (span->start << PageShift);
 
-       runtime_lock(&span->specialLock);
+       runtime_lock(&span->speciallock);
        t = &span->specials;
        while((s = *t) != nil) {
                // This function is used for finalizers only, so we don't check for
                // "interior" specials (p must be exactly equal to s->offset).
                if(offset == s->offset && kind == s->kind) {
                        *t = s->next;
-                       runtime_unlock(&span->specialLock);
+                       runtime_unlock(&span->speciallock);
                        runtime_m()->locks--;
                        return s;
                }
                t = &s->next;
        }
-       runtime_unlock(&span->specialLock);
+       runtime_unlock(&span->speciallock);
        runtime_m()->locks--;
        return nil;
 }
@@ -838,7 +838,7 @@ runtime_freeallspecials(MSpan *span, void *p, uintptr size)
        // this is required to not cause deadlock between span->specialLock and proflock
        list = nil;
        offset = (uintptr)p - (span->start << PageShift);
-       runtime_lock(&span->specialLock);
+       runtime_lock(&span->speciallock);
        t = &span->specials;
        while((s = *t) != nil) {
                if(offset + size <= s->offset)
@@ -850,7 +850,7 @@ runtime_freeallspecials(MSpan *span, void *p, uintptr size)
                } else
                        t = &s->next;
        }
-       runtime_unlock(&span->specialLock);
+       runtime_unlock(&span->speciallock);
 
        while(list != nil) {
                s = list;
@@ -908,7 +908,7 @@ runtime_MHeap_SplitSpan(MHeap *h, MSpan *s)
                // Allocate a new span for the first half.
                t = runtime_FixAlloc_Alloc(&h->spanalloc);
                runtime_MSpan_Init(t, s->start, npages/2);
-               t->limit = (byte*)((t->start + npages/2) << PageShift);
+               t->limit = (uintptr)((t->start + npages/2) << PageShift);
                t->state = MSpanInUse;
                t->elemsize = npages << (PageShift - 1);
                t->sweepgen = s->sweepgen;
index 4e8cfc9caca62ee2ba8c20cbf6f6d0d51ecb4acb..bb3f9e8c8e0abb06f1349ee22c22f3cdd8bbb1e2 100644 (file)
@@ -479,7 +479,7 @@ func GoroutineProfile(b Slice) (n int, ok bool) {
                        saveg(g, r++);
                        for(i = 0; i < runtime_allglen; i++) {
                                gp = runtime_allg[i];
-                               if(gp == g || gp->status == Gdead)
+                               if(gp == g || gp->atomicstatus == _Gdead)
                                        continue;
                                saveg(gp, r++);
                        }
index 34509d0456817c3872018aa2cc134f780da6cf99..1bafc82bd618c82882a96c16109ffa5928b42027 100644 (file)
@@ -29,8 +29,8 @@
 #include "arch.h"
 #include "malloc.h"
 
-int32 runtime_class_to_size[NumSizeClasses];
-int32 runtime_class_to_allocnpages[NumSizeClasses];
+int32 runtime_class_to_size[_NumSizeClasses];
+int32 runtime_class_to_allocnpages[_NumSizeClasses];
 
 // The SizeToClass lookup is implemented using two arrays,
 // one mapping sizes <= 1024 to their class and one mapping
@@ -101,14 +101,14 @@ runtime_InitSizes(void)
                runtime_class_to_size[sizeclass] = size;
                sizeclass++;
        }
-       if(sizeclass != NumSizeClasses) {
-               runtime_printf("sizeclass=%d NumSizeClasses=%d\n", sizeclass, NumSizeClasses);
-               runtime_throw("InitSizes - bad NumSizeClasses");
+       if(sizeclass != _NumSizeClasses) {
+               runtime_printf("sizeclass=%d _NumSizeClasses=%d\n", sizeclass, _NumSizeClasses);
+               runtime_throw("InitSizes - bad _NumSizeClasses");
        }
 
        // Initialize the size_to_class tables.
        nextsize = 0;
-       for (sizeclass = 1; sizeclass < NumSizeClasses; sizeclass++) {
+       for (sizeclass = 1; sizeclass < _NumSizeClasses; sizeclass++) {
                for(; nextsize < 1024 && nextsize <= runtime_class_to_size[sizeclass]; nextsize+=8)
                        runtime_size_to_class8[nextsize/8] = sizeclass;
                if(nextsize >= 1024)
@@ -120,7 +120,7 @@ runtime_InitSizes(void)
        if(0) {
                for(n=0; n < MaxSmallSize; n++) {
                        sizeclass = runtime_SizeToClass(n);
-                       if(sizeclass < 1 || sizeclass >= NumSizeClasses || runtime_class_to_size[sizeclass] < n) {
+                       if(sizeclass < 1 || sizeclass >= _NumSizeClasses || runtime_class_to_size[sizeclass] < n) {
                                runtime_printf("size=%d sizeclass=%d runtime_class_to_size=%d\n", n, sizeclass, runtime_class_to_size[sizeclass]);
                                runtime_printf("incorrect SizeToClass");
                                goto dump;
@@ -140,9 +140,9 @@ runtime_InitSizes(void)
 
 dump:
        if(1){
-               runtime_printf("NumSizeClasses=%d\n", NumSizeClasses);
+               runtime_printf("NumSizeClasses=%d\n", _NumSizeClasses);
                runtime_printf("runtime_class_to_size:");
-               for(sizeclass=0; sizeclass<NumSizeClasses; sizeclass++)
+               for(sizeclass=0; sizeclass<_NumSizeClasses; sizeclass++)
                        runtime_printf(" %d", runtime_class_to_size[sizeclass]);
                runtime_printf("\n\n");
                runtime_printf("size_to_class8:");
index 2f3fa455f3d930e2e833dfe7a4e926eb71f8b1e8..2744ec5989f65db3af0455f86d2dc9790d8f6b6f 100644 (file)
@@ -301,11 +301,11 @@ runtime_netpollready(G **gpp, PollDesc *pd, int32 mode)
        if(mode == 'w' || mode == 'r'+'w')
                wg = netpollunblock(pd, 'w', true);
        if(rg) {
-               rg->schedlink = *gpp;
+               rg->schedlink = (uintptr)*gpp;
                *gpp = rg;
        }
        if(wg) {
-               wg->schedlink = *gpp;
+               wg->schedlink = (uintptr)*gpp;
                *gpp = wg;
        }
 }
index de000db988993fbe8abb8f7eef82e4f86a2080d8..3fb3bde32232408b1e1a8d5c8983a10db93189fd 100644 (file)
@@ -4,7 +4,6 @@
 
 #include "runtime.h"
 #include "malloc.h"
-#include "go-defer.h"
 #include "go-panic.h"
 
 // Code related to defer, panic and recover.
@@ -21,10 +20,10 @@ runtime_newdefer()
        P *p;
 
        d = nil;
-       p = runtime_m()->p;
+       p = (P*)runtime_m()->p;
        d = p->deferpool;
        if(d)
-               p->deferpool = d->__next;
+               p->deferpool = d->next;
        if(d == nil) {
                // deferpool is empty
                d = runtime_malloc(sizeof(Defer));
@@ -39,10 +38,10 @@ runtime_freedefer(Defer *d)
 {
        P *p;
 
-       if(d->__special)
+       if(d->special)
                return;
-       p = runtime_m()->p;
-       d->__next = p->deferpool;
+       p = (P*)runtime_m()->p;
+       d->next = p->deferpool;
        p->deferpool = d;
        // No need to wipe out pointers in argp/pc/fn/args,
        // because we empty the pool before GC.
@@ -58,14 +57,14 @@ __go_rundefer(void)
        Defer *d;
 
        g = runtime_g();
-       while((d = g->defer) != nil) {
+       while((d = g->_defer) != nil) {
                void (*pfn)(void*);
 
-               g->defer = d->__next;
-               pfn = d->__pfn;
-               d->__pfn = nil;
+               g->_defer = d->next;
+               pfn = (void (*) (void *))d->pfn;
+               d->pfn = 0;
                if (pfn != nil)
-                       (*pfn)(d->__arg);
+                       (*pfn)(d->arg);
                runtime_freedefer(d);
        }
 }
@@ -171,7 +170,7 @@ runtime_canpanic(G *gp)
                return false;
        if(m->locks-m->softfloat != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0)
                return false;
-       if(gp->status != Grunning)
+       if(gp->atomicstatus != _Grunning)
                return false;
 #ifdef GOOS_windows
        if(m->libcallsp != 0)
index defb0a59bb136eec68f65a65a6a7c71dace94a58..1ac03a42372790b36ec031e0fac2dc91ea428add 100644 (file)
@@ -19,7 +19,6 @@
 #include "defs.h"
 #include "malloc.h"
 #include "go-type.h"
-#include "go-defer.h"
 
 #ifdef USING_SPLIT_STACK
 
@@ -62,7 +61,6 @@ static void gtraceback(G*);
 #endif
 
 static __thread G *g;
-static __thread M *m;
 
 #ifndef SETCONTEXT_CLOBBERS_TLS
 
@@ -179,14 +177,15 @@ M* runtime_m(void) __attribute__ ((noinline, no_split_stack));
 M*
 runtime_m(void)
 {
-       return m;
+       if(g == nil)
+               return nil;
+       return g->m;
 }
 
-// Set m and g.
+// Set g.
 void
-runtime_setmg(M* mp, G* gp)
+runtime_setg(G* gp)
 {
-       m = mp;
        g = gp;
 }
 
@@ -242,12 +241,12 @@ void
 runtime_gogo(G* newg)
 {
 #ifdef USING_SPLIT_STACK
-       __splitstack_setcontext(&newg->stack_context[0]);
+       __splitstack_setcontext(&newg->stackcontext[0]);
 #endif
        g = newg;
        newg->fromgogo = true;
-       fixcontext(&newg->context);
-       setcontext(&newg->context);
+       fixcontext((ucontext_t*)&newg->context[0]);
+       setcontext((ucontext_t*)&newg->context[0]);
        runtime_throw("gogo setcontext returned");
 }
 
@@ -266,37 +265,37 @@ runtime_mcall(void (*pfn)(G*))
        // collector.
        __builtin_unwind_init();
 
-       mp = m;
        gp = g;
+       mp = gp->m;
        if(gp == mp->g0)
                runtime_throw("runtime: mcall called on m->g0 stack");
 
        if(gp != nil) {
 
 #ifdef USING_SPLIT_STACK
-               __splitstack_getcontext(&g->stack_context[0]);
+               __splitstack_getcontext(&g->stackcontext[0]);
 #else
-               gp->gcnext_sp = &pfn;
+               gp->gcnextsp = &pfn;
 #endif
                gp->fromgogo = false;
-               getcontext(&gp->context);
+               getcontext((ucontext_t*)&gp->context[0]);
 
                // When we return from getcontext, we may be running
-               // in a new thread.  That means that m and g may have
-               // changed.  They are global variables so we will
-               // reload them, but the addresses of m and g may be
-               // cached in our local stack frame, and those
-               // addresses may be wrong.  Call functions to reload
-               // the values for this thread.
-               mp = runtime_m();
+               // in a new thread.  That means that g may have
+               // changed.  It is a global variables so we will
+               // reload it, but the address of g may be cached in
+               // our local stack frame, and that address may be
+               // wrong.  Call the function to reload the value for
+               // this thread.
                gp = runtime_g();
+               mp = gp->m;
 
                if(gp->traceback != nil)
                        gtraceback(gp);
        }
        if (gp == nil || !gp->fromgogo) {
 #ifdef USING_SPLIT_STACK
-               __splitstack_setcontext(&mp->g0->stack_context[0]);
+               __splitstack_setcontext(&mp->g0->stackcontext[0]);
 #endif
                mp->g0->entry = (byte*)pfn;
                mp->g0->param = gp;
@@ -306,8 +305,8 @@ runtime_mcall(void (*pfn)(G*))
                // the getcontext call just above.
                g = mp->g0;
 
-               fixcontext(&mp->g0->context);
-               setcontext(&mp->g0->context);
+               fixcontext((ucontext_t*)&mp->g0->context[0]);
+               setcontext((ucontext_t*)&mp->g0->context[0]);
                runtime_throw("runtime: mcall function returned");
        }
 }
@@ -360,10 +359,6 @@ struct Sched {
 
 enum
 {
-       // The max value of GOMAXPROCS.
-       // There are no fundamental restrictions on the value.
-       MaxGomaxprocs = 1<<8,
-
        // Number of goroutine ids to grab from runtime_sched.goidgen to local per-P cache at once.
        // 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
        GoidCacheBatch = 16,
@@ -442,6 +437,7 @@ bool runtime_isstarted;
 void
 runtime_schedinit(void)
 {
+       M *m;
        int32 n, procs;
        String s;
        const byte *p;
@@ -481,11 +477,11 @@ runtime_schedinit(void)
        s = runtime_getenv("GOMAXPROCS");
        p = s.str;
        if(p != nil && (n = runtime_atoi(p, s.len)) > 0) {
-               if(n > MaxGomaxprocs)
-                       n = MaxGomaxprocs;
+               if(n > _MaxGomaxprocs)
+                       n = _MaxGomaxprocs;
                procs = n;
        }
-       runtime_allp = runtime_malloc((MaxGomaxprocs+1)*sizeof(runtime_allp[0]));
+       runtime_allp = runtime_malloc((_MaxGomaxprocs+1)*sizeof(runtime_allp[0]));
        procresize(procs);
 
        // Can not enable GC until all roots are registered.
@@ -583,17 +579,17 @@ runtime_main(void* dummy __attribute__((unused)))
        runtime_lockOSThread();
        
        // Defer unlock so that runtime.Goexit during init does the unlock too.
-       d.__pfn = initDone;
-       d.__next = g->defer;
-       d.__arg = (void*)-1;
-       d.__panic = g->panic;
-       d.__retaddr = nil;
-       d.__makefunc_can_recover = 0;
-       d.__frame = &frame;
-       d.__special = true;
-       g->defer = &d;
-
-       if(m != &runtime_m0)
+       d.pfn = (uintptr)(void*)initDone;
+       d.next = g->_defer;
+       d.arg = (void*)-1;
+       d._panic = g->_panic;
+       d.retaddr = 0;
+       d.makefunccanrecover = 0;
+       d.frame = &frame;
+       d.special = true;
+       g->_defer = &d;
+
+       if(g->m != &runtime_m0)
                runtime_throw("runtime_main not on m0");
        __go_go(runtime_MHeap_Scavenger, nil);
 
@@ -605,9 +601,9 @@ runtime_main(void* dummy __attribute__((unused)))
 
        closechan(runtime_main_init_done);
 
-       if(g->defer != &d || d.__pfn != initDone)
+       if(g->_defer != &d || (void*)d.pfn != initDone)
                runtime_throw("runtime: bad defer entry after init");
-       g->defer = d.__next;
+       g->_defer = d.next;
        runtime_unlockOSThread();
 
        // For gccgo we have to wait until after main is initialized
@@ -640,42 +636,42 @@ runtime_main(void* dummy __attribute__((unused)))
 void
 runtime_goroutineheader(G *gp)
 {
-       const char *status;
+       String status;
        int64 waitfor;
 
-       switch(gp->status) {
-       case Gidle:
-               status = "idle";
+       switch(gp->atomicstatus) {
+       case _Gidle:
+               status = runtime_gostringnocopy((const byte*)"idle");
                break;
-       case Grunnable:
-               status = "runnable";
+       case _Grunnable:
+               status = runtime_gostringnocopy((const byte*)"runnable");
                break;
-       case Grunning:
-               status = "running";
+       case _Grunning:
+               status = runtime_gostringnocopy((const byte*)"running");
                break;
-       case Gsyscall:
-               status = "syscall";
+       case _Gsyscall:
+               status = runtime_gostringnocopy((const byte*)"syscall");
                break;
-       case Gwaiting:
-               if(gp->waitreason)
+       case _Gwaiting:
+               if(gp->waitreason.len > 0)
                        status = gp->waitreason;
                else
-                       status = "waiting";
+                       status = runtime_gostringnocopy((const byte*)"waiting");
                break;
        default:
-               status = "???";
+               status = runtime_gostringnocopy((const byte*)"???");
                break;
        }
 
        // approx time the G is blocked, in minutes
        waitfor = 0;
-       if((gp->status == Gwaiting || gp->status == Gsyscall) && gp->waitsince != 0)
+       if((gp->atomicstatus == _Gwaiting || gp->atomicstatus == _Gsyscall) && gp->waitsince != 0)
                waitfor = (runtime_nanotime() - gp->waitsince) / (60LL*1000*1000*1000);
 
        if(waitfor < 1)
-               runtime_printf("goroutine %D [%s]:\n", gp->goid, status);
+               runtime_printf("goroutine %D [%S]:\n", gp->goid, status);
        else
-               runtime_printf("goroutine %D [%s, %D minutes]:\n", gp->goid, status, waitfor);
+               runtime_printf("goroutine %D [%S, %D minutes]:\n", gp->goid, status, waitfor);
 }
 
 void
@@ -693,13 +689,6 @@ runtime_printcreatedby(G *g)
        }
 }
 
-struct Traceback
-{
-       G* gp;
-       Location locbuf[TracebackMaxFrames];
-       int32 c;
-};
-
 void
 runtime_tracebackothers(G * volatile me)
 {
@@ -712,15 +701,15 @@ runtime_tracebackothers(G * volatile me)
        traceback = runtime_gotraceback(nil);
        
        // Show the current goroutine first, if we haven't already.
-       if((gp = m->curg) != nil && gp != me) {
+       if((gp = g->m->curg) != nil && gp != me) {
                runtime_printf("\n");
                runtime_goroutineheader(gp);
                gp->traceback = &tb;
 
 #ifdef USING_SPLIT_STACK
-               __splitstack_getcontext(&me->stack_context[0]);
+               __splitstack_getcontext(&me->stackcontext[0]);
 #endif
-               getcontext(&me->context);
+               getcontext((ucontext_t*)&me->context[0]);
 
                if(gp->traceback != nil) {
                  runtime_gogo(gp);
@@ -733,7 +722,7 @@ runtime_tracebackothers(G * volatile me)
        runtime_lock(&allglock);
        for(i = 0; i < runtime_allglen; i++) {
                gp = runtime_allg[i];
-               if(gp == me || gp == m->curg || gp->status == Gdead)
+               if(gp == me || gp == g->m->curg || gp->atomicstatus == _Gdead)
                        continue;
                if(gp->issystem && traceback < 2)
                        continue;
@@ -749,19 +738,19 @@ runtime_tracebackothers(G * volatile me)
                // This means that if g is running or in a syscall, we
                // can't reliably print a stack trace.  FIXME.
 
-               if(gp->status == Grunning) {
+               if(gp->atomicstatus == _Grunning) {
                        runtime_printf("\tgoroutine running on other thread; stack unavailable\n");
                        runtime_printcreatedby(gp);
-               } else if(gp->status == Gsyscall) {
+               } else if(gp->atomicstatus == _Gsyscall) {
                        runtime_printf("\tgoroutine in C code; stack unavailable\n");
                        runtime_printcreatedby(gp);
                } else {
                        gp->traceback = &tb;
 
 #ifdef USING_SPLIT_STACK
-                       __splitstack_getcontext(&me->stack_context[0]);
+                       __splitstack_getcontext(&me->stackcontext[0]);
 #endif
-                       getcontext(&me->context);
+                       getcontext((ucontext_t*)&me->context[0]);
 
                        if(gp->traceback != nil) {
                                runtime_gogo(gp);
@@ -794,8 +783,12 @@ gtraceback(G* gp)
 
        traceback = gp->traceback;
        gp->traceback = nil;
+       if(gp->m != nil)
+               runtime_throw("gtraceback: m is not nil");
+       gp->m = traceback->gp->m;
        traceback->c = runtime_callers(1, traceback->locbuf,
                sizeof traceback->locbuf / sizeof traceback->locbuf[0], false);
+       gp->m = nil;
        runtime_gogo(traceback->gp);
 }
 
@@ -804,7 +797,7 @@ mcommoninit(M *mp)
 {
        // If there is no mcache runtime_callers() will crash,
        // and we are most likely in sysmon thread so the stack is senseless anyway.
-       if(m->mcache)
+       if(g->m->mcache)
                runtime_callers(1, mp->createstack, nelem(mp->createstack), false);
 
        mp->fastrand = 0x49f6428aUL + mp->id + runtime_cputicks();
@@ -828,16 +821,16 @@ void
 runtime_ready(G *gp)
 {
        // Mark runnable.
-       m->locks++;  // disable preemption because it can be holding p in a local var
-       if(gp->status != Gwaiting) {
-               runtime_printf("goroutine %D has status %d\n", gp->goid, gp->status);
-               runtime_throw("bad g->status in ready");
+       g->m->locks++;  // disable preemption because it can be holding p in a local var
+       if(gp->atomicstatus != _Gwaiting) {
+               runtime_printf("goroutine %D has status %d\n", gp->goid, gp->atomicstatus);
+               runtime_throw("bad g->atomicstatus in ready");
        }
-       gp->status = Grunnable;
-       runqput(m->p, gp);
+       gp->atomicstatus = _Grunnable;
+       runqput((P*)g->m->p, gp);
        if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0)  // TODO: fast atomic
                wakep();
-       m->locks--;
+       g->m->locks--;
 }
 
 int32
@@ -884,7 +877,7 @@ runtime_helpgc(int32 nproc)
        runtime_lock(&runtime_sched);
        pos = 0;
        for(n = 1; n < nproc; n++) {  // one M is currently running
-               if(runtime_allp[pos]->mcache == m->mcache)
+               if(runtime_allp[pos]->mcache == g->m->mcache)
                        pos++;
                mp = mget();
                if(mp == nil)
@@ -938,18 +931,18 @@ runtime_stoptheworld(void)
        runtime_atomicstore((uint32*)&runtime_sched.gcwaiting, 1);
        preemptall();
        // stop current P
-       m->p->status = Pgcstop;
+       ((P*)g->m->p)->status = _Pgcstop;
        runtime_sched.stopwait--;
-       // try to retake all P's in Psyscall status
+       // try to retake all P's in _Psyscall status
        for(i = 0; i < runtime_gomaxprocs; i++) {
                p = runtime_allp[i];
                s = p->status;
-               if(s == Psyscall && runtime_cas(&p->status, s, Pgcstop))
+               if(s == _Psyscall && runtime_cas(&p->status, s, _Pgcstop))
                        runtime_sched.stopwait--;
        }
        // stop idle P's
        while((p = pidleget()) != nil) {
-               p->status = Pgcstop;
+               p->status = _Pgcstop;
                runtime_sched.stopwait--;
        }
        wait = runtime_sched.stopwait > 0;
@@ -964,7 +957,7 @@ runtime_stoptheworld(void)
                runtime_throw("stoptheworld: not stopped");
        for(i = 0; i < runtime_gomaxprocs; i++) {
                p = runtime_allp[i];
-               if(p->status != Pgcstop)
+               if(p->status != _Pgcstop)
                        runtime_throw("stoptheworld: not stopped");
        }
 }
@@ -972,7 +965,7 @@ runtime_stoptheworld(void)
 static void
 mhelpgc(void)
 {
-       m->helpgc = -1;
+       g->m->helpgc = -1;
 }
 
 void
@@ -983,7 +976,7 @@ runtime_starttheworld(void)
        G *gp;
        bool add;
 
-       m->locks++;  // disable preemption because it can be holding p in a local var
+       g->m->locks++;  // disable preemption because it can be holding p in a local var
        gp = runtime_netpoll(false);  // non-blocking
        injectglist(gp);
        add = needaddgcproc();
@@ -1003,8 +996,8 @@ runtime_starttheworld(void)
                        pidleput(p);
                        break;
                }
-               p->m = mget();
-               p->link = p1;
+               p->m = (uintptr)mget();
+               p->link = (uintptr)p1;
                p1 = p;
        }
        if(runtime_sched.sysmonwait) {
@@ -1015,13 +1008,13 @@ runtime_starttheworld(void)
 
        while(p1) {
                p = p1;
-               p1 = p1->link;
+               p1 = (P*)p1->link;
                if(p->m) {
-                       mp = p->m;
-                       p->m = nil;
+                       mp = (M*)p->m;
+                       p->m = 0;
                        if(mp->nextp)
                                runtime_throw("starttheworld: inconsistent mp->nextp");
-                       mp->nextp = p;
+                       mp->nextp = (uintptr)p;
                        runtime_notewakeup(&mp->park);
                } else {
                        // Start M to run P.  Do not start another M below.
@@ -1040,15 +1033,18 @@ runtime_starttheworld(void)
                // the maximum number of procs.
                newm(mhelpgc, nil);
        }
-       m->locks--;
+       g->m->locks--;
 }
 
 // Called to start an M.
 void*
 runtime_mstart(void* mp)
 {
+       M *m;
+
        m = (M*)mp;
        g = m->g0;
+       g->m = m;
 
        initcontext();
 
@@ -1059,15 +1055,15 @@ runtime_mstart(void* mp)
        // Once we call schedule we're never coming back,
        // so other calls can reuse this stack space.
 #ifdef USING_SPLIT_STACK
-       __splitstack_getcontext(&g->stack_context[0]);
+       __splitstack_getcontext(&g->stackcontext[0]);
 #else
-       g->gcinitial_sp = &mp;
-       // Setting gcstack_size to 0 is a marker meaning that gcinitial_sp
+       g->gcinitialsp = &mp;
+       // Setting gcstacksize to 0 is a marker meaning that gcinitialsp
        // is the top of the stack, not the bottom.
-       g->gcstack_size = 0;
-       g->gcnext_sp = &mp;
+       g->gcstacksize = 0;
+       g->gcnextsp = &mp;
 #endif
-       getcontext(&g->context);
+       getcontext((ucontext_t*)&g->context[0]);
 
        if(g->entry != nil) {
                // Got here from mcall.
@@ -1097,14 +1093,14 @@ runtime_mstart(void* mp)
        }
        
        if(m->mstartfn)
-               m->mstartfn();
+               ((void (*)(void))m->mstartfn)();
 
        if(m->helpgc) {
                m->helpgc = 0;
                stopm();
        } else if(m != &runtime_m0) {
-               acquirep(m->nextp);
-               m->nextp = nil;
+               acquirep((P*)m->nextp);
+               m->nextp = 0;
        }
        schedule();
 
@@ -1127,12 +1123,12 @@ struct CgoThreadStart
 // Allocate a new m unassociated with any thread.
 // Can use p for allocation context if needed.
 M*
-runtime_allocm(P *p, int32 stacksize, byte** ret_g0_stack, size_t* ret_g0_stacksize)
+runtime_allocm(P *p, int32 stacksize, byte** ret_g0_stack, uintptr* ret_g0_stacksize)
 {
        M *mp;
 
-       m->locks++;  // disable GC because it can be called from sysmon
-       if(m->p == nil)
+       g->m->locks++;  // disable GC because it can be called from sysmon
+       if(g->m->p == 0)
                acquirep(p);  // temporarily borrow p for mallocs in this function
 #if 0
        if(mtype == nil) {
@@ -1145,10 +1141,11 @@ runtime_allocm(P *p, int32 stacksize, byte** ret_g0_stack, size_t* ret_g0_stacks
        mp = runtime_mal(sizeof *mp);
        mcommoninit(mp);
        mp->g0 = runtime_malg(stacksize, ret_g0_stack, ret_g0_stacksize);
+       mp->g0->m = mp;
 
-       if(p == m->p)
+       if(p == (P*)g->m->p)
                releasep();
-       m->locks--;
+       g->m->locks--;
 
        return mp;
 }
@@ -1235,26 +1232,26 @@ runtime_needm(void)
        // after exitsyscall makes sure it is okay to be
        // running at all (that is, there's no garbage collection
        // running right now).
-       mp->needextram = mp->schedlink == nil;
-       unlockextra(mp->schedlink);
+       mp->needextram = mp->schedlink == 0;
+       unlockextra((M*)mp->schedlink);
 
-       // Install m and g (= m->curg).
-       runtime_setmg(mp, mp->curg);
+       // Install g (= m->curg).
+       runtime_setg(mp->curg);
 
        // Initialize g's context as in mstart.
        initcontext();
-       g->status = Gsyscall;
+       g->atomicstatus = _Gsyscall;
        g->entry = nil;
        g->param = nil;
 #ifdef USING_SPLIT_STACK
-       __splitstack_getcontext(&g->stack_context[0]);
+       __splitstack_getcontext(&g->stackcontext[0]);
 #else
-       g->gcinitial_sp = &mp;
+       g->gcinitialsp = &mp;
        g->gcstack = nil;
-       g->gcstack_size = 0;
-       g->gcnext_sp = &mp;
+       g->gcstacksize = 0;
+       g->gcnextsp = &mp;
 #endif
-       getcontext(&g->context);
+       getcontext((ucontext_t*)&g->context[0]);
 
        if(g->entry != nil) {
                // Got here from mcall.
@@ -1284,7 +1281,7 @@ runtime_newextram(void)
        M *mp, *mnext;
        G *gp;
        byte *g0_sp, *sp;
-       size_t g0_spsize, spsize;
+       uintptr g0_spsize, spsize;
 
        // Create extra goroutine locked to extra m.
        // The goroutine is the context in which the cgo callback will run.
@@ -1293,9 +1290,10 @@ runtime_newextram(void)
        // the goroutine stack ends.
        mp = runtime_allocm(nil, StackMin, &g0_sp, &g0_spsize);
        gp = runtime_malg(StackMin, &sp, &spsize);
-       gp->status = Gdead;
+       gp->atomicstatus = _Gdead;
+       gp->m = mp;
        mp->curg = gp;
-       mp->locked = LockInternal;
+       mp->locked = _LockInternal;
        mp->lockedg = gp;
        gp->lockedm = mp;
        gp->goid = runtime_xadd64(&runtime_sched.goidgen, 1);
@@ -1304,14 +1302,14 @@ runtime_newextram(void)
 
        // The context for gp will be set up in runtime_needm.  But
        // here we need to set up the context for g0.
-       getcontext(&mp->g0->context);
-       mp->g0->context.uc_stack.ss_sp = g0_sp;
-       mp->g0->context.uc_stack.ss_size = g0_spsize;
-       makecontext(&mp->g0->context, kickoff, 0);
+       getcontext((ucontext_t*)&mp->g0->context[0]);
+       ((ucontext_t*)&mp->g0->context[0])->uc_stack.ss_sp = g0_sp;
+       ((ucontext_t*)&mp->g0->context[0])->uc_stack.ss_size = (size_t)g0_spsize;
+       makecontext((ucontext_t*)&mp->g0->context[0], kickoff, 0);
 
        // Add m to the extra list.
        mnext = lockextra(true);
-       mp->schedlink = mnext;
+       mp->schedlink = (uintptr)mnext;
        unlockextra(mp);
 }
 
@@ -1347,16 +1345,16 @@ runtime_dropm(void)
        runtime_unminit();
 
        // Clear m and g, and return m to the extra list.
-       // After the call to setmg we can only call nosplit functions.
-       mp = m;
-       runtime_setmg(nil, nil);
+       // After the call to setg we can only call nosplit functions.
+       mp = g->m;
+       runtime_setg(nil);
 
-       mp->curg->status = Gdead;
+       mp->curg->atomicstatus = _Gdead;
        mp->curg->gcstack = nil;
-       mp->curg->gcnext_sp = nil;
+       mp->curg->gcnextsp = nil;
 
        mnext = lockextra(true);
-       mp->schedlink = mnext;
+       mp->schedlink = (uintptr)mnext;
        unlockextra(mp);
 }
 
@@ -1417,7 +1415,7 @@ countextra()
                        continue;
                }
                c = 0;
-               for(mc = mp; mc != nil; mc = mc->schedlink)
+               for(mc = mp; mc != nil; mc = (M*)mc->schedlink)
                        c++;
                runtime_atomicstorep(&runtime_extram, mp);
                return c;
@@ -1431,8 +1429,8 @@ newm(void(*fn)(void), P *p)
        M *mp;
 
        mp = runtime_allocm(p, -1, nil, nil);
-       mp->nextp = p;
-       mp->mstartfn = fn;
+       mp->nextp = (uintptr)p;
+       mp->mstartfn = (uintptr)(void*)fn;
 
        runtime_newosproc(mp);
 }
@@ -1442,6 +1440,9 @@ newm(void(*fn)(void), P *p)
 static void
 stopm(void)
 {
+       M* m;
+
+       m = g->m;
        if(m->locks)
                runtime_throw("stopm holding locks");
        if(m->p)
@@ -1456,6 +1457,7 @@ retry:
        mput(m);
        runtime_unlock(&runtime_sched);
        runtime_notesleep(&m->park);
+       m = g->m;
        runtime_noteclear(&m->park);
        if(m->helpgc) {
                runtime_gchelper();
@@ -1463,14 +1465,14 @@ retry:
                m->mcache = nil;
                goto retry;
        }
-       acquirep(m->nextp);
-       m->nextp = nil;
+       acquirep((P*)m->nextp);
+       m->nextp = 0;
 }
 
 static void
 mspinning(void)
 {
-       m->spinning = true;
+       g->m->spinning = true;
 }
 
 // Schedules some M to run the p (creates an M if necessary).
@@ -1505,7 +1507,7 @@ startm(P *p, bool spinning)
        if(mp->nextp)
                runtime_throw("startm: m has p");
        mp->spinning = spinning;
-       mp->nextp = p;
+       mp->nextp = (uintptr)p;
        runtime_notewakeup(&mp->park);
 }
 
@@ -1527,7 +1529,7 @@ handoffp(P *p)
        }
        runtime_lock(&runtime_sched);
        if(runtime_sched.gcwaiting) {
-               p->status = Pgcstop;
+               p->status = _Pgcstop;
                if(--runtime_sched.stopwait == 0)
                        runtime_notewakeup(&runtime_sched.stopnote);
                runtime_unlock(&runtime_sched);
@@ -1565,8 +1567,10 @@ wakep(void)
 static void
 stoplockedm(void)
 {
+       M *m;
        P *p;
 
+       m = g->m;
        if(m->lockedg == nil || m->lockedg->lockedm != m)
                runtime_throw("stoplockedm: inconsistent locking");
        if(m->p) {
@@ -1577,11 +1581,12 @@ stoplockedm(void)
        incidlelocked(1);
        // Wait until another thread schedules lockedg again.
        runtime_notesleep(&m->park);
+       m = g->m;
        runtime_noteclear(&m->park);
-       if(m->lockedg->status != Grunnable)
+       if(m->lockedg->atomicstatus != _Grunnable)
                runtime_throw("stoplockedm: not runnable");
-       acquirep(m->nextp);
-       m->nextp = nil;
+       acquirep((P*)m->nextp);
+       m->nextp = 0;
 }
 
 // Schedules the locked m to run the locked gp.
@@ -1592,14 +1597,14 @@ startlockedm(G *gp)
        P *p;
 
        mp = gp->lockedm;
-       if(mp == m)
+       if(mp == g->m)
                runtime_throw("startlockedm: locked to me");
        if(mp->nextp)
                runtime_throw("startlockedm: m has p");
        // directly handoff current P to the locked m
        incidlelocked(-1);
        p = releasep();
-       mp->nextp = p;
+       mp->nextp = (uintptr)p;
        runtime_notewakeup(&mp->park);
        stopm();
 }
@@ -1613,13 +1618,13 @@ gcstopm(void)
 
        if(!runtime_sched.gcwaiting)
                runtime_throw("gcstopm: not waiting for gc");
-       if(m->spinning) {
-               m->spinning = false;
+       if(g->m->spinning) {
+               g->m->spinning = false;
                runtime_xadd(&runtime_sched.nmspinning, -1);
        }
        p = releasep();
        runtime_lock(&runtime_sched);
-       p->status = Pgcstop;
+       p->status = _Pgcstop;
        if(--runtime_sched.stopwait == 0)
                runtime_notewakeup(&runtime_sched.stopnote);
        runtime_unlock(&runtime_sched);
@@ -1633,19 +1638,19 @@ execute(G *gp)
 {
        int32 hz;
 
-       if(gp->status != Grunnable) {
-               runtime_printf("execute: bad g status %d\n", gp->status);
+       if(gp->atomicstatus != _Grunnable) {
+               runtime_printf("execute: bad g status %d\n", gp->atomicstatus);
                runtime_throw("execute: bad g status");
        }
-       gp->status = Grunning;
+       gp->atomicstatus = _Grunning;
        gp->waitsince = 0;
-       m->p->schedtick++;
-       m->curg = gp;
-       gp->m = m;
+       ((P*)g->m->p)->schedtick++;
+       g->m->curg = gp;
+       gp->m = g->m;
 
        // Check whether the profiler needs to be turned on or off.
        hz = runtime_sched.profilehz;
-       if(m->profilehz != hz)
+       if(g->m->profilehz != hz)
                runtime_resetcpuprofiler(hz);
 
        runtime_gogo(gp);
@@ -1668,13 +1673,13 @@ top:
        if(runtime_fingwait && runtime_fingwake && (gp = runtime_wakefing()) != nil)
                runtime_ready(gp);
        // local runq
-       gp = runqget(m->p);
+       gp = runqget((P*)g->m->p);
        if(gp)
                return gp;
        // global runq
        if(runtime_sched.runqsize) {
                runtime_lock(&runtime_sched);
-               gp = globrunqget(m->p, 0);
+               gp = globrunqget((P*)g->m->p, 0);
                runtime_unlock(&runtime_sched);
                if(gp)
                        return gp;
@@ -1682,17 +1687,17 @@ top:
        // poll network
        gp = runtime_netpoll(false);  // non-blocking
        if(gp) {
-               injectglist(gp->schedlink);
-               gp->status = Grunnable;
+               injectglist((G*)gp->schedlink);
+               gp->atomicstatus = _Grunnable;
                return gp;
        }
        // If number of spinning M's >= number of busy P's, block.
        // This is necessary to prevent excessive CPU consumption
        // when GOMAXPROCS>>1 but the program parallelism is low.
-       if(!m->spinning && 2 * runtime_atomicload(&runtime_sched.nmspinning) >= runtime_gomaxprocs - runtime_atomicload(&runtime_sched.npidle))  // TODO: fast atomic
+       if(!g->m->spinning && 2 * runtime_atomicload(&runtime_sched.nmspinning) >= runtime_gomaxprocs - runtime_atomicload(&runtime_sched.npidle))  // TODO: fast atomic
                goto stop;
-       if(!m->spinning) {
-               m->spinning = true;
+       if(!g->m->spinning) {
+               g->m->spinning = true;
                runtime_xadd(&runtime_sched.nmspinning, 1);
        }
        // random steal from other P's
@@ -1700,10 +1705,10 @@ top:
                if(runtime_sched.gcwaiting)
                        goto top;
                p = runtime_allp[runtime_fastrand1()%runtime_gomaxprocs];
-               if(p == m->p)
+               if(p == (P*)g->m->p)
                        gp = runqget(p);
                else
-                       gp = runqsteal(m->p, p);
+                       gp = runqsteal((P*)g->m->p, p);
                if(gp)
                        return gp;
        }
@@ -1715,15 +1720,15 @@ stop:
                goto top;
        }
        if(runtime_sched.runqsize) {
-               gp = globrunqget(m->p, 0);
+               gp = globrunqget((P*)g->m->p, 0);
                runtime_unlock(&runtime_sched);
                return gp;
        }
        p = releasep();
        pidleput(p);
        runtime_unlock(&runtime_sched);
-       if(m->spinning) {
-               m->spinning = false;
+       if(g->m->spinning) {
+               g->m->spinning = false;
                runtime_xadd(&runtime_sched.nmspinning, -1);
        }
        // check all runqueues once again
@@ -1742,9 +1747,9 @@ stop:
        }
        // poll network
        if(runtime_xchg64(&runtime_sched.lastpoll, 0) != 0) {
-               if(m->p)
+               if(g->m->p)
                        runtime_throw("findrunnable: netpoll with p");
-               if(m->spinning)
+               if(g->m->spinning)
                        runtime_throw("findrunnable: netpoll with spinning");
                gp = runtime_netpoll(true);  // block until new work is available
                runtime_atomicstore64(&runtime_sched.lastpoll, runtime_nanotime());
@@ -1754,8 +1759,8 @@ stop:
                        runtime_unlock(&runtime_sched);
                        if(p) {
                                acquirep(p);
-                               injectglist(gp->schedlink);
-                               gp->status = Grunnable;
+                               injectglist((G*)gp->schedlink);
+                               gp->atomicstatus = _Grunnable;
                                return gp;
                        }
                        injectglist(gp);
@@ -1770,8 +1775,8 @@ resetspinning(void)
 {
        int32 nmspinning;
 
-       if(m->spinning) {
-               m->spinning = false;
+       if(g->m->spinning) {
+               g->m->spinning = false;
                nmspinning = runtime_xadd(&runtime_sched.nmspinning, -1);
                if(nmspinning < 0)
                        runtime_throw("findrunnable: negative nmspinning");
@@ -1797,8 +1802,8 @@ injectglist(G *glist)
        runtime_lock(&runtime_sched);
        for(n = 0; glist; n++) {
                gp = glist;
-               glist = gp->schedlink;
-               gp->status = Grunnable;
+               glist = (G*)gp->schedlink;
+               gp->atomicstatus = _Grunnable;
                globrunqput(gp);
        }
        runtime_unlock(&runtime_sched);
@@ -1815,7 +1820,7 @@ schedule(void)
        G *gp;
        uint32 tick;
 
-       if(m->locks)
+       if(g->m->locks)
                runtime_throw("schedule: holding locks");
 
 top:
@@ -1828,19 +1833,19 @@ top:
        // Check the global runnable queue once in a while to ensure fairness.
        // Otherwise two goroutines can completely occupy the local runqueue
        // by constantly respawning each other.
-       tick = m->p->schedtick;
+       tick = ((P*)g->m->p)->schedtick;
        // This is a fancy way to say tick%61==0,
        // it uses 2 MUL instructions instead of a single DIV and so is faster on modern processors.
        if(tick - (((uint64)tick*0x4325c53fu)>>36)*61 == 0 && runtime_sched.runqsize > 0) {
                runtime_lock(&runtime_sched);
-               gp = globrunqget(m->p, 1);
+               gp = globrunqget((P*)g->m->p, 1);
                runtime_unlock(&runtime_sched);
                if(gp)
                        resetspinning();
        }
        if(gp == nil) {
-               gp = runqget(m->p);
-               if(gp && m->spinning)
+               gp = runqget((P*)g->m->p);
+               if(gp && g->m->spinning)
                        runtime_throw("schedule: spinning with local work");
        }
        if(gp == nil) {
@@ -1863,11 +1868,11 @@ top:
 void
 runtime_park(bool(*unlockf)(G*, void*), void *lock, const char *reason)
 {
-       if(g->status != Grunning)
+       if(g->atomicstatus != _Grunning)
                runtime_throw("bad g status");
-       m->waitlock = lock;
-       m->waitunlockf = unlockf;
-       g->waitreason = reason;
+       g->m->waitlock = lock;
+       g->m->waitunlockf = unlockf;
+       g->waitreason = runtime_gostringnocopy((const byte*)reason);
        runtime_mcall(park0);
 }
 
@@ -1891,17 +1896,19 @@ runtime_parkunlock(Lock *lock, const char *reason)
 static void
 park0(G *gp)
 {
+       M *m;
        bool ok;
 
-       gp->status = Gwaiting;
+       m = g->m;
+       gp->atomicstatus = _Gwaiting;
        gp->m = nil;
        m->curg = nil;
        if(m->waitunlockf) {
-               ok = m->waitunlockf(gp, m->waitlock);
+               ok = ((bool (*)(G*, void*))m->waitunlockf)(gp, m->waitlock);
                m->waitunlockf = nil;
                m->waitlock = nil;
                if(!ok) {
-                       gp->status = Grunnable;
+                       gp->atomicstatus = _Grunnable;
                        execute(gp);  // Schedule it back, never returns.
                }
        }
@@ -1916,7 +1923,7 @@ park0(G *gp)
 void
 runtime_gosched(void)
 {
-       if(g->status != Grunning)
+       if(g->atomicstatus != _Grunning)
                runtime_throw("bad g status");
        runtime_mcall(runtime_gosched0);
 }
@@ -1925,7 +1932,10 @@ runtime_gosched(void)
 void
 runtime_gosched0(G *gp)
 {
-       gp->status = Grunnable;
+       M *m;
+
+       m = g->m;
+       gp->atomicstatus = _Grunnable;
        gp->m = nil;
        m->curg = nil;
        runtime_lock(&runtime_sched);
@@ -1946,7 +1956,7 @@ void runtime_goexit(void) __attribute__ ((noinline));
 void
 runtime_goexit(void)
 {
-       if(g->status != Grunning)
+       if(g->atomicstatus != _Grunning)
                runtime_throw("bad g status");
        runtime_mcall(goexit0);
 }
@@ -1955,25 +1965,28 @@ runtime_goexit(void)
 static void
 goexit0(G *gp)
 {
-       gp->status = Gdead;
+       M *m;
+
+       m = g->m;
+       gp->atomicstatus = _Gdead;
        gp->entry = nil;
        gp->m = nil;
        gp->lockedm = nil;
        gp->paniconfault = 0;
-       gp->defer = nil; // should be true already but just in case.
-       gp->panic = nil; // non-nil for Goexit during panic. points at stack-allocated data.
+       gp->_defer = nil; // should be true already but just in case.
+       gp->_panic = nil; // non-nil for Goexit during panic. points at stack-allocated data.
        gp->writenbuf = 0;
        gp->writebuf = nil;
-       gp->waitreason = nil;
+       gp->waitreason = runtime_gostringnocopy(nil);
        gp->param = nil;
        m->curg = nil;
        m->lockedg = nil;
-       if(m->locked & ~LockExternal) {
+       if(m->locked & ~_LockExternal) {
                runtime_printf("invalid m->locked = %d\n", m->locked);
                runtime_throw("internal lockOSThread error");
        }       
        m->locked = 0;
-       gfput(m->p, gp);
+       gfput((P*)m->p, gp);
        schedule();
 }
 
@@ -1994,7 +2007,7 @@ runtime_entersyscall()
 {
        // Save the registers in the g structure so that any pointers
        // held in registers will be seen by the garbage collector.
-       getcontext(&g->gcregs);
+       getcontext((ucontext_t*)&g->gcregs[0]);
 
        // Do the work in a separate function, so that this function
        // doesn't save any registers on its own stack.  If this
@@ -2011,24 +2024,24 @@ runtime_entersyscall()
 static void
 doentersyscall()
 {
-       // Disable preemption because during this function g is in Gsyscall status,
+       // Disable preemption because during this function g is in _Gsyscall status,
        // but can have inconsistent g->sched, do not let GC observe it.
-       m->locks++;
+       g->m->locks++;
 
        // Leave SP around for GC and traceback.
 #ifdef USING_SPLIT_STACK
-       g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size,
-                                      &g->gcnext_segment, &g->gcnext_sp,
-                                      &g->gcinitial_sp);
+       g->gcstack = __splitstack_find(nil, nil, &g->gcstacksize,
+                                      &g->gcnextsegment, &g->gcnextsp,
+                                      &g->gcinitialsp);
 #else
        {
                void *v;
 
-               g->gcnext_sp = (byte *) &v;
+               g->gcnextsp = (byte *) &v;
        }
 #endif
 
-       g->status = Gsyscall;
+       g->atomicstatus = _Gsyscall;
 
        if(runtime_atomicload(&runtime_sched.sysmonwait)) {  // TODO: fast atomic
                runtime_lock(&runtime_sched);
@@ -2039,19 +2052,19 @@ doentersyscall()
                runtime_unlock(&runtime_sched);
        }
 
-       m->mcache = nil;
-       m->p->m = nil;
-       runtime_atomicstore(&m->p->status, Psyscall);
+       g->m->mcache = nil;
+       ((P*)(g->m->p))->m = 0;
+       runtime_atomicstore(&((P*)g->m->p)->status, _Psyscall);
        if(runtime_atomicload(&runtime_sched.gcwaiting)) {
                runtime_lock(&runtime_sched);
-               if (runtime_sched.stopwait > 0 && runtime_cas(&m->p->status, Psyscall, Pgcstop)) {
+               if (runtime_sched.stopwait > 0 && runtime_cas(&((P*)g->m->p)->status, _Psyscall, _Pgcstop)) {
                        if(--runtime_sched.stopwait == 0)
                                runtime_notewakeup(&runtime_sched.stopnote);
                }
                runtime_unlock(&runtime_sched);
        }
 
-       m->locks--;
+       g->m->locks--;
 }
 
 // The same as runtime_entersyscall(), but with a hint that the syscall is blocking.
@@ -2060,29 +2073,29 @@ runtime_entersyscallblock(void)
 {
        P *p;
 
-       m->locks++;  // see comment in entersyscall
+       g->m->locks++;  // see comment in entersyscall
 
        // Leave SP around for GC and traceback.
 #ifdef USING_SPLIT_STACK
-       g->gcstack = __splitstack_find(nil, nil, &g->gcstack_size,
-                                      &g->gcnext_segment, &g->gcnext_sp,
-                                      &g->gcinitial_sp);
+       g->gcstack = __splitstack_find(nil, nil, &g->gcstacksize,
+                                      &g->gcnextsegment, &g->gcnextsp,
+                                      &g->gcinitialsp);
 #else
-       g->gcnext_sp = (byte *) &p;
+       g->gcnextsp = (byte *) &p;
 #endif
 
        // Save the registers in the g structure so that any pointers
        // held in registers will be seen by the garbage collector.
-       getcontext(&g->gcregs);
+       getcontext((ucontext_t*)&g->gcregs[0]);
 
-       g->status = Gsyscall;
+       g->atomicstatus = _Gsyscall;
 
        p = releasep();
        handoffp(p);
        if(g->isbackground)  // do not consider blocked scavenger for deadlock detection
                incidlelocked(1);
 
-       m->locks--;
+       g->m->locks--;
 }
 
 // The goroutine g exited its system call.
@@ -2094,29 +2107,29 @@ runtime_exitsyscall(void)
 {
        G *gp;
 
-       m->locks++;  // see comment in entersyscall
-
        gp = g;
+       gp->m->locks++;  // see comment in entersyscall
+
        if(gp->isbackground)  // do not consider blocked scavenger for deadlock detection
                incidlelocked(-1);
 
-       g->waitsince = 0;
+       gp->waitsince = 0;
        if(exitsyscallfast()) {
                // There's a cpu for us, so we can run.
-               m->p->syscalltick++;
-               gp->status = Grunning;
+               ((P*)gp->m->p)->syscalltick++;
+               gp->atomicstatus = _Grunning;
                // Garbage collector isn't running (since we are),
                // so okay to clear gcstack and gcsp.
 #ifdef USING_SPLIT_STACK
                gp->gcstack = nil;
 #endif
-               gp->gcnext_sp = nil;
-               runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
-               m->locks--;
+               gp->gcnextsp = nil;
+               runtime_memclr(&gp->gcregs[0], sizeof gp->gcregs);
+               gp->m->locks--;
                return;
        }
 
-       m->locks--;
+       gp->m->locks--;
 
        // Call the scheduler.
        runtime_mcall(exitsyscall0);
@@ -2130,34 +2143,37 @@ runtime_exitsyscall(void)
 #ifdef USING_SPLIT_STACK
        gp->gcstack = nil;
 #endif
-       gp->gcnext_sp = nil;
-       runtime_memclr(&gp->gcregs, sizeof gp->gcregs);
+       gp->gcnextsp = nil;
+       runtime_memclr(&gp->gcregs[0], sizeof gp->gcregs);
 
-       // Don't refer to m again, we might be running on a different
-       // thread after returning from runtime_mcall.
-       runtime_m()->p->syscalltick++;
+       // Note that this gp->m might be different than the earlier
+       // gp->m after returning from runtime_mcall.
+       ((P*)gp->m->p)->syscalltick++;
 }
 
 static bool
 exitsyscallfast(void)
 {
+       G *gp;
        P *p;
 
+       gp = g;
+
        // Freezetheworld sets stopwait but does not retake P's.
        if(runtime_sched.stopwait) {
-               m->p = nil;
+               gp->m->p = 0;
                return false;
        }
 
        // Try to re-acquire the last P.
-       if(m->p && m->p->status == Psyscall && runtime_cas(&m->p->status, Psyscall, Prunning)) {
+       if(gp->m->p && ((P*)gp->m->p)->status == _Psyscall && runtime_cas(&((P*)gp->m->p)->status, _Psyscall, _Prunning)) {
                // There's a cpu for us, so we can run.
-               m->mcache = m->p->mcache;
-               m->p->m = m;
+               gp->m->mcache = ((P*)gp->m->p)->mcache;
+               ((P*)gp->m->p)->m = (uintptr)gp->m;
                return true;
        }
        // Try to get any other idle P.
-       m->p = nil;
+       gp->m->p = 0;
        if(runtime_sched.pidle) {
                runtime_lock(&runtime_sched);
                p = pidleget();
@@ -2179,9 +2195,11 @@ exitsyscallfast(void)
 static void
 exitsyscall0(G *gp)
 {
+       M *m;
        P *p;
 
-       gp->status = Grunnable;
+       m = g->m;
+       gp->atomicstatus = _Grunnable;
        gp->m = nil;
        m->curg = nil;
        runtime_lock(&runtime_sched);
@@ -2235,7 +2253,7 @@ syscall_runtime_AfterFork(void)
 
 // Allocate a new g, with a stack big enough for stacksize bytes.
 G*
-runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
+runtime_malg(int32 stacksize, byte** ret_stack, uintptr* ret_stacksize)
 {
        G *newg;
 
@@ -2243,11 +2261,13 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
        if(stacksize >= 0) {
 #if USING_SPLIT_STACK
                int dont_block_signals = 0;
+               size_t ss_stacksize;
 
                *ret_stack = __splitstack_makecontext(stacksize,
-                                                     &newg->stack_context[0],
-                                                     ret_stacksize);
-               __splitstack_block_signals_context(&newg->stack_context[0],
+                                                     &newg->stackcontext[0],
+                                                     &ss_stacksize);
+               *ret_stacksize = (uintptr)ss_stacksize;
+               __splitstack_block_signals_context(&newg->stackcontext[0],
                                                   &dont_block_signals, nil);
 #else
                 // In 64-bit mode, the maximum Go allocation space is
@@ -2265,9 +2285,9 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
                        *ret_stack = runtime_mallocgc(stacksize, 0, FlagNoProfiling|FlagNoGC);
                        runtime_xadd(&runtime_stacks_sys, stacksize);
                }
-               *ret_stacksize = stacksize;
-               newg->gcinitial_sp = *ret_stack;
-               newg->gcstack_size = (size_t)stacksize;
+               *ret_stacksize = (uintptr)stacksize;
+               newg->gcinitialsp = *ret_stack;
+               newg->gcstacksize = (uintptr)stacksize;
 #endif
        }
        return newg;
@@ -2310,36 +2330,39 @@ __go_go(void (*fn)(void*), void* arg)
 
 //runtime_printf("newproc1 %p %p narg=%d nret=%d\n", fn->fn, argp, narg, nret);
        if(fn == nil) {
-               m->throwing = -1;  // do not dump full stacks
+               g->m->throwing = -1;  // do not dump full stacks
                runtime_throw("go of nil func value");
        }
-       m->locks++;  // disable preemption because it can be holding p in a local var
+       g->m->locks++;  // disable preemption because it can be holding p in a local var
 
-       p = m->p;
+       p = (P*)g->m->p;
        if((newg = gfget(p)) != nil) {
 #ifdef USING_SPLIT_STACK
                int dont_block_signals = 0;
 
-               sp = __splitstack_resetcontext(&newg->stack_context[0],
+               sp = __splitstack_resetcontext(&newg->stackcontext[0],
                                               &spsize);
-               __splitstack_block_signals_context(&newg->stack_context[0],
+               __splitstack_block_signals_context(&newg->stackcontext[0],
                                                   &dont_block_signals, nil);
 #else
-               sp = newg->gcinitial_sp;
-               spsize = newg->gcstack_size;
+               sp = newg->gcinitialsp;
+               spsize = newg->gcstacksize;
                if(spsize == 0)
                        runtime_throw("bad spsize in __go_go");
-               newg->gcnext_sp = sp;
+               newg->gcnextsp = sp;
 #endif
        } else {
-               newg = runtime_malg(StackMin, &sp, &spsize);
+               uintptr malsize;
+
+               newg = runtime_malg(StackMin, &sp, &malsize);
+               spsize = (size_t)malsize;
                allgadd(newg);
        }
 
        newg->entry = (byte*)fn;
        newg->param = arg;
        newg->gopc = (uintptr)__builtin_return_address(0);
-       newg->status = Grunnable;
+       newg->atomicstatus = _Grunnable;
        if(p->goidcache == p->goidcacheend) {
                p->goidcache = runtime_xadd64(&runtime_sched.goidgen, GoidCacheBatch);
                p->goidcacheend = p->goidcache + GoidCacheBatch;
@@ -2353,19 +2376,19 @@ __go_go(void (*fn)(void*), void* arg)
                size_t volatile vspsize = spsize;
                G * volatile vnewg = newg;
 
-               getcontext(&vnewg->context);
-               vnewg->context.uc_stack.ss_sp = vsp;
+               getcontext((ucontext_t*)&vnewg->context[0]);
+               ((ucontext_t*)&vnewg->context[0])->uc_stack.ss_sp = vsp;
 #ifdef MAKECONTEXT_STACK_TOP
-               vnewg->context.uc_stack.ss_sp += vspsize;
+               ((ucontext_t*)&vnewg->context[0])->uc_stack.ss_sp += vspsize;
 #endif
-               vnewg->context.uc_stack.ss_size = vspsize;
-               makecontext(&vnewg->context, kickoff, 0);
+               ((ucontext_t*)&vnewg->context[0])->uc_stack.ss_size = vspsize;
+               makecontext((ucontext_t*)&vnewg->context[0], kickoff, 0);
 
                runqput(p, vnewg);
 
                if(runtime_atomicload(&runtime_sched.npidle) != 0 && runtime_atomicload(&runtime_sched.nmspinning) == 0 && fn != runtime_main)  // TODO: fast atomic
                        wakep();
-               m->locks--;
+               g->m->locks--;
                return vnewg;
        }
 }
@@ -2400,7 +2423,7 @@ allgadd(G *gp)
 static void
 gfput(P *p, G *gp)
 {
-       gp->schedlink = p->gfree;
+       gp->schedlink = (uintptr)p->gfree;
        p->gfree = gp;
        p->gfreecnt++;
        if(p->gfreecnt >= 64) {
@@ -2408,8 +2431,8 @@ gfput(P *p, G *gp)
                while(p->gfreecnt >= 32) {
                        p->gfreecnt--;
                        gp = p->gfree;
-                       p->gfree = gp->schedlink;
-                       gp->schedlink = runtime_sched.gfree;
+                       p->gfree = (G*)gp->schedlink;
+                       gp->schedlink = (uintptr)runtime_sched.gfree;
                        runtime_sched.gfree = gp;
                }
                runtime_unlock(&runtime_sched.gflock);
@@ -2430,15 +2453,15 @@ retry:
                while(p->gfreecnt < 32 && runtime_sched.gfree) {
                        p->gfreecnt++;
                        gp = runtime_sched.gfree;
-                       runtime_sched.gfree = gp->schedlink;
-                       gp->schedlink = p->gfree;
+                       runtime_sched.gfree = (G*)gp->schedlink;
+                       gp->schedlink = (uintptr)p->gfree;
                        p->gfree = gp;
                }
                runtime_unlock(&runtime_sched.gflock);
                goto retry;
        }
        if(gp) {
-               p->gfree = gp->schedlink;
+               p->gfree = (G*)gp->schedlink;
                p->gfreecnt--;
        }
        return gp;
@@ -2454,8 +2477,8 @@ gfpurge(P *p)
        while(p->gfreecnt) {
                p->gfreecnt--;
                gp = p->gfree;
-               p->gfree = gp->schedlink;
-               gp->schedlink = runtime_sched.gfree;
+               p->gfree = (G*)gp->schedlink;
+               gp->schedlink = (uintptr)runtime_sched.gfree;
                runtime_sched.gfree = gp;
        }
        runtime_unlock(&runtime_sched.gflock);
@@ -2482,8 +2505,8 @@ runtime_gomaxprocsfunc(int32 n)
 {
        int32 ret;
 
-       if(n > MaxGomaxprocs)
-               n = MaxGomaxprocs;
+       if(n > _MaxGomaxprocs)
+               n = _MaxGomaxprocs;
        runtime_lock(&runtime_sched);
        ret = runtime_gomaxprocs;
        if(n <= 0 || n == ret) {
@@ -2493,10 +2516,10 @@ runtime_gomaxprocsfunc(int32 n)
        runtime_unlock(&runtime_sched);
 
        runtime_semacquire(&runtime_worldsema, false);
-       m->gcing = 1;
+       g->m->gcing = 1;
        runtime_stoptheworld();
        newprocs = n;
-       m->gcing = 0;
+       g->m->gcing = 0;
        runtime_semrelease(&runtime_worldsema);
        runtime_starttheworld();
 
@@ -2509,22 +2532,22 @@ runtime_gomaxprocsfunc(int32 n)
 static void
 lockOSThread(void)
 {
-       m->lockedg = g;
-       g->lockedm = m;
+       g->m->lockedg = g;
+       g->lockedm = g->m;
 }
 
 void   runtime_LockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.LockOSThread");
 void
 runtime_LockOSThread(void)
 {
-       m->locked |= LockExternal;
+       g->m->locked |= _LockExternal;
        lockOSThread();
 }
 
 void
 runtime_lockOSThread(void)
 {
-       m->locked += LockInternal;
+       g->m->locked += _LockInternal;
        lockOSThread();
 }
 
@@ -2535,9 +2558,9 @@ runtime_lockOSThread(void)
 static void
 unlockOSThread(void)
 {
-       if(m->locked != 0)
+       if(g->m->locked != 0)
                return;
-       m->lockedg = nil;
+       g->m->lockedg = nil;
        g->lockedm = nil;
 }
 
@@ -2546,23 +2569,23 @@ void    runtime_UnlockOSThread(void) __asm__ (GOSYM_PREFIX "runtime.UnlockOSThread"
 void
 runtime_UnlockOSThread(void)
 {
-       m->locked &= ~LockExternal;
+       g->m->locked &= ~_LockExternal;
        unlockOSThread();
 }
 
 void
 runtime_unlockOSThread(void)
 {
-       if(m->locked < LockInternal)
+       if(g->m->locked < _LockInternal)
                runtime_throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
-       m->locked -= LockInternal;
+       g->m->locked -= _LockInternal;
        unlockOSThread();
 }
 
 bool
 runtime_lockedOSThread(void)
 {
-       return g->lockedm != nil && m->lockedg != nil;
+       return g->lockedm != nil && g->m->lockedg != nil;
 }
 
 int32
@@ -2580,8 +2603,8 @@ runtime_gcount(void)
        // Compromise solution is to introduce per-P counters of active goroutines.
        for(i = 0; i < runtime_allglen; i++) {
                gp = runtime_allg[i];
-               s = gp->status;
-               if(s == Grunnable || s == Grunning || s == Gsyscall || s == Gwaiting)
+               s = gp->atomicstatus;
+               if(s == _Grunnable || s == _Grunning || s == _Gsyscall || s == _Gwaiting)
                        n++;
        }
        runtime_unlock(&allglock);
@@ -2609,7 +2632,7 @@ static void GC(void) {}
 void
 runtime_sigprof()
 {
-       M *mp = m;
+       M *mp = g->m;
        int32 n, i;
        bool traceback;
 
@@ -2675,7 +2698,7 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
 
        // Disable preemption, otherwise we can be rescheduled to another thread
        // that has profiling enabled.
-       m->locks++;
+       g->m->locks++;
 
        // Stop profiler on this thread so that it is safe to lock prof.
        // if a profiling signal came in while we had prof locked,
@@ -2693,7 +2716,7 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
        if(hz != 0)
                runtime_resetcpuprofiler(hz);
 
-       m->locks--;
+       g->m->locks--;
 }
 
 // Change number of processors.  The world is stopped, sched is locked.
@@ -2706,7 +2729,7 @@ procresize(int32 new)
        P *p;
 
        old = runtime_gomaxprocs;
-       if(old < 0 || old > MaxGomaxprocs || new <= 0 || new >MaxGomaxprocs)
+       if(old < 0 || old > _MaxGomaxprocs || new <= 0 || new >_MaxGomaxprocs)
                runtime_throw("procresize: invalid arg");
        // initialize new P's
        for(i = 0; i < new; i++) {
@@ -2714,12 +2737,12 @@ procresize(int32 new)
                if(p == nil) {
                        p = (P*)runtime_mallocgc(sizeof(*p), 0, FlagNoInvokeGC);
                        p->id = i;
-                       p->status = Pgcstop;
+                       p->status = _Pgcstop;
                        runtime_atomicstorep(&runtime_allp[i], p);
                }
                if(p->mcache == nil) {
                        if(old==0 && i==0)
-                               p->mcache = m->mcache;  // bootstrap
+                               p->mcache = g->m->mcache;  // bootstrap
                        else
                                p->mcache = runtime_allocmcache();
                }
@@ -2739,9 +2762,9 @@ procresize(int32 new)
                        empty = false;
                        // pop from tail of local queue
                        p->runqtail--;
-                       gp = p->runq[p->runqtail%nelem(p->runq)];
+                       gp = (G*)p->runq[p->runqtail%nelem(p->runq)];
                        // push onto head of global queue
-                       gp->schedlink = runtime_sched.runqhead;
+                       gp->schedlink = (uintptr)runtime_sched.runqhead;
                        runtime_sched.runqhead = gp;
                        if(runtime_sched.runqtail == nil)
                                runtime_sched.runqtail = gp;
@@ -2753,7 +2776,7 @@ procresize(int32 new)
        // so if we have a spare G we want to put it into allp[1].
        for(i = 1; (uint32)i < (uint32)new * nelem(p->runq)/2 && runtime_sched.runqsize > 0; i++) {
                gp = runtime_sched.runqhead;
-               runtime_sched.runqhead = gp->schedlink;
+               runtime_sched.runqhead = (G*)gp->schedlink;
                if(runtime_sched.runqhead == nil)
                        runtime_sched.runqtail = nil;
                runtime_sched.runqsize--;
@@ -2766,21 +2789,21 @@ procresize(int32 new)
                runtime_freemcache(p->mcache);
                p->mcache = nil;
                gfpurge(p);
-               p->status = Pdead;
+               p->status = _Pdead;
                // can't free P itself because it can be referenced by an M in syscall
        }
 
-       if(m->p)
-               m->p->m = nil;
-       m->p = nil;
-       m->mcache = nil;
+       if(g->m->p)
+               ((P*)g->m->p)->m = 0;
+       g->m->p = 0;
+       g->m->mcache = nil;
        p = runtime_allp[0];
-       p->m = nil;
-       p->status = Pidle;
+       p->m = 0;
+       p->status = _Pidle;
        acquirep(p);
        for(i = new-1; i > 0; i--) {
                p = runtime_allp[i];
-               p->status = Pidle;
+               p->status = _Pidle;
                pidleput(p);
        }
        runtime_atomicstore((uint32*)&runtime_gomaxprocs, new);
@@ -2790,36 +2813,41 @@ procresize(int32 new)
 static void
 acquirep(P *p)
 {
+       M *m;
+
+       m = g->m;
        if(m->p || m->mcache)
                runtime_throw("acquirep: already in go");
-       if(p->m || p->status != Pidle) {
-               runtime_printf("acquirep: p->m=%p(%d) p->status=%d\n", p->m, p->m ? p->m->id : 0, p->status);
+       if(p->m || p->status != _Pidle) {
+               runtime_printf("acquirep: p->m=%p(%d) p->status=%d\n", p->m, p->m ? ((M*)p->m)->id : 0, p->status);
                runtime_throw("acquirep: invalid p state");
        }
        m->mcache = p->mcache;
-       m->p = p;
-       p->m = m;
-       p->status = Prunning;
+       m->p = (uintptr)p;
+       p->m = (uintptr)m;
+       p->status = _Prunning;
 }
 
 // Disassociate p and the current m.
 static P*
 releasep(void)
 {
+       M *m;
        P *p;
 
-       if(m->p == nil || m->mcache == nil)
+       m = g->m;
+       if(m->p == 0 || m->mcache == nil)
                runtime_throw("releasep: invalid arg");
-       p = m->p;
-       if(p->m != m || p->mcache != m->mcache || p->status != Prunning) {
+       p = (P*)m->p;
+       if((M*)p->m != m || p->mcache != m->mcache || p->status != _Prunning) {
                runtime_printf("releasep: m=%p m->p=%p p->m=%p m->mcache=%p p->mcache=%p p->status=%d\n",
                        m, m->p, p->m, m->mcache, p->mcache, p->status);
                runtime_throw("releasep: invalid p state");
        }
-       m->p = nil;
+       m->p = 0;
        m->mcache = nil;
-       p->m = nil;
-       p->status = Pidle;
+       p->m = 0;
+       p->status = _Pidle;
        return p;
 }
 
@@ -2870,10 +2898,10 @@ checkdead(void)
                gp = runtime_allg[i];
                if(gp->isbackground)
                        continue;
-               s = gp->status;
-               if(s == Gwaiting)
+               s = gp->atomicstatus;
+               if(s == _Gwaiting)
                        grunning++;
-               else if(s == Grunnable || s == Grunning || s == Gsyscall) {
+               else if(s == _Grunnable || s == _Grunning || s == _Gsyscall) {
                        runtime_unlock(&allglock);
                        runtime_printf("runtime: checkdead: find g %D in status %d\n", gp->goid, s);
                        runtime_throw("checkdead: runnable g");
@@ -2882,7 +2910,7 @@ checkdead(void)
        runtime_unlock(&allglock);
        if(grunning == 0)  // possible if main goroutine calls runtime_Goexit()
                runtime_throw("no goroutines (main called runtime.Goexit) - deadlock!");
-       m->throwing = -1;  // do not dump full stacks
+       g->m->throwing = -1;  // do not dump full stacks
        runtime_throw("all goroutines are asleep - deadlock!");
 }
 
@@ -2958,7 +2986,7 @@ struct Pdesc
        uint32  syscalltick;
        int64   syscallwhen;
 };
-static Pdesc pdesc[MaxGomaxprocs];
+static Pdesc pdesc[_MaxGomaxprocs];
 
 static uint32
 retake(int64 now)
@@ -2975,7 +3003,7 @@ retake(int64 now)
                        continue;
                pd = &pdesc[i];
                s = p->status;
-               if(s == Psyscall) {
+               if(s == _Psyscall) {
                        // Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
                        t = p->syscalltick;
                        if(pd->syscalltick != t) {
@@ -2995,12 +3023,12 @@ retake(int64 now)
                        // Otherwise the M from which we retake can exit the syscall,
                        // increment nmidle and report deadlock.
                        incidlelocked(-1);
-                       if(runtime_cas(&p->status, s, Pidle)) {
+                       if(runtime_cas(&p->status, s, _Pidle)) {
                                n++;
                                handoffp(p);
                        }
                        incidlelocked(1);
-               } else if(s == Prunning) {
+               } else if(s == _Prunning) {
                        // Preempt G if it's running for more than 10ms.
                        t = p->schedtick;
                        if(pd->schedtick != t) {
@@ -3060,7 +3088,7 @@ runtime_schedtrace(bool detailed)
                p = runtime_allp[i];
                if(p == nil)
                        continue;
-               mp = p->m;
+               mp = (M*)p->m;
                h = runtime_atomicload(&p->runqhead);
                t = runtime_atomicload(&p->runqtail);
                if(detailed)
@@ -3084,7 +3112,7 @@ runtime_schedtrace(bool detailed)
                return;
        }
        for(mp = runtime_allm; mp; mp = mp->alllink) {
-               p = mp->p;
+               p = (P*)mp->p;
                gp = mp->curg;
                lockedg = mp->lockedg;
                id1 = -1;
@@ -3100,15 +3128,15 @@ runtime_schedtrace(bool detailed)
                        " locks=%d dying=%d helpgc=%d spinning=%d blocked=%d lockedg=%D\n",
                        mp->id, id1, id2,
                        mp->mallocing, mp->throwing, mp->gcing, mp->locks, mp->dying, mp->helpgc,
-                       mp->spinning, m->blocked, id3);
+                       mp->spinning, mp->blocked, id3);
        }
        runtime_lock(&allglock);
        for(gi = 0; gi < runtime_allglen; gi++) {
                gp = runtime_allg[gi];
                mp = gp->m;
                lockedm = gp->lockedm;
-               runtime_printf("  G%D: status=%d(%s) m=%d lockedm=%d\n",
-                       gp->goid, gp->status, gp->waitreason, mp ? mp->id : -1,
+               runtime_printf("  G%D: status=%d(%S) m=%d lockedm=%d\n",
+                       gp->goid, gp->atomicstatus, gp->waitreason, mp ? mp->id : -1,
                        lockedm ? lockedm->id : -1);
        }
        runtime_unlock(&allglock);
@@ -3120,7 +3148,7 @@ runtime_schedtrace(bool detailed)
 static void
 mput(M *mp)
 {
-       mp->schedlink = runtime_sched.midle;
+       mp->schedlink = (uintptr)runtime_sched.midle;
        runtime_sched.midle = mp;
        runtime_sched.nmidle++;
        checkdead();
@@ -3134,7 +3162,7 @@ mget(void)
        M *mp;
 
        if((mp = runtime_sched.midle) != nil){
-               runtime_sched.midle = mp->schedlink;
+               runtime_sched.midle = (M*)mp->schedlink;
                runtime_sched.nmidle--;
        }
        return mp;
@@ -3145,9 +3173,9 @@ mget(void)
 static void
 globrunqput(G *gp)
 {
-       gp->schedlink = nil;
+       gp->schedlink = 0;
        if(runtime_sched.runqtail)
-               runtime_sched.runqtail->schedlink = gp;
+               runtime_sched.runqtail->schedlink = (uintptr)gp;
        else
                runtime_sched.runqhead = gp;
        runtime_sched.runqtail = gp;
@@ -3159,9 +3187,9 @@ globrunqput(G *gp)
 static void
 globrunqputbatch(G *ghead, G *gtail, int32 n)
 {
-       gtail->schedlink = nil;
+       gtail->schedlink = 0;
        if(runtime_sched.runqtail)
-               runtime_sched.runqtail->schedlink = ghead;
+               runtime_sched.runqtail->schedlink = (uintptr)ghead;
        else
                runtime_sched.runqhead = ghead;
        runtime_sched.runqtail = gtail;
@@ -3189,11 +3217,11 @@ globrunqget(P *p, int32 max)
        if(runtime_sched.runqsize == 0)
                runtime_sched.runqtail = nil;
        gp = runtime_sched.runqhead;
-       runtime_sched.runqhead = gp->schedlink;
+       runtime_sched.runqhead = (G*)gp->schedlink;
        n--;
        while(n--) {
                gp1 = runtime_sched.runqhead;
-               runtime_sched.runqhead = gp1->schedlink;
+               runtime_sched.runqhead = (G*)gp1->schedlink;
                runqput(p, gp1);
        }
        return gp;
@@ -3204,7 +3232,7 @@ globrunqget(P *p, int32 max)
 static void
 pidleput(P *p)
 {
-       p->link = runtime_sched.pidle;
+       p->link = (uintptr)runtime_sched.pidle;
        runtime_sched.pidle = p;
        runtime_xadd(&runtime_sched.npidle, 1);  // TODO: fast atomic
 }
@@ -3218,7 +3246,7 @@ pidleget(void)
 
        p = runtime_sched.pidle;
        if(p) {
-               runtime_sched.pidle = p->link;
+               runtime_sched.pidle = (P*)p->link;
                runtime_xadd(&runtime_sched.npidle, -1);  // TODO: fast atomic
        }
        return p;
@@ -3236,7 +3264,7 @@ retry:
        h = runtime_atomicload(&p->runqhead);  // load-acquire, synchronize with consumers
        t = p->runqtail;
        if(t - h < nelem(p->runq)) {
-               p->runq[t%nelem(p->runq)] = gp;
+               p->runq[t%nelem(p->runq)] = (uintptr)gp;
                runtime_atomicstore(&p->runqtail, t+1);  // store-release, makes the item available for consumption
                return;
        }
@@ -3260,13 +3288,13 @@ runqputslow(P *p, G *gp, uint32 h, uint32 t)
        if(n != nelem(p->runq)/2)
                runtime_throw("runqputslow: queue is not full");
        for(i=0; i<n; i++)
-               batch[i] = p->runq[(h+i)%nelem(p->runq)];
+               batch[i] = (G*)p->runq[(h+i)%nelem(p->runq)];
        if(!runtime_cas(&p->runqhead, h, h+n))  // cas-release, commits consume
                return false;
        batch[n] = gp;
        // Link the goroutines.
        for(i=0; i<n; i++)
-               batch[i]->schedlink = batch[i+1];
+               batch[i]->schedlink = (uintptr)batch[i+1];
        // Now put the batch on global queue.
        runtime_lock(&runtime_sched);
        globrunqputbatch(batch[0], batch[n], n+1);
@@ -3287,7 +3315,7 @@ runqget(P *p)
                t = p->runqtail;
                if(t == h)
                        return nil;
-               gp = p->runq[h%nelem(p->runq)];
+               gp = (G*)p->runq[h%nelem(p->runq)];
                if(runtime_cas(&p->runqhead, h, h+1))  // cas-release, commits consume
                        return gp;
        }
@@ -3311,7 +3339,7 @@ runqgrab(P *p, G **batch)
                if(n > nelem(p->runq)/2)  // read inconsistent h and t
                        continue;
                for(i=0; i<n; i++)
-                       batch[i] = p->runq[(h+i)%nelem(p->runq)];
+                       batch[i] = (G*)p->runq[(h+i)%nelem(p->runq)];
                if(runtime_cas(&p->runqhead, h, h+n))  // cas-release, commits consume
                        break;
        }
@@ -3340,7 +3368,7 @@ runqsteal(P *p, P *p2)
        if(t - h + n >= nelem(p->runq))
                runtime_throw("runqsteal: runq overflow");
        for(i=0; i<n; i++, t++)
-               p->runq[t%nelem(p->runq)] = batch[i];
+               p->runq[t%nelem(p->runq)] = (uintptr)batch[i];
        runtime_atomicstore(&p->runqtail, t);  // store-release, makes the item available for consumption
        return gp;
 }
@@ -3480,7 +3508,7 @@ sync_runtime_canSpin(intgo i)
        if (i >= ACTIVE_SPIN || runtime_ncpu <= 1 || runtime_gomaxprocs <= (int32)(runtime_sched.npidle+runtime_sched.nmspinning)+1) {
                return false;
        }
-       p = m->p;
+       p = (P*)g->m->p;
        return p != nil && p->runqhead == p->runqtail;
 }
 
index 4140d33d04157f2a049d576483cc4ebd8eda6cee..c7d33bcef4c65a170c343ebfc2bb13b52327c37b 100644 (file)
@@ -272,7 +272,8 @@ runtime_tickspersecond(void)
 void
 runtime_mpreinit(M *mp)
 {
-       mp->gsignal = runtime_malg(32*1024, &mp->gsignalstack, &mp->gsignalstacksize);  // OS X wants >=8K, Linux >=2K
+       mp->gsignal = runtime_malg(32*1024, (byte**)&mp->gsignalstack, &mp->gsignalstacksize);  // OS X wants >=8K, Linux >=2K
+       mp->gsignal->m = mp;
 }
 
 // Called to initialize a new m (including the bootstrap m).
index ba5eab78c7856ab92b86cd0e93965136a08fcf60..617766b8a990f749147172f729cbfca743852332 100644 (file)
@@ -56,24 +56,24 @@ typedef uintptr             uintreg;
 typedef        uint8                   bool;
 typedef        uint8                   byte;
 typedef        struct  Func            Func;
-typedef        struct  G               G;
-typedef        struct  Lock            Lock;
-typedef        struct  M               M;
-typedef        struct  P               P;
-typedef        struct  Note            Note;
+typedef        struct  g               G;
+typedef        struct  mutex           Lock;
+typedef        struct  m               M;
+typedef        struct  p               P;
+typedef        struct  note            Note;
 typedef        struct  String          String;
 typedef        struct  FuncVal         FuncVal;
 typedef        struct  SigTab          SigTab;
-typedef        struct  MCache          MCache;
+typedef        struct  mcache          MCache;
 typedef struct FixAlloc        FixAlloc;
 typedef        struct  Hchan           Hchan;
 typedef        struct  Timers          Timers;
 typedef        struct  Timer           Timer;
-typedef        struct  GCStats         GCStats;
+typedef        struct  gcstats         GCStats;
 typedef        struct  LFNode          LFNode;
 typedef        struct  ParFor          ParFor;
 typedef        struct  ParForThread    ParForThread;
-typedef        struct  CgoMal          CgoMal;
+typedef        struct  cgoMal          CgoMal;
 typedef        struct  PollDesc        PollDesc;
 typedef        struct  DebugVars       DebugVars;
 
@@ -81,8 +81,8 @@ typedef       struct  __go_open_array         Slice;
 typedef struct __go_interface          Iface;
 typedef        struct  __go_empty_interface    Eface;
 typedef        struct  __go_type_descriptor    Type;
-typedef        struct  __go_defer_stack        Defer;
-typedef        struct  __go_panic_stack        Panic;
+typedef        struct  _defer                  Defer;
+typedef        struct  _panic                  Panic;
 
 typedef struct __go_ptr_type           PtrType;
 typedef struct __go_func_type          FuncType;
@@ -90,9 +90,26 @@ typedef struct       __go_interface_type     InterfaceType;
 typedef struct __go_map_type           MapType;
 typedef struct __go_channel_type       ChanType;
 
-typedef struct  Traceback      Traceback;
+typedef struct  traceback      Traceback;
 
-typedef struct Location        Location;
+typedef struct location        Location;
+
+struct String
+{
+       const byte*     str;
+       intgo           len;
+};
+
+struct FuncVal
+{
+       void    (*fn)(void);
+       // variable-size, fn-specific data here
+};
+
+#include "array.h"
+#include "interface.h"
+
+#include "runtime.inc"
 
 /*
  * Per-CPU declaration.
@@ -103,33 +120,6 @@ extern G*  runtime_g(void);
 extern M       runtime_m0;
 extern G       runtime_g0;
 
-/*
- * defined constants
- */
-enum
-{
-       // G status
-       //
-       // If you add to this list, add to the list
-       // of "okay during garbage collection" status
-       // in mgc0.c too.
-       Gidle,
-       Grunnable,
-       Grunning,
-       Gsyscall,
-       Gwaiting,
-       Gmoribund_unused,  // currently unused, but hardcoded in gdb scripts
-       Gdead,
-};
-enum
-{
-       // P status
-       Pidle,
-       Prunning,
-       Psyscall,
-       Pgcstop,
-       Pdead,
-};
 enum
 {
        true    = 1,
@@ -146,184 +136,6 @@ enum
        // Global <-> per-M stack segment cache transfer batch size.
        StackCacheBatch = 16,
 };
-/*
- * structures
- */
-struct Lock
-{
-       // Futex-based impl treats it as uint32 key,
-       // while sema-based impl as M* waitm.
-       // Used to be a union, but unions break precise GC.
-       uintptr key;
-};
-struct Note
-{
-       // Futex-based impl treats it as uint32 key,
-       // while sema-based impl as M* waitm.
-       // Used to be a union, but unions break precise GC.
-       uintptr key;
-};
-struct String
-{
-       const byte*     str;
-       intgo           len;
-};
-struct FuncVal
-{
-       void    (*fn)(void);
-       // variable-size, fn-specific data here
-};
-struct GCStats
-{
-       // the struct must consist of only uint64's,
-       // because it is casted to uint64[].
-       uint64  nhandoff;
-       uint64  nhandoffcnt;
-       uint64  nprocyield;
-       uint64  nosyield;
-       uint64  nsleep;
-};
-
-// A location in the program, used for backtraces.
-struct Location
-{
-       uintptr pc;
-       String  filename;
-       String  function;
-       intgo   lineno;
-};
-
-struct G
-{
-       Defer*  defer;
-       Panic*  panic;
-       void*   exception;      // current exception being thrown
-       bool    is_foreign;     // whether current exception from other language
-       void    *gcstack;       // if status==Gsyscall, gcstack = stackbase to use during gc
-       size_t  gcstack_size;
-       void*   gcnext_segment;
-       void*   gcnext_sp;
-       void*   gcinitial_sp;
-       ucontext_t gcregs;
-       byte*   entry;          // initial function
-       void*   param;          // passed parameter on wakeup
-       bool    fromgogo;       // reached from gogo
-       int16   status;
-       uint32  selgen;         // valid sudog pointer
-       int64   goid;
-       int64   waitsince;      // approx time when the G become blocked
-       const char*     waitreason;     // if status==Gwaiting
-       G*      schedlink;
-       bool    ispanic;
-       bool    issystem;       // do not output in stack dump
-       bool    isbackground;   // ignore in deadlock detector
-       bool    paniconfault;   // panic (instead of crash) on unexpected fault address
-       M*      m;              // for debuggers, but offset not hard-coded
-       M*      lockedm;
-       int32   sig;
-       int32   writenbuf;
-       byte*   writebuf;
-       uintptr sigcode0;
-       uintptr sigcode1;
-       // uintptr      sigpc;
-       uintptr gopc;   // pc of go statement that created this goroutine
-
-       int32   ncgo;
-       CgoMal* cgomal;
-
-       Traceback* traceback;
-
-       ucontext_t      context;
-       void*           stack_context[10];
-};
-
-struct M
-{
-       G*      g0;             // goroutine with scheduling stack
-       G*      gsignal;        // signal-handling G
-       byte*   gsignalstack;
-       size_t  gsignalstacksize;
-       void    (*mstartfn)(void);
-       G*      curg;           // current running goroutine
-       G*      caughtsig;      // goroutine running during fatal signal
-       P*      p;              // attached P for executing Go code (nil if not executing Go code)
-       P*      nextp;
-       int32   id;
-       int32   mallocing;
-       int32   throwing;
-       int32   gcing;
-       int32   locks;
-       int32   softfloat;
-       int32   dying;
-       int32   profilehz;
-       int32   helpgc;
-       bool    spinning;       // M is out of work and is actively looking for work
-       bool    blocked;        // M is blocked on a Note
-       uint32  fastrand;
-       uint64  ncgocall;       // number of cgo calls in total
-       int32   ncgo;           // number of cgo calls currently in progress
-       CgoMal* cgomal;
-       Note    park;
-       M*      alllink;        // on allm
-       M*      schedlink;
-       MCache  *mcache;
-       G*      lockedg;
-       Location createstack[32];       // Stack that created this thread.
-       uint32  locked; // tracking for LockOSThread
-       M*      nextwaitm;      // next M waiting for lock
-       uintptr waitsema;       // semaphore for parking on locks
-       uint32  waitsemacount;
-       uint32  waitsemalock;
-       GCStats gcstats;
-       bool    needextram;
-       bool    dropextram;     // for gccgo: drop after call is done.
-       uint8   traceback;
-       bool    (*waitunlockf)(G*, void*);
-       void*   waitlock;
-       uintptr end[];
-};
-
-struct P
-{
-       Lock;
-
-       int32   id;
-       uint32  status;         // one of Pidle/Prunning/...
-       P*      link;
-       uint32  schedtick;      // incremented on every scheduler call
-       uint32  syscalltick;    // incremented on every system call
-       M*      m;              // back-link to associated M (nil if idle)
-       MCache* mcache;
-       Defer*  deferpool;      // pool of available Defer structs (see panic.c)
-
-       // Cache of goroutine ids, amortizes accesses to runtime_sched.goidgen.
-       uint64  goidcache;
-       uint64  goidcacheend;
-
-       // Queue of runnable goroutines.
-       uint32  runqhead;
-       uint32  runqtail;
-       G*      runq[256];
-
-       // Available G's (status == Gdead)
-       G*      gfree;
-       int32   gfreecnt;
-
-       byte    pad[64];
-};
-
-// The m->locked word holds two pieces of state counting active calls to LockOSThread/lockOSThread.
-// The low bit (LockExternal) is a boolean reporting whether any LockOSThread call is active.
-// External locks are not recursive; a second lock is silently ignored.
-// The upper bits of m->lockedcount record the nesting depth of calls to lockOSThread
-// (counting up by LockInternal), popped by unlockOSThread (counting down by LockInternal).
-// Internal locks can be recursive. For instance, a lock for cgo can occur while the main
-// goroutine is holding the lock during the initialization phase.
-enum
-{
-       LockExternal = 1,
-       LockInternal = 2,
-};
 
 struct SigTab
 {
@@ -331,16 +143,6 @@ struct     SigTab
        int32   flags;
        void*   fwdsig;
 };
-enum
-{
-       SigNotify = 1<<0,       // let signal.Notify have signal, even if from kernel
-       SigKill = 1<<1,         // if signal.Notify doesn't take it, exit quietly
-       SigThrow = 1<<2,        // if signal.Notify doesn't take it, exit loudly
-       SigPanic = 1<<3,        // if the signal is from the kernel, panic
-       SigDefault = 1<<4,      // if the signal isn't explicitly requested, don't monitor it
-       SigHandling = 1<<5,     // our signal handler is registered
-       SigGoExit = 1<<6,       // cause all runtime procs to exit (only used on Plan 9).
-};
 
 // Layout of in-memory per-function information prepared by linker
 // See http://golang.org/s/go12symtab.
@@ -438,14 +240,6 @@ struct ParFor
        uint64 nsleep;
 };
 
-// Track memory allocated by code not written in Go during a cgo call,
-// so that the garbage collector can see them.
-struct CgoMal
-{
-       CgoMal  *next;
-       void    *alloc;
-};
-
 // Holds variables parsed from GODEBUG env var.
 struct DebugVars
 {
@@ -565,7 +359,7 @@ void        runtime_ready(G*);
 String runtime_getenv(const char*);
 int32  runtime_atoi(const byte*, intgo);
 void*  runtime_mstart(void*);
-G*     runtime_malg(int32, byte**, size_t*);
+G*     runtime_malg(int32, byte**, uintptr*);
 void   runtime_mpreinit(M*);
 void   runtime_minit(void);
 void   runtime_unminit(void);
@@ -604,7 +398,7 @@ int32       runtime_round2(int32 x); // round x up to a power of 2.
 #define runtime_atomicloadp(p) __atomic_load_n (p, __ATOMIC_SEQ_CST)
 #define runtime_atomicstorep(p, v) __atomic_store_n (p, v, __ATOMIC_SEQ_CST)
 
-void runtime_setmg(M*, G*);
+void runtime_setg(G*);
 void runtime_newextram(void);
 #define runtime_exit(s) exit(s)
 #define runtime_breakpoint() __builtin_trap()
index cd9d3017b51df52880539bca75660e4bafa89c84..26b5566017d00761ec902d3d05ee56d79d5a7b9d 100644 (file)
@@ -65,7 +65,7 @@ func sync.runtime_procPin() (p int) {
        mp = runtime_m();
        // Disable preemption.
        mp->locks++;
-       p = mp->p->id;
+       p = ((P*)mp->p)->id;
 }
 
 func sync.runtime_procUnpin() {
@@ -78,7 +78,7 @@ func sync_atomic.runtime_procPin() (p int) {
        mp = runtime_m();
        // Disable preemption.
        mp->locks++;
-       p = mp->p->id;
+       p = ((P*)mp->p)->id;
 }
 
 func sync_atomic.runtime_procUnpin() {
index 5bee0d2a70605ac0fe9488e30dc34f41b6d50440..2cca08cf47bed7fed9335b531d8a595f93f1683e 100644 (file)
@@ -26,7 +26,7 @@ runtime_initsig(bool preinit)
        // First call: basic setup.
        for(i = 0; runtime_sigtab[i].sig != -1; i++) {
                t = &runtime_sigtab[i];
-               if((t->flags == 0) || (t->flags & SigDefault))
+               if((t->flags == 0) || (t->flags & _SigDefault))
                        continue;
 
                t->fwdsig = runtime_getsig(i);
@@ -42,10 +42,10 @@ runtime_initsig(bool preinit)
                        }
                }
 
-               if(runtime_isarchive && (t->flags&SigPanic) == 0)
+               if(runtime_isarchive && (t->flags&_SigPanic) == 0)
                        continue;
 
-               t->flags |= SigHandling;
+               t->flags |= _SigHandling;
                runtime_setsig(i, runtime_sighandler, true);
        }
 }
@@ -67,8 +67,8 @@ runtime_sigenable(uint32 sig)
        if(t == nil)
                return;
 
-       if((t->flags & SigNotify) && !(t->flags & SigHandling)) {
-               t->flags |= SigHandling;
+       if((t->flags & _SigNotify) && !(t->flags & _SigHandling)) {
+               t->flags |= _SigHandling;
                t->fwdsig = runtime_getsig(i);
                runtime_setsig(i, runtime_sighandler, true);
        }
@@ -92,7 +92,7 @@ runtime_sigdisable(uint32 sig)
                return;
 
        if((sig == SIGHUP || sig == SIGINT) && t->fwdsig == GO_SIG_IGN) {
-               t->flags &= ~SigHandling;
+               t->flags &= ~_SigHandling;
                runtime_setsig(i, t->fwdsig, true);
        }
 }
@@ -114,8 +114,8 @@ runtime_sigignore(uint32 sig)
        if(t == nil)
                return;
 
-       if((t->flags & SigNotify) != 0) {
-               t->flags &= ~SigHandling;
+       if((t->flags & _SigNotify) != 0) {
+               t->flags &= ~_SigHandling;
                runtime_setsig(i, GO_SIG_IGN, true);
        }
 }