OSDN Git Service

Introduce G structure and thread-local global g.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Nov 2011 21:02:48 +0000 (21:02 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 11 Nov 2011 21:02:48 +0000 (21:02 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181301 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
libgo/Makefile.am
libgo/Makefile.in
libgo/runtime/go-defer.c
libgo/runtime/go-deferred-recover.c
libgo/runtime/go-go.c
libgo/runtime/go-main.c
libgo/runtime/go-panic-defer.c [deleted file]
libgo/runtime/go-panic.c
libgo/runtime/go-panic.h
libgo/runtime/go-recover.c
libgo/runtime/go-unwind.c
libgo/runtime/mgc0.c
libgo/runtime/proc.c
libgo/runtime/runtime.h

index eb41490..00e97d2 100644 (file)
@@ -434,7 +434,6 @@ runtime_files = \
        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 \
index 4c07233..68b972e 100644 (file)
@@ -198,14 +198,14 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.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 \
@@ -239,10 +239,9 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
        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 \
@@ -865,7 +864,6 @@ runtime_files = \
        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 \
@@ -2492,7 +2490,6 @@ distclean-compile:
 @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@
@@ -2863,13 +2860,6 @@ go-panic.lo: runtime/go-panic.c
 @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
index 1f116eb..dda62fb 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include "runtime.h"
 #include "go-alloc.h"
 #include "go-panic.h"
 #include "go-defer.h"
@@ -17,18 +18,14 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
 {
   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.  */
@@ -36,22 +33,19 @@ __go_defer (_Bool *frame, void (*pfn) (void *), void *arg)
 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
@@ -69,7 +63,7 @@ __go_undefer (_Bool *frame)
 _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;
 }
index 2d9ca14..d749c27 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include "runtime.h"
 #include "go-panic.h"
 #include "go-defer.h"
 
@@ -78,9 +79,7 @@
 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;
 
index d56b8b1..82b265f 100644 (file)
@@ -115,6 +115,7 @@ remove_current_thread (void *dummy __attribute__ ((unused)))
      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);
@@ -135,10 +136,11 @@ start_go_thread (void *thread_arg)
 
 #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);
 
@@ -230,6 +232,9 @@ __go_go (void (*pfn) (void*), void *arg)
 
   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;
 
@@ -299,9 +304,6 @@ stop_for_gc (void)
   }
 #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);
@@ -433,10 +435,6 @@ runtime_stoptheworld (void)
       --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.  */
 }
 
index 927a36c..15a6a30 100644 (file)
@@ -48,6 +48,10 @@ main (int argc, char **argv)
   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);
diff --git a/libgo/runtime/go-panic-defer.c b/libgo/runtime/go-panic-defer.c
deleted file mode 100644 (file)
index 64773bb..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/* 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;
index f3e182d..8b95cd4 100644 (file)
@@ -41,14 +41,10 @@ __go_panic (struct __go_empty_interface arg)
 {
   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.  */
 
@@ -57,7 +53,7 @@ __go_panic (struct __go_empty_interface arg)
       struct __go_defer_stack *d;
       void (*pfn) (void *);
 
-      d = __go_panic_defer->__defer;
+      d = g->defer;
       if (d == NULL)
        break;
 
@@ -73,7 +69,7 @@ __go_panic (struct __go_empty_interface arg)
              /* 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
@@ -96,13 +92,13 @@ __go_panic (struct __go_empty_interface arg)
          *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 ();
index 2836c46..bd3e238 100644 (file)
@@ -31,36 +31,6 @@ struct __go_panic_stack
   _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));
 
index 4de122e..fe6031c 100644 (file)
@@ -4,6 +4,7 @@
    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"
@@ -21,9 +22,7 @@ __go_can_recover (const void* retaddr)
   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;
 
@@ -31,7 +30,7 @@ __go_can_recover (const void* retaddr)
      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
@@ -53,9 +52,7 @@ __go_recover ()
 {
   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;
 
@@ -63,7 +60,7 @@ __go_recover ()
       ret.__object = NULL;
       return ret;
     }
-  p = __go_panic_defer->__panic;
+  p = g->panic;
   p->__was_recovered = 1;
   return p->__arg;
 }
index e64cf90..58c675a 100644 (file)
@@ -13,6 +13,7 @@
 #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"
@@ -48,12 +49,12 @@ __go_check_defer (_Bool *frame)
 {
   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;
@@ -69,20 +70,20 @@ __go_check_defer (_Bool *frame)
       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);
 
@@ -97,7 +98,7 @@ __go_check_defer (_Bool *frame)
        }
 
       was_recovered = n->__was_recovered;
-      __go_panic_defer->__panic = n->__next;
+      g->panic = n->__next;
       __go_free (n);
 
       if (was_recovered)
@@ -110,17 +111,17 @@ __go_check_defer (_Bool *frame)
       /* 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.  */
@@ -132,7 +133,7 @@ __go_check_defer (_Bool *frame)
   /* 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);
@@ -163,7 +164,7 @@ __go_unwind_stack ()
                    sizeof hdr->exception_class);
   hdr->exception_cleanup = NULL;
 
-  __go_panic_defer->__exception = hdr;
+  g->exception = hdr;
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
   _Unwind_SjLj_RaiseException (hdr);
@@ -413,17 +414,17 @@ PERSONALITY_FUNCTION (int version,
       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),
index cb58525..6d402e5 100644 (file)
@@ -652,7 +652,8 @@ mark(void (*scan)(byte*, int64))
                }
        }
 
-       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);
 
index 8af6935..e9b7c90 100644 (file)
@@ -8,13 +8,15 @@
 
 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;
index 2767dd8..7f061cb 100644 (file)
@@ -48,11 +48,15 @@ typedef unsigned int uintptr __attribute__ ((mode (pointer)));
 
 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.  */
 
@@ -76,9 +80,11 @@ struct Note {
 #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
@@ -94,8 +100,34 @@ enum
 
 /* 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;
@@ -117,7 +149,6 @@ struct      M
        void    *gc_next_segment;
        void    *gc_next_sp;
        void    *gc_initial_sp;
-       struct __go_panic_defer_struct *gc_panic_defer;
 };
 
 /* Macros.  */