libgo: update to go1.9
[official-gcc.git] / libgo / go / runtime / cgo_gccgo.go
blobc3bf9552ea8736a787d029ec7207b2ea2482d475
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 // Cgocall prepares to call from code written in Go to code written in
31 // C/C++. This takes the current goroutine out of the Go scheduler, as
32 // though it were making a system call. Otherwise the program can
33 // lookup if the C code blocks. The idea is to call this function,
34 // then immediately call the C/C++ function. After the C/C++ function
35 // returns, call cgocalldone. The usual Go code would look like
36 // syscall.Cgocall()
37 // defer syscall.Cgocalldone()
38 // cfunction()
39 func Cgocall() {
40 lockOSThread()
41 mp := getg().m
42 mp.ncgocall++
43 mp.ncgo++
44 mp.incgo = true
45 entersyscall(0)
48 // CgocallDone prepares to return to Go code from C/C++ code.
49 func CgocallDone() {
50 gp := getg()
51 if gp == nil {
52 throw("no g in CgocallDone")
54 gp.m.incgo = false
55 gp.m.ncgo--
57 // If we are invoked because the C function called _cgo_panic,
58 // then _cgo_panic will already have exited syscall mode.
59 if readgstatus(gp)&^_Gscan == _Gsyscall {
60 exitsyscall(0)
63 unlockOSThread()
66 // CgocallBack is used when calling from C/C++ code into Go code.
67 // The usual approach is
68 // syscall.CgocallBack()
69 // defer syscall.CgocallBackDone()
70 // gofunction()
71 //go:nosplit
72 func CgocallBack() {
73 gp := getg()
74 if gp == nil || gp.m == nil {
75 needm(0)
76 gp = getg()
77 mp := gp.m
78 mp.dropextram = true
81 exitsyscall(0)
82 gp.m.incgo = false
84 if gp.m.ncgo == 0 {
85 // The C call to Go came from a thread created by C.
86 // The C call to Go came from a thread not currently running
87 // any Go. In the case of -buildmode=c-archive or c-shared,
88 // this call may be coming in before package initialization
89 // is complete. Wait until it is.
90 <-main_init_done
93 mp := gp.m
94 if mp.needextram || atomic.Load(&extraMWaiters) > 0 {
95 mp.needextram = false
96 newextram()
100 // CgocallBackDone prepares to return to C/C++ code that has called
101 // into Go code.
102 func CgocallBackDone() {
103 // If we are the top level Go function called from C/C++, then
104 // we need to release the m. But don't release it if we are
105 // panicing; since this is the top level, we are going to
106 // crash the program, and we need the g and m to print the
107 // panic values.
109 // Dropping the m is going to clear g. This function is being
110 // called as a deferred function, so we will return to
111 // deferreturn which will want to clear the _defer field.
112 // As soon as we call dropm another thread may call needm and
113 // start using g, so we must not tamper with the _defer field
114 // after dropm. So clear _defer now.
115 gp := getg()
116 mp := gp.m
117 drop := false
118 if mp.dropextram && mp.ncgo == 0 && gp._panic == nil {
119 d := gp._defer
120 if d == nil || d.link != nil {
121 throw("unexpected g._defer in CgocallBackDone")
123 gp._defer = nil
124 freedefer(d)
125 drop = true
128 gp.m.incgo = true
129 entersyscall(0)
131 if drop {
132 mp.dropextram = false
133 dropm()
137 // _cgo_panic may be called by SWIG code to panic.
138 func _cgo_panic(p *byte) {
139 exitsyscall(0)
140 panic(gostringnocopy(p))
143 // cgo_yield exists in the gc toolchain to let TSAN deliver a signal.
144 // gccgo does not need this.
145 var cgo_yield = &_cgo_yield
146 var _cgo_yield unsafe.Pointer