2018-23-01 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / go / runtime / cgo_gccgo.go
blob05be496450057445e43f53e90530e58d656c5323
1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package runtime
7 import (
8 "runtime/internal/atomic"
9 "unsafe"
12 // For historical reasons these functions are called as though they
13 // were in the syscall package.
14 //go:linkname Cgocall syscall.Cgocall
15 //go:linkname CgocallDone syscall.CgocallDone
16 //go:linkname CgocallBack syscall.CgocallBack
17 //go:linkname CgocallBackDone syscall.CgocallBackDone
19 // A routine that may be called by SWIG.
20 //go:linkname _cgo_panic _cgo_panic
22 // iscgo is set to true if the cgo tool sets the C variable runtime_iscgo
23 // to true.
24 var iscgo bool
26 // cgoHasExtraM is set on startup when an extra M is created for cgo.
27 // The extra M must be created before any C/C++ code calls cgocallback.
28 var cgoHasExtraM bool
30 // cgoAlwaysFalse is a boolean value that is always false.
31 // The cgo-generated code says if cgoAlwaysFalse { cgoUse(p) }.
32 // The compiler cannot see that cgoAlwaysFalse is always false,
33 // so it emits the test and keeps the call, giving the desired
34 // escape analysis result. The test is cheaper than the call.
35 var cgoAlwaysFalse bool
37 // Cgocall prepares to call from code written in Go to code written in
38 // C/C++. This takes the current goroutine out of the Go scheduler, as
39 // though it were making a system call. Otherwise the program can
40 // lookup if the C code blocks. The idea is to call this function,
41 // then immediately call the C/C++ function. After the C/C++ function
42 // returns, call cgocalldone. The usual Go code would look like
43 // syscall.Cgocall()
44 // defer syscall.Cgocalldone()
45 // cfunction()
46 func Cgocall() {
47 mp := getg().m
48 mp.ncgocall++
49 mp.ncgo++
50 entersyscall(0)
51 mp.incgo = true
54 // CgocallDone prepares to return to Go code from C/C++ code.
55 func CgocallDone() {
56 gp := getg()
57 if gp == nil {
58 throw("no g in CgocallDone")
60 gp.m.incgo = false
61 gp.m.ncgo--
63 // If we are invoked because the C function called _cgo_panic,
64 // then _cgo_panic will already have exited syscall mode.
65 if readgstatus(gp)&^_Gscan == _Gsyscall {
66 exitsyscall(0)
70 // CgocallBack is used when calling from C/C++ code into Go code.
71 // The usual approach is
72 // syscall.CgocallBack()
73 // defer syscall.CgocallBackDone()
74 // gofunction()
75 //go:nosplit
76 func CgocallBack() {
77 gp := getg()
78 if gp == nil || gp.m == nil {
79 needm(0)
80 gp = getg()
81 mp := gp.m
82 mp.dropextram = true
85 lockOSThread()
87 exitsyscall(0)
88 gp.m.incgo = false
90 if gp.m.ncgo == 0 {
91 // The C call to Go came from a thread created by C.
92 // The C call to Go came from a thread not currently running
93 // any Go. In the case of -buildmode=c-archive or c-shared,
94 // this call may be coming in before package initialization
95 // is complete. Wait until it is.
96 <-main_init_done
99 mp := gp.m
100 if mp.needextram || atomic.Load(&extraMWaiters) > 0 {
101 mp.needextram = false
102 newextram()
106 // CgocallBackDone prepares to return to C/C++ code that has called
107 // into Go code.
108 func CgocallBackDone() {
109 unlockOSThread()
111 // If we are the top level Go function called from C/C++, then
112 // we need to release the m. But don't release it if we are
113 // panicing; since this is the top level, we are going to
114 // crash the program, and we need the g and m to print the
115 // panic values.
117 // Dropping the m is going to clear g. This function is being
118 // called as a deferred function, so we will return to
119 // deferreturn which will want to clear the _defer field.
120 // As soon as we call dropm another thread may call needm and
121 // start using g, so we must not tamper with the _defer field
122 // after dropm. So clear _defer now.
123 gp := getg()
124 mp := gp.m
125 drop := false
126 if mp.dropextram && mp.ncgo == 0 && gp._panic == nil {
127 d := gp._defer
128 if d == nil || d.link != nil {
129 throw("unexpected g._defer in CgocallBackDone")
131 gp._defer = nil
132 freedefer(d)
133 drop = true
136 gp.m.incgo = true
137 entersyscall(0)
139 if drop {
140 mp.dropextram = false
141 dropm()
145 // _cgo_panic may be called by SWIG code to panic.
146 func _cgo_panic(p *byte) {
147 exitsyscall(0)
148 panic(gostringnocopy(p))
151 // cgo_yield exists in the gc toolchain to let TSAN deliver a signal.
152 // gccgo does not need this.
153 var cgo_yield = &_cgo_yield
154 var _cgo_yield unsafe.Pointer