Skip to content

Commit

Permalink
runtime: Support -buildmode=c-shared.
Browse files Browse the repository at this point in the history
These changes permit using the go tool from the upcoming Go
1.5 release with -buildmode=c-archive to build gccgo code into
an archive file that can be linked with a C program.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@222594 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
ian committed Apr 29, 2015
1 parent 0a6c9df commit 87bb088
Show file tree
Hide file tree
Showing 7 changed files with 333 additions and 8 deletions.
9 changes: 7 additions & 2 deletions libgo/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ toolexeclib_LTLIBRARIES = libgo-llgo.la
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 = \
Expand Down Expand Up @@ -2036,6 +2036,11 @@ libgobegin_llgo_a_SOURCES = \
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

Expand Down Expand Up @@ -2067,7 +2072,7 @@ BUILDPACKAGE = \
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 =
Expand Down
35 changes: 31 additions & 4 deletions libgo/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ libgobegin_a_AR = $(AR) $(ARFLAGS)
libgobegin_a_LIBADD =
am_libgobegin_a_OBJECTS = libgobegin_a-go-main.$(OBJEXT)
libgobegin_a_OBJECTS = $(am_libgobegin_a_OBJECTS)
libgolibbegin_a_AR = $(AR) $(ARFLAGS)
libgolibbegin_a_LIBADD =
am_libgolibbegin_a_OBJECTS = libgolibbegin_a-go-libmain.$(OBJEXT)
libgolibbegin_a_OBJECTS = $(am_libgolibbegin_a_OBJECTS)
libnetgo_a_AR = $(AR) $(ARFLAGS)
libnetgo_a_DEPENDENCIES = netgo.o
am__objects_1 =
Expand Down Expand Up @@ -264,8 +268,8 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libgobegin_llgo_a_SOURCES) $(libgobegin_a_SOURCES) \
$(libnetgo_a_SOURCES) $(libgo_llgo_la_SOURCES) \
$(libgo_la_SOURCES)
$(libgolibbegin_a_SOURCES) $(libnetgo_a_SOURCES) \
$(libgo_llgo_la_SOURCES) $(libgo_la_SOURCES)
MULTISRCTOP =
MULTIBUILDTOP =
MULTIDIRS =
Expand Down Expand Up @@ -532,7 +536,7 @@ AM_MAKEFLAGS = \
FLAGS_TO_PASS = $(AM_MAKEFLAGS)
@GOC_IS_LLGO_FALSE@toolexeclib_LTLIBRARIES = libgo.la
@GOC_IS_LLGO_TRUE@toolexeclib_LTLIBRARIES = libgo-llgo.la
@GOC_IS_LLGO_FALSE@toolexeclib_LIBRARIES = libgobegin.a libnetgo.a
@GOC_IS_LLGO_FALSE@toolexeclib_LIBRARIES = libgobegin.a libgolibbegin.a libnetgo.a
@GOC_IS_LLGO_TRUE@toolexeclib_LIBRARIES = libgobegin-llgo.a
toolexeclibgo_DATA = \
bufio.gox \
Expand Down Expand Up @@ -2102,6 +2106,10 @@ libgobegin_llgo_a_SOURCES = \
# Use -fPIC for libgobegin so that it can be put in a PIE.
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
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS))
Expand Down Expand Up @@ -2132,7 +2140,7 @@ BUILDPACKAGE = \
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 =
Expand Down Expand Up @@ -2421,6 +2429,10 @@ libgobegin.a: $(libgobegin_a_OBJECTS) $(libgobegin_a_DEPENDENCIES)
-rm -f libgobegin.a
$(libgobegin_a_AR) libgobegin.a $(libgobegin_a_OBJECTS) $(libgobegin_a_LIBADD)
$(RANLIB) libgobegin.a
libgolibbegin.a: $(libgolibbegin_a_OBJECTS) $(libgolibbegin_a_DEPENDENCIES)
-rm -f libgolibbegin.a
$(libgolibbegin_a_AR) libgolibbegin.a $(libgolibbegin_a_OBJECTS) $(libgolibbegin_a_LIBADD)
$(RANLIB) libgolibbegin.a
libnetgo.a: $(libnetgo_a_OBJECTS) $(libnetgo_a_DEPENDENCIES)
-rm -f libnetgo.a
$(libnetgo_a_AR) libnetgo.a $(libnetgo_a_OBJECTS) $(libnetgo_a_LIBADD)
Expand Down Expand Up @@ -2546,6 +2558,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lfstack.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgobegin_a-go-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgobegin_llgo_a-go-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgolibbegin_a-go-libmain.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_futex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_sema.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc.Plo@am__quote@
Expand Down Expand Up @@ -2631,6 +2644,20 @@ libgobegin_a-go-main.obj: runtime/go-main.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgobegin_a_CFLAGS) $(CFLAGS) -c -o libgobegin_a-go-main.obj `if test -f 'runtime/go-main.c'; then $(CYGPATH_W) 'runtime/go-main.c'; else $(CYGPATH_W) '$(srcdir)/runtime/go-main.c'; fi`

