[Patch Doc] Update documentation for __fp16 type
[official-gcc.git] / libgo / runtime / go-cgo.c
blob75c180655b0591ced8457a1bbd8084d08b83ab2f
1 /* go-cgo.c -- SWIG support routines for libgo.
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. */
7 #include "runtime.h"
8 #include "go-alloc.h"
9 #include "go-type.h"
11 extern void chanrecv1 (ChanType *, Hchan *, void *)
12 __asm__ (GOSYM_PREFIX "runtime.chanrecv1");
14 /* Prepare to call from code written in Go to code written in C or
15 C++. This takes the current goroutine out of the Go scheduler, as
16 though it were making a system call. Otherwise the program can
17 lock up if the C code goes to sleep on a mutex or for some other
18 reason. This idea is to call this function, then immediately call
19 the C/C++ function. After the C/C++ function returns, call
20 syscall_cgocalldone. The usual Go code would look like
22 syscall.Cgocall()
23 defer syscall.Cgocalldone()
24 cfunction()
28 /* We let Go code call these via the syscall package. */
29 void syscall_cgocall(void) __asm__ (GOSYM_PREFIX "syscall.Cgocall");
30 void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallDone");
31 void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBack");
32 void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX "syscall.CgocallBackDone");
34 void
35 syscall_cgocall ()
37 M* m;
39 if (runtime_needextram && runtime_cas (&runtime_needextram, 1, 0))
40 runtime_newextram ();
42 runtime_lockOSThread();
44 m = runtime_m ();
45 ++m->ncgocall;
46 ++m->ncgo;
47 runtime_entersyscall (0);
50 /* Prepare to return to Go code from C/C++ code. */
52 void
53 syscall_cgocalldone ()
55 G* g;
57 g = runtime_g ();
58 __go_assert (g != NULL);
59 --g->m->ncgo;
60 if (g->m->ncgo == 0)
62 /* We are going back to Go, and we are not in a recursive call.
63 Let the garbage collector clean up any unreferenced
64 memory. */
65 g->m->cgomal = NULL;
68 /* If we are invoked because the C function called _cgo_panic, then
69 _cgo_panic will already have exited syscall mode. */
70 if (g->atomicstatus == _Gsyscall)
71 runtime_exitsyscall (0);
73 runtime_unlockOSThread();
76 /* Call back from C/C++ code to Go code. */
78 void
79 syscall_cgocallback ()
81 M *mp;
83 mp = runtime_m ();
84 if (mp == NULL)
86 runtime_needm ();
87 mp = runtime_m ();
88 mp->dropextram = true;
91 runtime_exitsyscall (0);
93 if (runtime_m ()->ncgo == 0)
95 /* The C call to Go came from a thread not currently running any
96 Go. In the case of -buildmode=c-archive or c-shared, this
97 call may be coming in before package initialization is
98 complete. Wait until it is. */
99 chanrecv1 (NULL, runtime_main_init_done, NULL);
102 mp = runtime_m ();
103 if (mp->needextram)
105 mp->needextram = 0;
106 runtime_newextram ();
110 /* Prepare to return to C/C++ code from a callback to Go code. */
112 void
113 syscall_cgocallbackdone ()
115 M *mp;
117 runtime_entersyscall (0);
118 mp = runtime_m ();
119 if (mp->dropextram && mp->ncgo == 0)
121 mp->dropextram = false;
122 runtime_dropm ();
126 /* Allocate memory and save it in a list visible to the Go garbage
127 collector. */
129 void *
130 alloc_saved (size_t n)
132 void *ret;
133 M *m;
134 CgoMal *c;
136 ret = __go_alloc (n);
138 m = runtime_m ();
139 c = (CgoMal *) __go_alloc (sizeof (CgoMal));
140 c->next = m->cgomal;
141 c->alloc = ret;
142 m->cgomal = c;
144 return ret;
147 /* These are routines used by SWIG. The gc runtime library provides
148 the same routines under the same name, though in that case the code
149 is required to import runtime/cgo. */
151 void *
152 _cgo_allocate (size_t n)
154 void *ret;
156 runtime_exitsyscall (0);
157 ret = alloc_saved (n);
158 runtime_entersyscall (0);
159 return ret;
162 extern const struct __go_type_descriptor string_type_descriptor
163 __asm__ (GOSYM_PREFIX "__go_tdn_string");
165 void
166 _cgo_panic (const char *p)
168 intgo len;
169 unsigned char *data;
170 String *ps;
171 Eface e;
172 const struct __go_type_descriptor *td;
174 runtime_exitsyscall (0);
175 len = __builtin_strlen (p);
176 data = alloc_saved (len);
177 __builtin_memcpy (data, p, len);
178 ps = alloc_saved (sizeof *ps);
179 ps->str = data;
180 ps->len = len;
181 td = &string_type_descriptor;
182 memcpy(&e._type, &td, sizeof td); /* This is a const_cast. */
183 e.data = ps;
185 /* We don't call runtime_entersyscall here, because normally what
186 will happen is that we will walk up the stack to a Go deferred
187 function that calls recover. However, this will do the wrong
188 thing if this panic is recovered and the stack unwinding is
189 caught by a C++ exception handler. It might be possible to
190 handle this by calling runtime_entersyscall in the personality
191 function in go-unwind.c. FIXME. */
193 runtime_panic (e);
196 /* Used for _cgo_wait_runtime_init_done. This is based on code in
197 runtime/cgo/gcc_libinit.c in the master library. */
199 static pthread_cond_t runtime_init_cond = PTHREAD_COND_INITIALIZER;
200 static pthread_mutex_t runtime_init_mu = PTHREAD_MUTEX_INITIALIZER;
201 static _Bool runtime_init_done;
203 /* This is called by exported cgo functions to ensure that the runtime
204 has been initialized before we enter the function. This is needed
205 when building with -buildmode=c-archive or similar. */
207 void
208 _cgo_wait_runtime_init_done (void)
210 int err;
212 if (__atomic_load_n (&runtime_init_done, __ATOMIC_ACQUIRE))
213 return;
215 err = pthread_mutex_lock (&runtime_init_mu);
216 if (err != 0)
217 abort ();
218 while (!__atomic_load_n (&runtime_init_done, __ATOMIC_ACQUIRE))
220 err = pthread_cond_wait (&runtime_init_cond, &runtime_init_mu);
221 if (err != 0)
222 abort ();
224 err = pthread_mutex_unlock (&runtime_init_mu);
225 if (err != 0)
226 abort ();
229 /* This is called by runtime_main after the Go runtime is
230 initialized. */
232 void
233 _cgo_notify_runtime_init_done (void)
235 int err;
237 err = pthread_mutex_lock (&runtime_init_mu);
238 if (err != 0)
239 abort ();
240 __atomic_store_n (&runtime_init_done, 1, __ATOMIC_RELEASE);
241 err = pthread_cond_broadcast (&runtime_init_cond);
242 if (err != 0)
243 abort ();
244 err = pthread_mutex_unlock (&runtime_init_mu);
245 if (err != 0)
246 abort ();
249 // runtime_iscgo is set to true if some cgo code is linked in.
250 // This is done by a constructor in the cgo generated code.
251 _Bool runtime_iscgo;
253 // runtime_cgoHasExtraM is set on startup when an extra M is created
254 // for cgo. The extra M must be created before any C/C++ code calls
255 // cgocallback.
256 _Bool runtime_cgoHasExtraM;