diff options
author | Ben Cheng <bccheng@google.com> | 2014-03-25 22:37:19 -0700 |
---|---|---|
committer | Ben Cheng <bccheng@google.com> | 2014-03-25 22:37:19 -0700 |
commit | 1bc5aee63eb72b341f506ad058502cd0361f0d10 (patch) | |
tree | c607e8252f3405424ff15bc2d00aa38dadbb2518 /gcc-4.9/libgo/runtime/go-cgo.c | |
parent | 283a0bf58fcf333c58a2a92c3ebbc41fb9eb1fdb (diff) | |
download | toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.gz toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.bz2 toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.zip |
Initial checkin of GCC 4.9.0 from trunk (r208799).
Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba
Diffstat (limited to 'gcc-4.9/libgo/runtime/go-cgo.c')
-rw-r--r-- | gcc-4.9/libgo/runtime/go-cgo.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/gcc-4.9/libgo/runtime/go-cgo.c b/gcc-4.9/libgo/runtime/go-cgo.c new file mode 100644 index 000000000..9ba1ea7d0 --- /dev/null +++ b/gcc-4.9/libgo/runtime/go-cgo.c @@ -0,0 +1,195 @@ +/* go-cgo.c -- SWIG support routines for libgo. + + Copyright 2011 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 "runtime.h" +#include "go-alloc.h" +#include "interface.h" +#include "go-panic.h" + +/* 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 + though it were making a system call. Otherwise the program can + lock up if the C code goes to sleep on a mutex or for some other + reason. This idea is to call this function, then immediately call + the C/C++ function. After the C/C++ function returns, call + syscall_cgocalldone. The usual Go code would look like + + syscall.Cgocall() + defer syscall.Cgocalldone() + cfunction() + + */ + +/* We let Go code call these via the syscall package. */ +void syscall_cgocall(void) __asm__ (GOSYM_PREFIX "syscall.Cgocall"); +void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallDone"); +void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBack"); +void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBackDone"); + +void +syscall_cgocall () +{ + M* m; + G* g; + + if (runtime_needextram && runtime_cas (&runtime_needextram, 1, 0)) + runtime_newextram (); + + m = runtime_m (); + ++m->ncgocall; + g = runtime_g (); + ++g->ncgo; + runtime_entersyscall (); +} + +/* Prepare to return to Go code from C/C++ code. */ + +void +syscall_cgocalldone () +{ + G* g; + + g = runtime_g (); + __go_assert (g != NULL); + --g->ncgo; + if (g->ncgo == 0) + { + /* We are going back to Go, and we are not in a recursive call. + Let the garbage collector clean up any unreferenced + memory. */ + g->cgomal = NULL; + } + + /* If we are invoked because the C function called _cgo_panic, then + _cgo_panic will already have exited syscall mode. */ + if (g->status == Gsyscall) + runtime_exitsyscall (); +} + +/* Call back from C/C++ code to Go code. */ + +void +syscall_cgocallback () +{ + M *mp; + + mp = runtime_m (); + if (mp == NULL) + { + runtime_needm (); + mp = runtime_m (); + mp->dropextram = true; + } + + runtime_exitsyscall (); + + mp = runtime_m (); + if (mp->needextram) + { + mp->needextram = 0; + runtime_newextram (); + } +} + +/* Prepare to return to C/C++ code from a callback to Go code. */ + +void +syscall_cgocallbackdone () +{ + M *mp; + + runtime_entersyscall (); + mp = runtime_m (); + if (mp->dropextram && runtime_g ()->ncgo == 0) + { + mp->dropextram = false; + runtime_dropm (); + } +} + +/* Allocate memory and save it in a list visible to the Go garbage + collector. */ + +void * +alloc_saved (size_t n) +{ + void *ret; + G *g; + CgoMal *c; + + ret = __go_alloc (n); + + g = runtime_g (); + c = (CgoMal *) __go_alloc (sizeof (CgoMal)); + c->next = g->cgomal; + c->alloc = ret; + g->cgomal = c; + + return ret; +} + +/* These are routines used by SWIG. The gc runtime library provides + the same routines under the same name, though in that case the code + is required to import runtime/cgo. */ + +void * +_cgo_allocate (size_t n) +{ + void *ret; + + runtime_exitsyscall (); + ret = alloc_saved (n); + runtime_entersyscall (); + return ret; +} + +extern const struct __go_type_descriptor string_type_descriptor + __asm__ (GOSYM_PREFIX "__go_tdn_string"); + +void +_cgo_panic (const char *p) +{ + intgo len; + unsigned char *data; + String *ps; + struct __go_empty_interface e; + + runtime_exitsyscall (); + len = __builtin_strlen (p); + data = alloc_saved (len); + __builtin_memcpy (data, p, len); + ps = alloc_saved (sizeof *ps); + ps->str = data; + ps->len = len; + e.__type_descriptor = &string_type_descriptor; + e.__object = ps; + + /* We don't call runtime_entersyscall here, because normally what + will happen is that we will walk up the stack to a Go deferred + function that calls recover. However, this will do the wrong + thing if this panic is recovered and the stack unwinding is + caught by a C++ exception handler. It might be possible to + handle this by calling runtime_entersyscall in the personality + function in go-unwind.c. FIXME. */ + + __go_panic (e); +} + +/* Return the number of CGO calls. */ + +int64 runtime_NumCgoCall (void) __asm__ (GOSYM_PREFIX "runtime.NumCgoCall"); + +int64 +runtime_NumCgoCall (void) +{ + int64 ret; + M* m; + + ret = 0; + for (m = runtime_atomicloadp (&runtime_allm); m != NULL; m = m->alllink) + ret += m->ncgocall; + return ret; +} |