diff -r ae8a4c892d42 libgo/Makefile.am
--- a/libgo/Makefile.am	Fri Apr 24 15:07:55 2015 -0700
+++ b/libgo/Makefile.am	Wed Apr 29 13:41:41 2015 -0700
@@ -105,7 +105,7 @@
 toolexeclib_LIBRARIES = libgobegin-llgo.a
 else
 toolexeclib_LTLIBRARIES = libgo.la
-toolexeclib_LIBRARIES = libgobegin.a libnetgo.a
+toolexeclib_LIBRARIES = libgobegin.a libgolibbegin.a libnetgo.a
 endif
 
 toolexeclibgo_DATA = \
@@ -2036,6 +2036,11 @@
 libgobegin_a_CFLAGS = $(AM_CFLAGS) -fPIC
 libgobegin_llgo_a_CFLAGS = $(AM_CFLAGS) -fPIC
 
+libgolibbegin_a_SOURCES = \
+	runtime/go-libmain.c
+
+libgolibbegin_a_CFLAGS = $(AM_CFLAGS) -fPIC
+
 libnetgo_a_SOURCES = $(go_netgo_files)
 libnetgo_a_LIBADD = netgo.o
 
@@ -2067,7 +2072,7 @@
 BUILDNETGO = \
 	$(MKDIR_P) $(@D); \
 	files=`echo $^ | sed -e 's/[^ ]*\.gox//g'`; \
-	$(GOCOMPILE) -I . -c -fgo-pkgpath=net -o $@ $$files
+	$(GOCOMPILE) -I . -c -fPIC -fgo-pkgpath=net -o $@ $$files
 
 GOTESTFLAGS =
 GOBENCH = 
diff -r ae8a4c892d42 libgo/runtime/go-cgo.c
--- a/libgo/runtime/go-cgo.c	Fri Apr 24 15:07:55 2015 -0700
+++ b/libgo/runtime/go-cgo.c	Wed Apr 29 13:41:41 2015 -0700
@@ -8,6 +8,9 @@
 #include "go-alloc.h"
 #include "interface.h"
 #include "go-panic.h"
+#include "go-type.h"
+
+extern void __go_receive (ChanType *, Hchan *, byte *);
 
 /* Prepare to call from code written in Go to code written in C or
    C++.  This takes the current goroutine out of the Go scheduler, as
@@ -86,6 +89,15 @@
 
   runtime_exitsyscall ();
 
+  if (runtime_g ()->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
+	 call may be coming in before package initialization is
+	 complete.  Wait until it is.  */
+      __go_receive (NULL, runtime_main_init_done, NULL);
+    }
+
   mp = runtime_m ();
   if (mp->needextram)
     {
@@ -177,3 +189,65 @@
 
   __go_panic (e);
 }