libgolibbegin_a-go-libmain.o: runtime/go-libmain.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgolibbegin_a_CFLAGS) $(CFLAGS) -MT libgolibbegin_a-go-libmain.o -MD -MP -MF $(DEPDIR)/libgolibbegin_a-go-libmain.Tpo -c -o libgolibbegin_a-go-libmain.o `test -f 'runtime/go-libmain.c' || echo '$(srcdir)/'`runtime/go-libmain.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libgolibbegin_a-go-libmain.Tpo $(DEPDIR)/libgolibbegin_a-go-libmain.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-libmain.c' object='libgolibbegin_a-go-libmain.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgolibbegin_a_CFLAGS) $(CFLAGS) -c -o libgolibbegin_a-go-libmain.o `test -f 'runtime/go-libmain.c' || echo '$(srcdir)/'`runtime/go-libmain.c

libgolibbegin_a-go-libmain.obj: runtime/go-libmain.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgolibbegin_a_CFLAGS) $(CFLAGS) -MT libgolibbegin_a-go-libmain.obj -MD -MP -MF $(DEPDIR)/libgolibbegin_a-go-libmain.Tpo -c -o libgolibbegin_a-go-libmain.obj `if test -f 'runtime/go-libmain.c'; then $(CYGPATH_W) 'runtime/go-libmain.c'; else $(CYGPATH_W) '$(srcdir)/runtime/go-libmain.c'; fi`
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libgolibbegin_a-go-libmain.Tpo $(DEPDIR)/libgolibbegin_a-go-libmain.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-libmain.c' object='libgolibbegin_a-go-libmain.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgolibbegin_a_CFLAGS) $(CFLAGS) -c -o libgolibbegin_a-go-libmain.obj `if test -f 'runtime/go-libmain.c'; then $(CYGPATH_W) 'runtime/go-libmain.c'; else $(CYGPATH_W) '$(srcdir)/runtime/go-libmain.c'; fi`

go-append.lo: runtime/go-append.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-append.lo -MD -MP -MF $(DEPDIR)/go-append.Tpo -c -o go-append.lo `test -f 'runtime/go-append.c' || echo '$(srcdir)/'`runtime/go-append.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-append.Tpo $(DEPDIR)/go-append.Plo
Expand Down
74 changes: 74 additions & 0 deletions libgo/runtime/go-cgo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -86,6 +89,15 @@ syscall_cgocallback ()

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)
{
Expand Down Expand Up @@ -177,3 +189,65 @@ _cgo_panic (const char *p)

__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;
114 changes: 114 additions & 0 deletions libgo/runtime/go-libmain.c
Original file line number Diff line number Diff line change
@@ -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);
}
6 changes: 6 additions & 0 deletions libgo/runtime/go-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ extern char **environ;
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 ();
Expand Down
Loading

0 comments on commit 87bb088

Please sign in to comment.