diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-08-30 21:07:47 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-08-30 21:07:47 +0000 |
commit | 75791bab05ec4a45a5c6a4dccd7f824ea8f4487c (patch) | |
tree | 9c8130f09f3b1f343a58af6dd0f97f3a14f617c9 /libgo/runtime | |
parent | 7875b41f1d0137005d87cc5dd12b2a7df2f30c5e (diff) | |
download | gcc-75791bab05ec4a45a5c6a4dccd7f824ea8f4487c.zip gcc-75791bab05ec4a45a5c6a4dccd7f824ea8f4487c.tar.gz gcc-75791bab05ec4a45a5c6a4dccd7f824ea8f4487c.tar.bz2 |
runtime: use -fgo-c-header to build C header file
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
Diffstat (limited to 'libgo/runtime')
-rw-r--r-- | libgo/runtime/go-cgo.c | 24 | ||||
-rw-r--r-- | libgo/runtime/go-defer.c | 39 | ||||
-rw-r--r-- | libgo/runtime/go-defer.h | 47 | ||||
-rw-r--r-- | libgo/runtime/go-deferred-recover.c | 3 | ||||
-rw-r--r-- | libgo/runtime/go-panic.c | 41 | ||||
-rw-r--r-- | libgo/runtime/go-panic.h | 23 | ||||
-rw-r--r-- | libgo/runtime/go-recover.c | 61 | ||||
-rw-r--r-- | libgo/runtime/go-signal.c | 24 | ||||
-rw-r--r-- | libgo/runtime/go-unwind.c | 56 | ||||
-rw-r--r-- | libgo/runtime/heapdump.c | 45 | ||||
-rw-r--r-- | libgo/runtime/lock_sema.c | 4 | ||||
-rw-r--r-- | libgo/runtime/malloc.goc | 16 | ||||
-rw-r--r-- | libgo/runtime/malloc.h | 100 | ||||
-rw-r--r-- | libgo/runtime/mcache.c | 4 | ||||
-rw-r--r-- | libgo/runtime/mcentral.c | 2 | ||||
-rw-r--r-- | libgo/runtime/mgc0.c | 52 | ||||
-rw-r--r-- | libgo/runtime/mheap.c | 26 | ||||
-rw-r--r-- | libgo/runtime/mprof.goc | 2 | ||||
-rw-r--r-- | libgo/runtime/msize.c | 18 | ||||
-rw-r--r-- | libgo/runtime/netpoll.goc | 4 | ||||
-rw-r--r-- | libgo/runtime/panic.c | 23 | ||||
-rw-r--r-- | libgo/runtime/proc.c | 720 | ||||
-rw-r--r-- | libgo/runtime/runtime.c | 3 | ||||
-rw-r--r-- | libgo/runtime/runtime.h | 268 | ||||
-rw-r--r-- | libgo/runtime/runtime1.goc | 4 | ||||
-rw-r--r-- | libgo/runtime/signal_unix.c | 16 |
26 files changed, 650 insertions, 975 deletions
diff --git a/libgo/runtime/go-cgo.c b/libgo/runtime/go-cgo.c index 610bcf5e..598c261 100644 --- a/libgo/runtime/go-cgo.c +++ b/libgo/runtime/go-cgo.c @@ -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; } diff --git a/libgo/runtime/go-defer.c b/libgo/runtime/go-defer.c index 3a48fe1..f3e14bd 100644 --- a/libgo/runtime/go-defer.c +++ b/libgo/runtime/go-defer.c @@ -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 index acf2d40..0000000 --- a/libgo/runtime/go-defer.h +++ /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; -}; diff --git a/libgo/runtime/go-deferred-recover.c b/libgo/runtime/go-deferred-recover.c index 78ef287..408ef2a 100644 --- a/libgo/runtime/go-deferred-recover.c +++ b/libgo/runtime/go-deferred-recover.c @@ -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; diff --git a/libgo/runtime/go-panic.c b/libgo/runtime/go-panic.c index 77975c6..436a966 100644 --- a/libgo/runtime/go-panic.c +++ b/libgo/runtime/go-panic.c @@ -11,23 +11,22 @@ #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); } diff --git a/libgo/runtime/go-panic.h b/libgo/runtime/go-panic.h index d29fe88..1b172d9 100644 --- a/libgo/runtime/go-panic.h +++ b/libgo/runtime/go-panic.h @@ -11,25 +11,6 @@ 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); diff --git a/libgo/runtime/go-recover.c b/libgo/runtime/go-recover.c index fc66f61..4d2f0f9f 100644 --- a/libgo/runtime/go-recover.c +++ b/libgo/runtime/go-recover.c @@ -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; } diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c index a948c31..0aef2fc 100644 --- a/libgo/runtime/go-signal.c +++ b/libgo/runtime/go-signal.c @@ -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; diff --git a/libgo/runtime/go-unwind.c b/libgo/runtime/go-unwind.c index 87d9eb3..ea11e4e3 100644 --- a/libgo/runtime/go-unwind.c +++ b/libgo/runtime/go-unwind.c @@ -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), diff --git a/libgo/runtime/heapdump.c b/libgo/runtime/heapdump.c index 52a91e8..18fe913 100644 --- a/libgo/runtime/heapdump.c +++ b/libgo/runtime/heapdump.c @@ -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. diff --git a/libgo/runtime/lock_sema.c b/libgo/runtime/lock_sema.c index ef611fb..06ac6e7 100644 --- a/libgo/runtime/lock_sema.c +++ b/libgo/runtime/lock_sema.c @@ -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; diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc index c111a0e..fbb7b74 100644 --- a/libgo/runtime/malloc.goc +++ b/libgo/runtime/malloc.goc @@ -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; diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h index 065f74a..acd919f 100644 --- a/libgo/runtime/malloc.h +++ b/libgo/runtime/malloc.h @@ -82,11 +82,11 @@ 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; diff --git a/libgo/runtime/mcache.c b/libgo/runtime/mcache.c index 746711a..4396271 100644 --- a/libgo/runtime/mcache.c +++ b/libgo/runtime/mcache.c @@ -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); diff --git a/libgo/runtime/mcentral.c b/libgo/runtime/mcentral.c index e41a83f..62e2c2d 100644 --- a/libgo/runtime/mcentral.c +++ b/libgo/runtime/mcentral.c @@ -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; diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c index d7d0b27..1f6a40c 100644 --- a/libgo/runtime/mgc0.c +++ b/libgo/runtime/mgc0.c @@ -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++; diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c index 793915e..04dc971 100644 --- a/libgo/runtime/mheap.c +++ b/libgo/runtime/mheap.c @@ -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; diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc index 4e8cfc9..bb3f9e8 100644 --- a/libgo/runtime/mprof.goc +++ b/libgo/runtime/mprof.goc @@ -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++); } diff --git a/libgo/runtime/msize.c b/libgo/runtime/msize.c index 34509d0..1bafc82 100644 --- a/libgo/runtime/msize.c +++ b/libgo/runtime/msize.c @@ -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:"); diff --git a/libgo/runtime/netpoll.goc b/libgo/runtime/netpoll.goc index 2f3fa45..2744ec5 100644 --- a/libgo/runtime/netpoll.goc +++ b/libgo/runtime/netpoll.goc @@ -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; } } diff --git a/libgo/runtime/panic.c b/libgo/runtime/panic.c index de000db9..3fb3bde 100644 --- a/libgo/runtime/panic.c +++ b/libgo/runtime/panic.c @@ -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) diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index defb0a5..1ac03a4 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -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 = ∓ - // Setting gcstack_size to 0 is a marker meaning that gcinitial_sp + g->gcinitialsp = ∓ + // 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 = ∓ + g->gcstacksize = 0; + g->gcnextsp = ∓ #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 = ∓ + g->gcinitialsp = ∓ g->gcstack = nil; - g->gcstack_size = 0; - g->gcnext_sp = ∓ + g->gcstacksize = 0; + g->gcnextsp = ∓ #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; } diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index 4140d33..c7d33bc 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -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). diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index ba5eab7..617766b 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -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() diff --git a/libgo/runtime/runtime1.goc b/libgo/runtime/runtime1.goc index cd9d301..26b5566 100644 --- a/libgo/runtime/runtime1.goc +++ b/libgo/runtime/runtime1.goc @@ -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() { diff --git a/libgo/runtime/signal_unix.c b/libgo/runtime/signal_unix.c index 5bee0d2..2cca08c 100644 --- a/libgo/runtime/signal_unix.c +++ b/libgo/runtime/signal_unix.c @@ -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); } } |