Index: src/pkg/runtime/cgo/gcc_sharedlib_linux.c |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/pkg/runtime/cgo/gcc_sharedlib_linux.c |
@@ -0,0 +1,130 @@ |
+// Copyright 2009 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. |
+ |
+// cgo glue for initializing the Go runtime in shared library mode |
+ |
+#include <pthread.h> |
+#include <stdlib.h> |
+#include <stdio.h> |
+#include <string.h> // strerror |
+#include <sys/mman.h> |
+#include <unistd.h> |
+ |
+static pthread_mutex_t wait_mu = PTHREAD_MUTEX_INITIALIZER; |
+static pthread_cond_t wait_cond = PTHREAD_COND_INITIALIZER; |
+static pthread_once_t init_once = PTHREAD_ONCE_INIT; |
+static int init_done; |
+ |
+typedef void (*MainFunc)(int, char**); |
+static MainFunc runtime_main; |
+ |
+char** |
+x_cgo_getenviron(void) |
+{ |
+ extern char** environ; |
+ return environ; |
+} |
+ |
+void |
+x_cgo_lib_init_done(void *v) |
+{ |
+ int err; |
+ |
+ err = pthread_mutex_lock(&wait_mu); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_mutex_lock failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+ |
+ init_done = 1; |
+ |
+ err = pthread_cond_broadcast(&wait_cond); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_cond_broadcast failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+ err = pthread_mutex_unlock(&wait_mu); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_mutex_unlock failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+} |
+ |
+static void* |
+lib_init_entry(void* v) |
+{ |
+ runtime_main(0, NULL); |
+ |
+ return NULL; |
+} |
+ |
+static void |
+x_cgo_lib_init_once(void) |
+{ |
+ pthread_attr_t attr; |
+ pthread_t p; |
+ int err; |
+ long ps; |
+ void *map; |
+ void *guard_addr; |
+ |
+ ps = sysconf(_SC_PAGESIZE); |
+ if(ps == -1) { |
+ fprintf(stderr, "runtime/cgo: failed to query page size\n"); |
+ abort(); |
+ } |
+ if(sizeof(void *) > 4) |
+ guard_addr = (void*)(0x00d0ULL<<32); |
+ else |
+ guard_addr = (void*)(0xa0000000); |
+ map = mmap(guard_addr, ps, PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0); |
+ if(map == MAP_FAILED || map != guard_addr) { |
+ fprintf(stderr, "runtime/cgo: failed to map guard page (%p) (multiple go shared libraries in the same process is not supported)\n", guard_addr); |
+ abort(); |
+ } |
+ |
+ pthread_attr_init(&attr); |
+ err = pthread_create(&p, &attr, lib_init_entry, runtime_main); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+ |
+ err = pthread_mutex_lock(&wait_mu); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_mutex_lock failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+ do { |
+ err = pthread_cond_wait(&wait_cond, &wait_mu); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_cond_wait failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+ } while (!init_done); |
+ err = pthread_mutex_unlock(&wait_mu); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_mutex_unlock failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+} |
+ |
+void |
+x_cgo_lib_setup(MainFunc main_func) |
+{ |
+ runtime_main = main_func; |
+} |
+ |
+void |
+x_cgo_lib_init(void) |
+{ |
+ int err; |
+ |
+ err = pthread_once(&init_once, x_cgo_lib_init_once); |
+ if(err != 0) { |
+ fprintf(stderr, "runtime/cgo: pthread_once failed: %s\n", strerror(err)); |
+ abort(); |
+ } |
+} |
+ |