summaryrefslogtreecommitdiff
path: root/libgo/runtime/go-libmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/runtime/go-libmain.c')
-rw-r--r--libgo/runtime/go-libmain.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/libgo/runtime/go-libmain.c b/libgo/runtime/go-libmain.c
new file mode 100644
index 0000000000..f578aab43b
--- /dev/null
+++ b/libgo/runtime/go-libmain.c
@@ -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);
+}