LEFT | RIGHT |
(no file at all) | |
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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 SEHUnwind sehunwind; |
102 | |
103 if(m->racecall) { | |
104 runtime·asmcgocall(fn, arg); | |
105 return; | |
106 } | |
107 | 102 |
108 if(!runtime·iscgo && !Solaris && !Windows) | 103 if(!runtime·iscgo && !Solaris && !Windows) |
109 runtime·throw("cgocall unavailable"); | 104 runtime·throw("cgocall unavailable"); |
110 | 105 |
111 if(fn == 0) | 106 if(fn == 0) |
112 runtime·throw("cgocall nil"); | 107 runtime·throw("cgocall nil"); |
113 | 108 |
114 if(raceenabled) | 109 if(raceenabled) |
115 runtime·racereleasemerge(&cgosync); | 110 runtime·racereleasemerge(&cgosync); |
116 | 111 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 | 244 |
250 #pragma textflag NOSPLIT | 245 #pragma textflag NOSPLIT |
251 void | 246 void |
252 runtime·cgocallbackg(void) | 247 runtime·cgocallbackg(void) |
253 { | 248 { |
254 if(g != m->curg) { | 249 if(g != m->curg) { |
255 runtime·prints("runtime: bad g in cgocallback"); | 250 runtime·prints("runtime: bad g in cgocallback"); |
256 runtime·exit(2); | 251 runtime·exit(2); |
257 } | 252 } |
258 | 253 |
259 » if(m->racecall) { | 254 » runtime·exitsyscall();» // coming out of cgo call |
260 » » // We were not in syscall, so no need to call runtime·exitsyscal
l. | 255 » runtime·cgocallbackg1(); |
261 » » // However we must set m->locks for the following reason. | 256 » runtime·entersyscall();»// going back to cgo call |
262 » » // Race detector runtime makes __tsan_symbolize cgo callback | |
263 » » // holding internal mutexes. The mutexes are not cooperative wit
h Go scheduler. | |
264 » » // So if we deschedule a goroutine that holds race detector inte
rnal mutex | |
265 » » // (e.g. preempt it), another goroutine will deadlock trying to
acquire the same mutex. | |
266 » » m->locks++; | |
267 » » runtime·cgocallbackg1(); | |
268 » » m->locks--; | |
269 » } else { | |
270 » » runtime·exitsyscall();» // coming out of cgo call | |
271 » » runtime·cgocallbackg1(); | |
272 » » runtime·entersyscall();»// going back to cgo call | |
273 » } | |
274 } | 257 } |
275 | 258 |
276 void | 259 void |
277 runtime·cgocallbackg1(void) | 260 runtime·cgocallbackg1(void) |
278 { | 261 { |
279 CallbackArgs *cb; | 262 CallbackArgs *cb; |
280 Defer d; | 263 Defer d; |
281 | 264 |
282 if(m->needextram) { | 265 if(m->needextram) { |
283 m->needextram = 0; | 266 m->needextram = 0; |
284 runtime·newextram(); | 267 runtime·newextram(); |
285 } | 268 } |
286 | 269 |
287 // Add entry to defer stack in case of panic. | 270 // Add entry to defer stack in case of panic. |
288 d.fn = &unwindmf; | 271 d.fn = &unwindmf; |
289 d.siz = 0; | 272 d.siz = 0; |
290 d.link = g->defer; | 273 d.link = g->defer; |
291 d.argp = (void*)-1; // unused because unwindm never recovers | 274 d.argp = (void*)-1; // unused because unwindm never recovers |
292 d.special = true; | 275 d.special = true; |
293 g->defer = &d; | 276 g->defer = &d; |
294 | 277 |
295 » if(raceenabled && !m->racecall) | 278 » if(raceenabled) |
296 runtime·raceacquire(&cgosync); | 279 runtime·raceacquire(&cgosync); |
297 | 280 |
298 // Invoke callback. | 281 // Invoke callback. |
299 cb = CBARGS; | 282 cb = CBARGS; |
300 runtime·newstackcall(cb->fn, cb->arg, cb->argsize); | 283 runtime·newstackcall(cb->fn, cb->arg, cb->argsize); |
301 | 284 |
302 » if(raceenabled && !m->racecall) | 285 » if(raceenabled) |
303 runtime·racereleasemerge(&cgosync); | 286 runtime·racereleasemerge(&cgosync); |
304 | 287 |
305 // Pop defer. | 288 // Pop defer. |
306 // Do not unwind m->g0->sched.sp. | 289 // Do not unwind m->g0->sched.sp. |
307 // Our caller, cgocallback, will do that. | 290 // Our caller, cgocallback, will do that. |
308 if(g->defer != &d || d.fn != &unwindmf) | 291 if(g->defer != &d || d.fn != &unwindmf) |
309 runtime·throw("runtime: bad defer entry in cgocallback"); | 292 runtime·throw("runtime: bad defer entry in cgocallback"); |
310 g->defer = d.link; | 293 g->defer = d.link; |
311 } | 294 } |
312 | 295 |
(...skipping 25 matching lines...) Expand all Loading... |
338 runtime·cgounimpl(void) // called from (incomplete) assembly | 321 runtime·cgounimpl(void) // called from (incomplete) assembly |
339 { | 322 { |
340 runtime·throw("runtime: cgo not implemented"); | 323 runtime·throw("runtime: cgo not implemented"); |
341 } | 324 } |
342 | 325 |
343 // For cgo-using programs with external linking, | 326 // For cgo-using programs with external linking, |
344 // export "main" (defined in assembly) so that libc can handle basic | 327 // export "main" (defined in assembly) so that libc can handle basic |
345 // 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 |
346 // the C main function. | 329 // the C main function. |
347 #pragma cgo_export_static main | 330 #pragma cgo_export_static main |
LEFT | RIGHT |