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. */
13 extern void __go_receive (ChanType
*, Hchan
*, byte
*);
15 /* Prepare to call from code written in Go to code written in C or
16 C++. This takes the current goroutine out of the Go scheduler, as
17 though it were making a system call. Otherwise the program can
18 lock up if the C code goes to sleep on a mutex or for some other
19 reason. This idea is to call this function, then immediately call
20 the C/C++ function. After the C/C++ function returns, call
21 syscall_cgocalldone. The usual Go code would look like
24 defer syscall.Cgocalldone()
29 /* We let Go code call these via the syscall package. */
30 void syscall_cgocall(void) __asm__ (GOSYM_PREFIX
"syscall.Cgocall");
31 void syscall_cgocalldone(void) __asm__ (GOSYM_PREFIX
"syscall.CgocallDone");
32 void syscall_cgocallback(void) __asm__ (GOSYM_PREFIX
"syscall.CgocallBack");
33 void syscall_cgocallbackdone(void) __asm__ (GOSYM_PREFIX
"syscall.CgocallBackDone");
41 if (runtime_needextram
&& runtime_cas (&runtime_needextram
, 1, 0))
48 runtime_entersyscall ();
51 /* Prepare to return to Go code from C/C++ code. */
54 syscall_cgocalldone ()
59 __go_assert (g
!= NULL
);
63 /* We are going back to Go, and we are not in a recursive call.
64 Let the garbage collector clean up any unreferenced
69 /* If we are invoked because the C function called _cgo_panic, then
70 _cgo_panic will already have exited syscall mode. */
71 if (g
->status
== Gsyscall
)
72 runtime_exitsyscall ();
75 /* Call back from C/C++ code to Go code. */
78 syscall_cgocallback ()
87 mp
->dropextram
= true;
90 runtime_exitsyscall ();
92 if (runtime_g ()->ncgo
== 0)
94 /* The C call to Go came from a thread not currently running any
95 Go. In the case of -buildmode=c-archive or c-shared, this
96 call may be coming in before package initialization is
97 complete. Wait until it is. */
98 __go_receive (NULL
, runtime_main_init_done
, NULL
);
105 runtime_newextram ();
109 /* Prepare to return to C/C++ code from a callback to Go code. */
112 syscall_cgocallbackdone ()
116 runtime_entersyscall ();
118 if (mp
->dropextram
&& runtime_g ()->ncgo
== 0)
120 mp
->dropextram
= false;
125 /* Allocate memory and save it in a list visible to the Go garbage
129 alloc_saved (size_t n
)
135 ret
= __go_alloc (n
);
138 c
= (CgoMal
*) __go_alloc (sizeof (CgoMal
));
146 /* These are routines used by SWIG. The gc runtime library provides
147 the same routines under the same name, though in that case the code
148 is required to import runtime/cgo. */
151 _cgo_allocate (size_t n
)
155 runtime_exitsyscall ();
156 ret
= alloc_saved (n
);
157 runtime_entersyscall ();
161 extern const struct __go_type_descriptor string_type_descriptor
162 __asm__ (GOSYM_PREFIX
"__go_tdn_string");
165 _cgo_panic (const char *p
)
170 struct __go_empty_interface e
;
172 runtime_exitsyscall ();
173 len
= __builtin_strlen (p
);
174 data
= alloc_saved (len
);
175 __builtin_memcpy (data
, p
, len
);
176 ps
= alloc_saved (sizeof *ps
);
179 e
.__type_descriptor
= &string_type_descriptor
;
182 /* We don't call runtime_entersyscall here, because normally what
183 will happen is that we will walk up the stack to a Go deferred
184 function that calls recover. However, this will do the wrong
185 thing if this panic is recovered and the stack unwinding is
186 caught by a C++ exception handler. It might be possible to
187 handle this by calling runtime_entersyscall in the personality
188 function in go-unwind.c. FIXME. */
193 /* Used for _cgo_wait_runtime_init_done. This is based on code in
194 runtime/cgo/gcc_libinit.c in the master library. */
196 static pthread_cond_t runtime_init_cond
= PTHREAD_COND_INITIALIZER
;
197 static pthread_mutex_t runtime_init_mu
= PTHREAD_MUTEX_INITIALIZER
;
198 static _Bool runtime_init_done
;
200 /* This is called by exported cgo functions to ensure that the runtime
201 has been initialized before we enter the function. This is needed
202 when building with -buildmode=c-archive or similar. */
205 _cgo_wait_runtime_init_done (void)
209 if (__atomic_load_n (&runtime_init_done
, __ATOMIC_ACQUIRE
))
212 err
= pthread_mutex_lock (&runtime_init_mu
);
215 while (!__atomic_load_n (&runtime_init_done
, __ATOMIC_ACQUIRE
))
217 err
= pthread_cond_wait (&runtime_init_cond
, &runtime_init_mu
);
221 err
= pthread_mutex_unlock (&runtime_init_mu
);
226 /* This is called by runtime_main after the Go runtime is
230 _cgo_notify_runtime_init_done (void)
234 err
= pthread_mutex_lock (&runtime_init_mu
);
237 __atomic_store_n (&runtime_init_done
, 1, __ATOMIC_RELEASE
);
238 err
= pthread_cond_broadcast (&runtime_init_cond
);
241 err
= pthread_mutex_unlock (&runtime_init_mu
);
246 // runtime_iscgo is set to true if some cgo code is linked in.
247 // This is done by a constructor in the cgo generated code.
250 // runtime_cgoHasExtraM is set on startup when an extra M is created
251 // for cgo. The extra M must be created before any C/C++ code calls
253 _Bool runtime_cgoHasExtraM
;