runtime: runtime.Caller should succeed even without debug info.
[gcc.git] / libgo / runtime / go-cgo.c
1 /* go-cgo.c -- SWIG support routines for libgo.
2
3 Copyright 2011 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
6
7 #include "runtime.h"
8 #include "go-alloc.h"
9 #include "interface.h"
10 #include "go-panic.h"
11 #include "go-string.h"
12
13 /* Go memory allocated by code not written in Go. We keep a linked
14 list of these allocations so that the garbage collector can see
15 them. */
16
17 struct cgoalloc
18 {
19 struct cgoalloc *next;
20 void *alloc;
21 };
22
23 /* Prepare to call from code written in Go to code written in C or
24 C++. This takes the current goroutine out of the Go scheduler, as
25 though it were making a system call. Otherwise the program can
26 lock up if the C code goes to sleep on a mutex or for some other
27 reason. This idea is to call this function, then immediately call
28 the C/C++ function. After the C/C++ function returns, call
29 syscall_cgocalldone. The usual Go code would look like
30
31 syscall.Cgocall()
32 defer syscall.Cgocalldone()
33 cfunction()
34
35 */
36
37 /* We let Go code call these via the syscall package. */
38 void syscall_cgocall(void) __asm__ ("syscall.Cgocall");
39 void syscall_cgocalldone(void) __asm__ ("syscall.CgocallDone");
40 void syscall_cgocallback(void) __asm__ ("syscall.CgocallBack");
41 void syscall_cgocallbackdone(void) __asm__ ("syscall.CgocallBackDone");
42
43 void
44 syscall_cgocall ()
45 {
46 M* m;
47 G* g;
48
49 m = runtime_m ();
50 ++m->ncgocall;
51 g = runtime_g ();
52 ++g->ncgo;
53 runtime_entersyscall ();
54 }
55
56 /* Prepare to return to Go code from C/C++ code. */
57
58 void
59 syscall_cgocalldone ()
60 {
61 G* g;
62
63 g = runtime_g ();
64 __go_assert (g != NULL);
65 --g->ncgo;
66 if (g->ncgo == 0)
67 {
68 /* We are going back to Go, and we are not in a recursive call.
69 Let the garbage collector clean up any unreferenced
70 memory. */
71 g->cgoalloc = NULL;
72 }
73
74 /* If we are invoked because the C function called _cgo_panic, then
75 _cgo_panic will already have exited syscall mode. */
76 if (g->status == Gsyscall)
77 runtime_exitsyscall ();
78 }
79
80 /* Call back from C/C++ code to Go code. */
81
82 void
83 syscall_cgocallback ()
84 {
85 runtime_exitsyscall ();
86 }
87
88 /* Prepare to return to C/C++ code from a callback to Go code. */
89
90 void
91 syscall_cgocallbackdone ()
92 {
93 runtime_entersyscall ();
94 }
95
96 /* Allocate memory and save it in a list visible to the Go garbage
97 collector. */
98
99 void *
100 alloc_saved (size_t n)
101 {
102 void *ret;
103 G *g;
104 struct cgoalloc *c;
105
106 ret = __go_alloc (n);
107
108 g = runtime_g ();
109 c = (struct cgoalloc *) __go_alloc (sizeof (struct cgoalloc));
110 c->next = g->cgoalloc;
111 c->alloc = ret;
112 g->cgoalloc = c;
113
114 return ret;
115 }
116
117 /* These are routines used by SWIG. The gc runtime library provides
118 the same routines under the same name, though in that case the code
119 is required to import runtime/cgo. */
120
121 void *
122 _cgo_allocate (size_t n)
123 {
124 void *ret;
125
126 runtime_exitsyscall ();
127 ret = alloc_saved (n);
128 runtime_entersyscall ();
129 return ret;
130 }
131
132 extern const struct __go_type_descriptor string_type_descriptor
133 asm ("__go_tdn_string");
134
135 void
136 _cgo_panic (const char *p)
137 {
138 int len;
139 unsigned char *data;
140 struct __go_string *ps;
141 struct __go_empty_interface e;
142
143 runtime_exitsyscall ();
144 len = __builtin_strlen (p);
145 data = alloc_saved (len);
146 __builtin_memcpy (data, p, len);
147 ps = alloc_saved (sizeof *ps);
148 ps->__data = data;
149 ps->__length = len;
150 e.__type_descriptor = &string_type_descriptor;
151 e.__object = ps;
152
153 /* We don't call runtime_entersyscall here, because normally what
154 will happen is that we will walk up the stack to a Go deferred
155 function that calls recover. However, this will do the wrong
156 thing if this panic is recovered and the stack unwinding is
157 caught by a C++ exception handler. It might be possible to
158 handle this by calling runtime_entersyscall in the personality
159 function in go-unwind.c. FIXME. */
160
161 __go_panic (e);
162 }
163
164 /* Return the number of CGO calls. */
165
166 int64 runtime_NumCgoCall (void) __asm__ ("runtime.NumCgoCall");
167
168 int64
169 runtime_NumCgoCall (void)
170 {
171 int64 ret;
172 M* m;
173
174 ret = 0;
175 for (m = runtime_atomicloadp (&runtime_allm); m != NULL; m = m->alllink)
176 ret += m->ncgocall;
177 return ret;
178 }