+
+/* Used for _cgo_wait_runtime_init_done.  This is based on code in
+   runtime/cgo/gcc_libinit.c in the master library.  */
+
+static pthread_cond_t runtime_init_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t runtime_init_mu = PTHREAD_MUTEX_INITIALIZER;
+static _Bool runtime_init_done;
+
+/* This is called by exported cgo functions to ensure that the runtime
+   has been initialized before we enter the function.  This is needed
+   when building with -buildmode=c-archive or similar.  */
+
+void
+_cgo_wait_runtime_init_done (void)
+{
+  int err;
+
+  if (__atomic_load_n (&runtime_init_done, __ATOMIC_ACQUIRE))
+    return;
+
+  err = pthread_mutex_lock (&runtime_init_mu);
+  if (err != 0)
+    abort ();
+  while (!__atomic_load_n (&runtime_init_done, __ATOMIC_ACQUIRE))
+    {
+      err = pthread_cond_wait (&runtime_init_cond, &runtime_init_mu);
+      if (err != 0)
+	abort ();
+    }
+  err = pthread_mutex_unlock (&runtime_init_mu);
+  if (err != 0)
+    abort ();
+}
+
+/* This is called by runtime_main after the Go runtime is
+   initialized.  */
+
+void
+_cgo_notify_runtime_init_done (void)
+{
+  int err;
+
+  err = pthread_mutex_lock (&runtime_init_mu);
+  if (err != 0)
+    abort ();
+  __atomic_store_n (&runtime_init_done, 1, __ATOMIC_RELEASE);
+  err = pthread_cond_broadcast (&runtime_init_cond);
+  if (err != 0)
+    abort ();
+  err = pthread_mutex_unlock (&runtime_init_mu);
+  if (err != 0)
+    abort ();
+}
+
+// runtime_iscgo is set to true if some cgo code is linked in.
+// This is done by a constructor in the cgo generated code.
+_Bool runtime_iscgo;
+
+// runtime_cgoHasExtraM is set on startup when an extra M is created
+// for cgo.  The extra M must be created before any C/C++ code calls
+// cgocallback.
+_Bool runtime_cgoHasExtraM;
diff -r ae8a4c892d42 libgo/runtime/go-libmain.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/go-libmain.c	Wed Apr 29 13:41:41 2015 -0700
@@ -0,0 +1,114 @@
+/* go-libmain.c -- the startup function for a Go library.
+
+   Copyright 2015 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 "config.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "runtime.h"
+#include "go-alloc.h"
+#include "array.h"
+#include "arch.h"
+#include "malloc.h"
+
+/* This is used when building a standalone Go library using the Go
+   command's -buildmode=c-archive or -buildmode=c-shared option.  It
+   starts up the Go code as a global constructor but does not take any
+   other action.  The main program is written in some other language
+   and calls exported Go functions as needed.  */
+
+static void die (const char *, int);
+static void initfn (int, char **, char **);
+static void *gostart (void *);
+
+/* Used to pass arguments to the thread that runs the Go startup.  */
+
+struct args {
+  int argc;
+  char **argv;
+};
+
+/* We use .init_array so that we can get the command line arguments.
+   This obviously assumes .init_array support; different systems may
+   require other approaches.  */
+
+typedef void (*initarrayfn) (int, char **, char **);
+
+static initarrayfn initarray[1]
+__attribute__ ((section (".init_array"), used)) =
+  { initfn };
+
+/* This function is called at program startup time.  It starts a new
+   thread to do the actual Go startup, so that program startup is not
+   paused waiting for the Go initialization functions.  Exported cgo
+   functions will wait for initialization to complete if
+   necessary.  */
+
+static void
+initfn (int argc, char **argv, char** env __attribute__ ((unused)))
+{
+  int err;
+  pthread_attr_t attr;
+  struct args *a;
+  pthread_t tid;
+
+  a = (struct args *) malloc (sizeof *a);
+  if (a == NULL)
+    die ("malloc", errno);
+  a->argc = argc;
+  a->argv = argv;
+
+  err = pthread_attr_init (&attr);
+  if (err != 0)
+    die ("pthread_attr_init", err);
+  err = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+  if (err != 0)
+    die ("pthread_attr_setdetachstate", err);
+
+  err = pthread_create (&tid, &attr, gostart, (void *) a);
+  if (err != 0)
+    die ("pthread_create", err);
+
+  err = pthread_attr_destroy (&attr);
+  if (err != 0)
+    die ("pthread_attr_destroy", err);
+}
+
+/* Start up the Go runtime.  */
+
+static void *
+gostart (void *arg)
+{
+  struct args *a = (struct args *) arg;
+
+  runtime_isarchive = true;
+
+  if (runtime_isstarted)
+    return NULL;
+  runtime_isstarted = true;
+
+  runtime_check ();
+  runtime_args (a->argc, (byte **) a->argv);
+  runtime_osinit ();
+  runtime_schedinit ();
+  __go_go (runtime_main, NULL);
+  runtime_mstart (runtime_m ());
+  abort ();
+}
+
+/* If something goes wrong during program startup, crash.  There is no
+   way to report failure and nobody to whom to report it.  */
+
+static void
+die (const char *fn, int err)
+{
+  fprintf (stderr, "%s: %d\n", fn, err);
+  exit (EXIT_FAILURE);
+}
diff -r ae8a4c892d42 libgo/runtime/go-main.c
--- a/libgo/runtime/go-main.c	Fri Apr 24 15:07:55 2015 -0700
+++ b/libgo/runtime/go-main.c	Wed Apr 29 13:41:41 2015 -0700
@@ -35,6 +35,12 @@
 int
 main (int argc, char **argv)
 {
+  runtime_isarchive = false;
+
+  if (runtime_isstarted)
+    return NULL;
+  runtime_isstarted = true;
+
   runtime_check ();
   runtime_args (argc, (byte **) argv);
   runtime_osinit ();
diff -r ae8a4c892d42 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Fri Apr 24 15:07:55 2015 -0700
+++ b/libgo/runtime/proc.c	Wed Apr 29 13:41:41 2015 -0700
@@ -372,7 +372,6 @@
 Sched	runtime_sched;
 int32	runtime_gomaxprocs;
 uint32	runtime_needextram = 1;
-bool	runtime_iscgo = true;
 M	runtime_m0;
 G	runtime_g0;	// idle goroutine for m0
 G*	runtime_lastg;
@@ -389,6 +388,8 @@
 uintptr runtime_allglen;
 static	uintptr allgcap;
 
+bool	runtime_isarchive;
+
 void* runtime_mstart(void*);
 static void runqput(P*, G*);
 static G* runqget(P*);
@@ -428,6 +429,8 @@
 static bool exitsyscallfast(void);
 static void allgadd(G*);
 
+bool runtime_isstarted;
+
 // The bootstrap sequence is:
 //
 //	call osinit
@@ -490,6 +493,64 @@
 extern void main_init(void) __asm__ (GOSYM_PREFIX "__go_init_main");
 extern void main_main(void) __asm__ (GOSYM_PREFIX "main.main");
 
+// Used to determine the field alignment.
+
+struct field_align
+{
+  char c;
+  Hchan *p;
+};
+
+// main_init_done is a signal used by cgocallbackg that initialization
+// has been completed.  It is made before _cgo_notify_runtime_init_done,
+// so all cgo calls can rely on it existing.  When main_init is
+// complete, it is closed, meaning cgocallbackg can reliably receive
+// from it.
+Hchan *runtime_main_init_done;
+
+// The chan bool type, for runtime_main_init_done.
+
+extern const struct __go_type_descriptor bool_type_descriptor
+  __asm__ (GOSYM_PREFIX "__go_tdn_bool");
+
+static struct __go_channel_type chan_bool_type_descriptor =
+  {
+    /* __common */
+    {
+      /* __code */
+      GO_CHAN,
+      /* __align */
+      __alignof (Hchan *),
+      /* __field_align */
+      offsetof (struct field_align, p) - 1,
+      /* __size */
+      sizeof (Hchan *),
+      /* __hash */
+      0, /* This value doesn't matter.  */
+      /* __hashfn */
+      __go_type_hash_error,
+      /* __equalfn */
+      __go_type_equal_error,
+      /* __gc */
+      NULL, /* This value doesn't matter */
+      /* __reflection */
+      NULL, /* This value doesn't matter */
+      /* __uncommon */
+      NULL,
+      /* __pointer_to_this */
+      NULL,
+      /* __zero */
+      NULL /* This value doesn't matter */
+    },
+    /* __element_type */
+    &bool_type_descriptor,
+    /* __dir */
+    CHANNEL_BOTH_DIR
+  };
+
+extern Hchan *__go_new_channel (ChanType *, uintptr);
+extern void closechan(Hchan *) __asm__ (GOSYM_PREFIX "runtime.closechan");
+
 static void
 initDone(void *arg __attribute__ ((unused))) {
 	runtime_unlockOSThread();
@@ -535,8 +596,15 @@
 	if(m != &runtime_m0)
 		runtime_throw("runtime_main not on m0");
 	__go_go(runtime_MHeap_Scavenger, nil);
+
+	runtime_main_init_done = __go_new_channel(&chan_bool_type_descriptor, 0);
+
+	_cgo_notify_runtime_init_done();
+
 	main_init();
 
+	closechan(runtime_main_init_done);
+
 	if(g->defer != &d || d.__pfn != initDone)
 		runtime_throw("runtime: bad defer entry after init");
 	g->defer = d.__next;
@@ -547,6 +615,14 @@
 	// roots.
 	mstats.enablegc = 1;
 
+	if(runtime_isarchive) {
+		// This is not a complete program, but is instead a
+		// library built using -buildmode=c-archive or
+		// c-shared.  Now that we are initialized, there is
+		// nothing further to do.
+		return;
+	}
+
 	main_main();
 
 	// Make racy client program work: if panicking on
@@ -1011,8 +1087,14 @@
 
 	// Install signal handlers; after minit so that minit can
 	// prepare the thread to be able to handle the signals.
-	if(m == &runtime_m0)
+	if(m == &runtime_m0) {
+		if(runtime_iscgo && !runtime_cgoHasExtraM) {
+			runtime_cgoHasExtraM = true;
+			runtime_newextram();
+			runtime_needextram = 0;
+		}
 		runtime_initsig();
+	}
 	
 	if(m->mstartfn)
 		m->mstartfn();
@@ -2747,6 +2829,13 @@
 	int32 run, grunning, s;
 	uintptr i;
 
+	// For -buildmode=c-shared or -buildmode=c-archive it's OK if
+	// there are no running goroutines.  The calling program is
+	// assumed to be running.
+	if(runtime_isarchive) {
+		return;
+	}
+
 	// -1 for sysmon
 	run = runtime_sched.mcount - runtime_sched.nmidle - runtime_sched.nmidlelocked - 1 - countextra();
 	if(run > 0)
@@ -3332,6 +3421,7 @@
 runtime_proc_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
 {
 	enqueue1(wbufp, (Obj){(byte*)&runtime_sched, sizeof runtime_sched, 0});
+	enqueue1(wbufp, (Obj){(byte*)&runtime_main_init_done, sizeof runtime_main_init_done, 0});
 }
 
 // Return whether we are waiting for a GC.  This gc toolchain uses
diff -r ae8a4c892d42 libgo/runtime/runtime.h
--- a/libgo/runtime/runtime.h	Fri Apr 24 15:07:55 2015 -0700
+++ b/libgo/runtime/runtime.h	Wed Apr 29 13:41:41 2015 -0700
@@ -509,6 +509,9 @@
 extern	DebugVars	runtime_debug;
 extern	uintptr	runtime_maxstacksize;
 
+extern	bool	runtime_isstarted;
+extern	bool	runtime_isarchive;
+
 /*
  * common functions and data
  */
@@ -845,3 +848,9 @@
 
 struct time_now_ret now() __asm__ (GOSYM_PREFIX "time.now")
   __attribute__ ((no_split_stack));
+
+extern void _cgo_wait_runtime_init_done (void);
+extern void _cgo_notify_runtime_init_done (void);
+extern _Bool runtime_iscgo;
+extern _Bool runtime_cgoHasExtraM;
+extern Hchan *runtime_main_init_done;
