runtime/go-new.c \
runtime/go-note.c \
runtime/go-panic.c \
- runtime/go-panic-defer.c \
runtime/go-print.c \
runtime/go-rand.c \
runtime/go-rec-big.c \
runtime/go-map-index.c runtime/go-map-len.c \
runtime/go-map-range.c runtime/go-nanotime.c \
runtime/go-new-channel.c runtime/go-new-map.c runtime/go-new.c \
- runtime/go-note.c runtime/go-panic.c runtime/go-panic-defer.c \
- runtime/go-print.c runtime/go-rand.c runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c runtime/go-recover.c \
- runtime/go-reflect.c runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c runtime/go-reflect-map.c \
- runtime/go-rune.c runtime/go-runtime-error.c \
- runtime/go-sched.c runtime/go-select.c runtime/go-semacquire.c \
+ runtime/go-note.c runtime/go-panic.c runtime/go-print.c \
+ runtime/go-rand.c runtime/go-rec-big.c runtime/go-rec-nb-big.c \
+ runtime/go-rec-nb-small.c runtime/go-rec-small.c \
+ runtime/go-recover.c runtime/go-reflect.c \
+ runtime/go-reflect-call.c runtime/go-reflect-chan.c \
+ runtime/go-reflect-map.c runtime/go-rune.c \
+ runtime/go-runtime-error.c runtime/go-sched.c \
+ runtime/go-select.c runtime/go-semacquire.c \
runtime/go-send-big.c runtime/go-send-nb-big.c \
runtime/go-send-nb-small.c runtime/go-send-small.c \
runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \
go-interface-val-compare.lo go-lock-os-thread.lo \
go-make-slice.lo go-map-delete.lo go-map-index.lo \
go-map-len.lo go-map-range.lo go-nanotime.lo go-new-channel.lo \
- go-new-map.lo go-new.lo go-note.lo go-panic.lo \
- go-panic-defer.lo go-print.lo go-rand.lo go-rec-big.lo \
- go-rec-nb-big.lo go-rec-nb-small.lo go-rec-small.lo \
- go-recover.lo go-reflect.lo go-reflect-call.lo \
+ go-new-map.lo go-new.lo go-note.lo go-panic.lo go-print.lo \
+ go-rand.lo go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
+ go-rec-small.lo go-recover.lo go-reflect.lo go-reflect-call.lo \
go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
go-runtime-error.lo go-sched.lo go-select.lo go-semacquire.lo \
go-send-big.lo go-send-nb-big.lo go-send-nb-small.lo \
runtime/go-new.c \
runtime/go-note.c \
runtime/go-panic.c \
- runtime/go-panic-defer.c \
runtime/go-print.c \
runtime/go-rand.c \
runtime/go-rec-big.c \
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-note.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic-defer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-print.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rand.Plo@am__quote@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-panic.lo `test -f 'runtime/go-panic.c' || echo '$(srcdir)/'`runtime/go-panic.c
-go-panic-defer.lo: runtime/go-panic-defer.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-panic-defer.lo -MD -MP -MF $(DEPDIR)/go-panic-defer.Tpo -c -o go-panic-defer.lo `test -f 'runtime/go-panic-defer.c' || echo '$(srcdir)/'`runtime/go-panic-defer.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-panic-defer.Tpo $(DEPDIR)/go-panic-defer.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-panic-defer.c' object='go-panic-defer.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-panic-defer.lo `test -f 'runtime/go-panic-defer.c' || echo '$(srcdir)/'`runtime/go-panic-defer.c
-
go-print.lo: runtime/go-print.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-print.lo -MD -MP -MF $(DEPDIR)/go-print.Tpo -c -o go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-print.Tpo $(DEPDIR)/go-print.Plo
#include <stddef.h>
+#include "runtime.h"
#include "go-alloc.h"
#include "go-panic.h"
#include "go-defer.h"
{
struct __go_defer_stack *n;
- if (__go_panic_defer == NULL)
- __go_panic_defer = ((struct __go_panic_defer_struct *)
- __go_alloc (sizeof (struct __go_panic_defer_struct)));
-
n = (struct __go_defer_stack *) __go_alloc (sizeof (struct __go_defer_stack));
- n->__next = __go_panic_defer->__defer;
+ n->__next = g->defer;
n->__frame = frame;
- n->__panic = __go_panic_defer->__panic;
+ n->__panic = g->panic;
n->__pfn = pfn;
n->__arg = arg;
n->__retaddr = NULL;
- __go_panic_defer->__defer = n;
+ g->defer = n;
}
/* This function is called when we want to undefer the stack. */
void
__go_undefer (_Bool *frame)
{
- if (__go_panic_defer == NULL)
- return;
- while (__go_panic_defer->__defer != NULL
- && __go_panic_defer->__defer->__frame == frame)
+ while (g->defer != NULL && g->defer->__frame == frame)
{
struct __go_defer_stack *d;
void (*pfn) (void *);
- d = __go_panic_defer->__defer;
+ d = g->defer;
pfn = d->__pfn;
d->__pfn = NULL;
if (pfn != NULL)
(*pfn) (d->__arg);
- __go_panic_defer->__defer = d->__next;
+ g->defer = d->__next;
__go_free (d);
/* Since we are executing a defer function here, we know we are
_Bool
__go_set_defer_retaddr (void *retaddr)
{
- if (__go_panic_defer != NULL && __go_panic_defer->__defer != NULL)
- __go_panic_defer->__defer->__retaddr = retaddr;
+ if (g->defer != NULL)
+ g->defer->__retaddr = retaddr;
return 0;
}
#include <stddef.h>
+#include "runtime.h"
#include "go-panic.h"
#include "go-defer.h"
struct __go_empty_interface
__go_deferred_recover ()
{
- if (__go_panic_defer == NULL
- || __go_panic_defer->__defer == NULL
- || __go_panic_defer->__defer->__panic != __go_panic_defer->__panic)
+ if (g->defer == NULL || g->defer->__panic != g->panic)
{
struct __go_empty_interface ret;
any code from here to thread exit must not assume that m is
valid. */
m = NULL;
+ g = NULL;
i = pthread_mutex_unlock (&__go_thread_ids_lock);
__go_assert (i == 0);
#ifdef __rtems__
__wrap_rtems_task_variable_add ((void **) &m);
- __wrap_rtems_task_variable_add ((void **) &__go_panic_defer);
+ __wrap_rtems_task_variable_add ((void **) &g);
#endif
m = newm;
+ g = m->curg;
pthread_cleanup_push (remove_current_thread, NULL);
newm->list_entry = list_entry;
+ newm->curg = __go_alloc (sizeof (G));
+ newm->curg->m = newm;
+
newm->id = __sync_fetch_and_add (&mcount, 1);
newm->fastrand = 0x49f6428aUL + newm->id;
}
#endif
- /* FIXME: Perhaps we should just move __go_panic_defer into M. */
- m->gc_panic_defer = __go_panic_defer;
-
/* Tell the garbage collector that we are ready by posting to the
semaphore. */
i = sem_post (&__go_thread_ready_sem);
--c;
}
- /* The gc_panic_defer field should now be set for all M's except the
- one in this thread. Set this one now. */
- m->gc_panic_defer = __go_panic_defer;
-
/* Leave with __go_thread_ids_lock held. */
}
int i;
struct __go_string *values;
+ m = &runtime_m0;
+ g = &runtime_g0;
+ m->curg = g;
+ g->m = m;
runtime_mallocinit ();
runtime_cpuprofinit ();
__go_gc_goroutine_init (&argc);
+++ /dev/null
-/* go-panic-stack.c -- The panic/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. */
-
-#include "go-panic.h"
-
-#ifdef __rtems__
-#define __thread
-#endif
-
-__thread struct __go_panic_defer_struct *__go_panic_defer;
{
struct __go_panic_stack *n;
- if (__go_panic_defer == NULL)
- __go_panic_defer = ((struct __go_panic_defer_struct *)
- __go_alloc (sizeof (struct __go_panic_defer_struct)));
-
n = (struct __go_panic_stack *) __go_alloc (sizeof (struct __go_panic_stack));
n->__arg = arg;
- n->__next = __go_panic_defer->__panic;
- __go_panic_defer->__panic = n;
+ n->__next = g->panic;
+ g->panic = n;
/* Run all the defer functions. */
struct __go_defer_stack *d;
void (*pfn) (void *);
- d = __go_panic_defer->__defer;
+ d = g->defer;
if (d == NULL)
break;
/* Some defer function called recover. That means that
we should stop running this panic. */
- __go_panic_defer->__panic = n->__next;
+ g->panic = n->__next;
__go_free (n);
/* Now unwind the stack by throwing an exception. The
*d->__frame = 0;
}
- __go_panic_defer->__defer = d->__next;
+ g->defer = d->__next;
__go_free (d);
}
/* The panic was not recovered. */
- __printpanics (__go_panic_defer->__panic);
+ __printpanics (g->panic);
/* FIXME: We should dump a call stack here. */
abort ();
_Bool __is_foreign;
};
-/* The panic and defer stacks, grouped together into a single thread
- local variable for convenience for systems without TLS. */
-
-struct __go_panic_defer_struct
-{
- /* The list of defers to execute. */
- struct __go_defer_stack *__defer;
-
- /* The list of currently active panics. There will be more than one
- if a deferred function calls panic. */
- struct __go_panic_stack *__panic;
-
- /* The current exception being thrown when unwinding after a call to
- panic . This is really struct _UnwindException *. */
- void *__exception;
-
- /* Whether the current exception is from some other language. */
- _Bool __is_foreign;
-};
-
-#ifdef __rtems__
-#define __thread
-#endif
-
-extern __thread struct __go_panic_defer_struct *__go_panic_defer;
-
-#ifdef __rtems__
-#undef __thread
-#endif
-
extern void __go_panic (struct __go_empty_interface)
__attribute__ ((noreturn));
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
+#include "runtime.h"
#include "interface.h"
#include "go-panic.h"
#include "go-defer.h"
const char* ret;
const char* dret;
- if (__go_panic_defer == NULL)
- return 0;
- d = __go_panic_defer->__defer;
+ d = g->defer;
if (d == NULL)
return 0;
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 == __go_panic_defer->__panic)
+ if (d->__panic == g->panic)
return 0;
/* D->__RETADDR is the address of a label immediately following the
{
struct __go_panic_stack *p;
- if (__go_panic_defer == NULL
- || __go_panic_defer->__panic == NULL
- || __go_panic_defer->__panic->__was_recovered)
+ if (g->panic == NULL || g->panic->__was_recovered)
{
struct __go_empty_interface ret;
ret.__object = NULL;
return ret;
}
- p = __go_panic_defer->__panic;
+ p = g->panic;
p->__was_recovered = 1;
return p->__arg;
}
#define NO_SIZE_OF_ENCODED_VALUE
#include "unwind-pe.h"
+#include "runtime.h"
#include "go-alloc.h"
#include "go-defer.h"
#include "go-panic.h"
{
struct _Unwind_Exception *hdr;
- if (__go_panic_defer == NULL)
+ if (g == NULL)
{
/* Some other language has thrown an exception. We know there
are no defer handlers, so there is nothing to do. */
}
- else if (__go_panic_defer->__is_foreign)
+ else if (g->is_foreign)
{
struct __go_panic_stack *n;
_Bool was_recovered;
n->__arg.__object = NULL;
n->__was_recovered = 0;
n->__is_foreign = 1;
- n->__next = __go_panic_defer->__panic;
- __go_panic_defer->__panic = n;
+ n->__next = g->panic;
+ g->panic = n;
while (1)
{
struct __go_defer_stack *d;
void (*pfn) (void *);
- d = __go_panic_defer->__defer;
+ d = g->defer;
if (d == NULL || d->__frame != frame || d->__pfn == NULL)
break;
pfn = d->__pfn;
- __go_panic_defer->__defer = d->__next;
+ g->defer = d->__next;
(*pfn) (d->__arg);
}
was_recovered = n->__was_recovered;
- __go_panic_defer->__panic = n->__next;
+ g->panic = n->__next;
__go_free (n);
if (was_recovered)
/* We are panicing through this function. */
*frame = 0;
}
- else if (__go_panic_defer->__defer != NULL
- && __go_panic_defer->__defer->__pfn == NULL
- && __go_panic_defer->__defer->__frame == frame)
+ else if (g->defer != NULL
+ && g->defer->__pfn == NULL
+ && g->defer->__frame == frame)
{
struct __go_defer_stack *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 = __go_panic_defer->__defer;
- __go_panic_defer->__defer = d->__next;
+ d = g->defer;
+ g->defer = d->__next;
__go_free (d);
/* We are returning from this function. */
/* This is some other defer function. It was already run by the
call to panic, or just above. Rethrow the exception. */
- hdr = (struct _Unwind_Exception *) __go_panic_defer->__exception;
+ hdr = (struct _Unwind_Exception *) g->exception;
#ifdef LIBGO_SJLJ_EXCEPTIONS
_Unwind_SjLj_Resume_or_Rethrow (hdr);
sizeof hdr->exception_class);
hdr->exception_cleanup = NULL;
- __go_panic_defer->__exception = hdr;
+ g->exception = hdr;
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException (hdr);
return _URC_HANDLER_FOUND;
}
- /* It's possible for __go_panic_defer to be NULL here for an
- exception thrown by a language other than Go. */
- if (__go_panic_defer == NULL)
+ /* It's possible for g to be NULL here for an exception thrown by a
+ language other than Go. */
+ if (g == NULL)
{
if (!is_foreign)
abort ();
}
else
{
- __go_panic_defer->__exception = ue_header;
- __go_panic_defer->__is_foreign = is_foreign;
+ g->exception = ue_header;
+ g->is_foreign = is_foreign;
}
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
}
}
- scan((byte*)&m0, sizeof m0);
+ scan((byte*)&runtime_m0, sizeof runtime_m0);
+ scan((byte*)&runtime_g0, sizeof runtime_g0);
scan((byte*)&finq, sizeof finq);
runtime_MProf_Mark(scan);
typedef struct Sched Sched;
-M m0;
+G runtime_g0;
+M runtime_m0;
#ifdef __rtems__
#define __thread
#endif
-__thread M *m = &m0;
+__thread G *g;
+__thread M *m;
static struct {
Lock;
typedef uint8 bool;
typedef uint8 byte;
+typedef struct G G;
typedef struct M M;
typedef struct MCache MCache;
typedef struct FixAlloc FixAlloc;
typedef struct Lock Lock;
+typedef struct __go_defer_stack Defer;
+typedef struct __go_panic_stack Panic;
+
/* We use mutexes for locks. 6g uses futexes directly, and perhaps
someday we will do that too. */
#define __thread
#endif
+extern __thread G* g;
extern __thread M* m;
-extern M m0;
+extern M runtime_m0;
+extern G runtime_g0;
#ifdef __rtems__
#undef __thread
/* Structures. */
+struct G
+{
+ Defer* defer;
+ Panic* panic;
+ void* exception; // current exception being thrown
+ bool is_foreign; // whether current exception from other language
+ byte* entry; // initial function
+ G* alllink; // on allg
+ void* param; // passed parameter on wakeup
+ int16 status;
+ int32 goid;
+ int8* waitreason; // if status==Gwaiting
+ G* schedlink;
+ bool readyonstop;
+ bool ispanic;
+ M* m; // for debuggers, but offset not hard-coded
+ M* lockedm;
+ M* idlem;
+ // int32 sig;
+ // uintptr sigcode0;
+ // uintptr sigcode1;
+ // uintptr sigpc;
+ // uintptr gopc; // pc of go statement that created this goroutine
+};
+
struct M
{
+ G* curg; // current running goroutine
int32 id;
int32 mallocing;
int32 gcing;
void *gc_next_segment;
void *gc_next_sp;
void *gc_initial_sp;
- struct __go_panic_defer_struct *gc_panic_defer;
};
/* Macros. */