LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "arch_GOARCH.h" | 6 #include "arch_GOARCH.h" |
7 #include "stack.h" | 7 #include "stack.h" |
8 #include "cgocall.h" | 8 #include "cgocall.h" |
9 #include "race.h" | 9 #include "race.h" |
10 #include "../../cmd/ld/textflag.h" | 10 #include "../../cmd/ld/textflag.h" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 | 91 |
92 // Call from Go to C. | 92 // Call from Go to C. |
93 | 93 |
94 static void endcgo(void); | 94 static void endcgo(void); |
95 static FuncVal endcgoV = { endcgo }; | 95 static FuncVal endcgoV = { endcgo }; |
96 | 96 |
97 void | 97 void |
98 runtime·cgocall(void (*fn)(void*), void *arg) | 98 runtime·cgocall(void (*fn)(void*), void *arg) |
99 { | 99 { |
100 Defer d; | 100 Defer d; |
| 101 SEHUnwind sehunwind; |
101 | 102 |
102 if(!runtime·iscgo && !Solaris && !Windows) | 103 if(!runtime·iscgo && !Solaris && !Windows) |
103 runtime·throw("cgocall unavailable"); | 104 runtime·throw("cgocall unavailable"); |
104 | 105 |
105 if(fn == 0) | 106 if(fn == 0) |
106 runtime·throw("cgocall nil"); | 107 runtime·throw("cgocall nil"); |
107 | 108 |
108 if(raceenabled) | 109 if(raceenabled) |
109 runtime·racereleasemerge(&cgosync); | 110 runtime·racereleasemerge(&cgosync); |
110 | 111 |
111 // Create an extra M for callbacks on threads not created by Go on first
cgo call. | 112 // Create an extra M for callbacks on threads not created by Go on first
cgo call. |
112 if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0)) | 113 if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0)) |
113 runtime·newextram(); | 114 runtime·newextram(); |
114 | 115 |
115 m->ncgocall++; | 116 m->ncgocall++; |
116 | 117 |
117 /* | 118 /* |
118 * Lock g to m to ensure we stay on the same stack if we do a | 119 * Lock g to m to ensure we stay on the same stack if we do a |
119 * cgo callback. Add entry to defer stack in case of panic. | 120 * cgo callback. Add entry to defer stack in case of panic. |
120 */ | 121 */ |
121 runtime·lockOSThread(); | 122 runtime·lockOSThread(); |
122 d.fn = &endcgoV; | 123 d.fn = &endcgoV; |
123 d.siz = 0; | 124 d.siz = 0; |
124 d.link = g->defer; | 125 d.link = g->defer; |
125 d.argp = (void*)-1; // unused because unlockm never recovers | 126 d.argp = (void*)-1; // unused because unlockm never recovers |
126 d.special = true; | 127 d.special = true; |
127 g->defer = &d; | 128 g->defer = &d; |
| 129 ········ |
| 130 // Record current SEH for restoration during endcgo. |
| 131 // This matters most when the execution stops due to panic |
| 132 // and the called C code isn't given a chance to clean up |
| 133 // the SEHs it has pushed. |
| 134 sehunwind.seh = runtime·getseh(); |
| 135 sehunwind.link = m->sehunwind; |
| 136 m->sehunwind = &sehunwind; |
128 | 137 |
129 m->ncgo++; | 138 m->ncgo++; |
130 | 139 |
131 /* | 140 /* |
132 * Announce we are entering a system call | 141 * Announce we are entering a system call |
133 * so that the scheduler knows to create another | 142 * so that the scheduler knows to create another |
134 * M to run goroutines while we are in the | 143 * M to run goroutines while we are in the |
135 * foreign code. | 144 * foreign code. |
136 * | 145 * |
137 * The call to asmcgocall is guaranteed not to | 146 * The call to asmcgocall is guaranteed not to |
(...skipping 16 matching lines...) Expand all Loading... |
154 { | 163 { |
155 runtime·unlockOSThread(); | 164 runtime·unlockOSThread(); |
156 m->ncgo--; | 165 m->ncgo--; |
157 if(m->ncgo == 0) { | 166 if(m->ncgo == 0) { |
158 // We are going back to Go and are not in a recursive | 167 // We are going back to Go and are not in a recursive |
159 // call. Let the GC collect any memory allocated via | 168 // call. Let the GC collect any memory allocated via |
160 // _cgo_allocate that is no longer referenced. | 169 // _cgo_allocate that is no longer referenced. |
161 m->cgomal = nil; | 170 m->cgomal = nil; |
162 } | 171 } |
163 | 172 |
| 173 runtime·setseh(m->sehunwind->seh); |
| 174 m->sehunwind = m->sehunwind->link; |
| 175 |
164 if(raceenabled) | 176 if(raceenabled) |
165 runtime·raceacquire(&cgosync); | 177 runtime·raceacquire(&cgosync); |
166 } | |
167 | |
168 void | |
169 runtime·NumCgoCall(int64 ret) | |
170 { | |
171 M *mp; | |
172 | |
173 ret = 0; | |
174 for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink) | |
175 ret += mp->ncgocall; | |
176 FLUSH(&ret); | |
177 } | 178 } |
178 | 179 |
179 // Helper functions for cgo code. | 180 // Helper functions for cgo code. |
180 | 181 |
181 void (*_cgo_malloc)(void*); | 182 void (*_cgo_malloc)(void*); |
182 void (*_cgo_free)(void*); | 183 void (*_cgo_free)(void*); |
183 | 184 |
184 void* | 185 void* |
185 runtime·cmalloc(uintptr n) | 186 runtime·cmalloc(uintptr n) |
186 { | 187 { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 | 221 |
221 // On arm, stack frame is two words and there's a saved LR between | 222 // On arm, stack frame is two words and there's a saved LR between |
222 // SP and the stack frame and between the stack frame and the arguments. | 223 // SP and the stack frame and between the stack frame and the arguments. |
223 #ifdef GOARCH_arm | 224 #ifdef GOARCH_arm |
224 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) | 225 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) |
225 #endif | 226 #endif |
226 | 227 |
227 // On amd64, stack frame is one word, plus caller PC. | 228 // On amd64, stack frame is one word, plus caller PC. |
228 #ifdef GOARCH_amd64 | 229 #ifdef GOARCH_amd64 |
229 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*)) | 230 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*)) |
| 231 #endif |
| 232 |
| 233 // Unimplemented on amd64p32 |
| 234 #ifdef GOARCH_amd64p32 |
| 235 #define CBARGS (CallbackArgs*)(nil) |
230 #endif | 236 #endif |
231 | 237 |
232 // On 386, stack frame is three words, plus caller PC. | 238 // On 386, stack frame is three words, plus caller PC. |
233 #ifdef GOARCH_386 | 239 #ifdef GOARCH_386 |
234 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) | 240 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) |
235 #endif | 241 #endif |
236 | 242 |
237 void runtime·cgocallbackg1(void); | 243 void runtime·cgocallbackg1(void); |
238 | 244 |
239 #pragma textflag NOSPLIT | 245 #pragma textflag NOSPLIT |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 runtime·cgounimpl(void) // called from (incomplete) assembly | 321 runtime·cgounimpl(void) // called from (incomplete) assembly |
316 { | 322 { |
317 runtime·throw("runtime: cgo not implemented"); | 323 runtime·throw("runtime: cgo not implemented"); |
318 } | 324 } |
319 | 325 |
320 // For cgo-using programs with external linking, | 326 // For cgo-using programs with external linking, |
321 // export "main" (defined in assembly) so that libc can handle basic | 327 // export "main" (defined in assembly) so that libc can handle basic |
322 // C runtime startup and call the Go program as if it were | 328 // C runtime startup and call the Go program as if it were |
323 // the C main function. | 329 // the C main function. |
324 #pragma cgo_export_static main | 330 #pragma cgo_export_static main |
LEFT | RIGHT |