OLD | NEW |
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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 if(fn == 0) | 105 if(fn == 0) |
106 runtime·throw("cgocall nil"); | 106 runtime·throw("cgocall nil"); |
107 | 107 |
108 if(raceenabled) | 108 if(raceenabled) |
109 runtime·racereleasemerge(&cgosync); | 109 runtime·racereleasemerge(&cgosync); |
110 | 110 |
111 // Create an extra M for callbacks on threads not created by Go on first
cgo call. | 111 // 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)) | 112 if(runtime·needextram && runtime·cas(&runtime·needextram, 1, 0)) |
113 runtime·newextram(); | 113 runtime·newextram(); |
114 | 114 |
115 » m->ncgocall++; | 115 » g->m->ncgocall++; |
116 | 116 |
117 /* | 117 /* |
118 * Lock g to m to ensure we stay on the same stack if we do a | 118 * 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. | 119 * cgo callback. Add entry to defer stack in case of panic. |
120 */ | 120 */ |
121 runtime·lockOSThread(); | 121 runtime·lockOSThread(); |
122 d.fn = &endcgoV; | 122 d.fn = &endcgoV; |
123 d.siz = 0; | 123 d.siz = 0; |
124 d.link = g->defer; | 124 d.link = g->defer; |
125 d.argp = NoArgs; | 125 d.argp = NoArgs; |
126 d.special = true; | 126 d.special = true; |
127 g->defer = &d; | 127 g->defer = &d; |
128 ········ | 128 ········ |
129 » m->ncgo++; | 129 » g->m->ncgo++; |
130 | 130 |
131 /* | 131 /* |
132 * Announce we are entering a system call | 132 * Announce we are entering a system call |
133 * so that the scheduler knows to create another | 133 * so that the scheduler knows to create another |
134 * M to run goroutines while we are in the | 134 * M to run goroutines while we are in the |
135 * foreign code. | 135 * foreign code. |
136 * | 136 * |
137 * The call to asmcgocall is guaranteed not to | 137 * The call to asmcgocall is guaranteed not to |
138 * split the stack and does not allocate memory, | 138 * split the stack and does not allocate memory, |
139 * so it is safe to call while "in a system call", outside | 139 * so it is safe to call while "in a system call", outside |
140 * the $GOMAXPROCS accounting. | 140 * the $GOMAXPROCS accounting. |
141 */ | 141 */ |
142 runtime·entersyscall(); | 142 runtime·entersyscall(); |
143 runtime·asmcgocall(fn, arg); | 143 runtime·asmcgocall(fn, arg); |
144 runtime·exitsyscall(); | 144 runtime·exitsyscall(); |
145 | 145 |
146 if(g->defer != &d || d.fn != &endcgoV) | 146 if(g->defer != &d || d.fn != &endcgoV) |
147 runtime·throw("runtime: bad defer entry in cgocallback"); | 147 runtime·throw("runtime: bad defer entry in cgocallback"); |
148 g->defer = d.link; | 148 g->defer = d.link; |
149 endcgo(); | 149 endcgo(); |
150 } | 150 } |
151 | 151 |
152 static void | 152 static void |
153 endcgo(void) | 153 endcgo(void) |
154 { | 154 { |
155 runtime·unlockOSThread(); | 155 runtime·unlockOSThread(); |
156 » m->ncgo--; | 156 » g->m->ncgo--; |
157 » if(m->ncgo == 0) { | 157 » if(g->m->ncgo == 0) { |
158 // We are going back to Go and are not in a recursive | 158 // We are going back to Go and are not in a recursive |
159 // call. Let the GC collect any memory allocated via | 159 // call. Let the GC collect any memory allocated via |
160 // _cgo_allocate that is no longer referenced. | 160 // _cgo_allocate that is no longer referenced. |
161 » » m->cgomal = nil; | 161 » » g->m->cgomal = nil; |
162 } | 162 } |
163 | 163 |
164 if(raceenabled) | 164 if(raceenabled) |
165 runtime·raceacquire(&cgosync); | 165 runtime·raceacquire(&cgosync); |
166 } | 166 } |
167 | 167 |
168 // Helper functions for cgo code. | 168 // Helper functions for cgo code. |
169 | 169 |
170 void (*_cgo_malloc)(void*); | 170 void (*_cgo_malloc)(void*); |
171 void (*_cgo_free)(void*); | 171 void (*_cgo_free)(void*); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 void *arg; | 203 void *arg; |
204 uintptr argsize; | 204 uintptr argsize; |
205 }; | 205 }; |
206 | 206 |
207 // Location of callback arguments depends on stack frame layout | 207 // Location of callback arguments depends on stack frame layout |
208 // and size of stack frame of cgocallback_gofunc. | 208 // and size of stack frame of cgocallback_gofunc. |
209 | 209 |
210 // On arm, stack frame is two words and there's a saved LR between | 210 // On arm, stack frame is two words and there's a saved LR between |
211 // SP and the stack frame and between the stack frame and the arguments. | 211 // SP and the stack frame and between the stack frame and the arguments. |
212 #ifdef GOARCH_arm | 212 #ifdef GOARCH_arm |
213 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) | 213 #define CBARGS (CallbackArgs*)((byte*)g->m->g0->sched.sp+4*sizeof(void*)) |
214 #endif | 214 #endif |
215 | 215 |
216 // On amd64, stack frame is one word, plus caller PC. | 216 // On amd64, stack frame is one word, plus caller PC. |
217 #ifdef GOARCH_amd64 | 217 #ifdef GOARCH_amd64 |
218 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+2*sizeof(void*)) | 218 #define CBARGS (CallbackArgs*)((byte*)g->m->g0->sched.sp+2*sizeof(void*)) |
219 #endif | 219 #endif |
220 | 220 |
221 // Unimplemented on amd64p32 | 221 // Unimplemented on amd64p32 |
222 #ifdef GOARCH_amd64p32 | 222 #ifdef GOARCH_amd64p32 |
223 #define CBARGS (CallbackArgs*)(nil) | 223 #define CBARGS (CallbackArgs*)(nil) |
224 #endif | 224 #endif |
225 | 225 |
226 // On 386, stack frame is three words, plus caller PC. | 226 // On 386, stack frame is three words, plus caller PC. |
227 #ifdef GOARCH_386 | 227 #ifdef GOARCH_386 |
228 #define CBARGS (CallbackArgs*)((byte*)m->g0->sched.sp+4*sizeof(void*)) | 228 #define CBARGS (CallbackArgs*)((byte*)g->m->g0->sched.sp+4*sizeof(void*)) |
229 #endif | 229 #endif |
230 | 230 |
231 void runtime·cgocallbackg1(void); | 231 void runtime·cgocallbackg1(void); |
232 | 232 |
233 #pragma textflag NOSPLIT | 233 #pragma textflag NOSPLIT |
234 void | 234 void |
235 runtime·cgocallbackg(void) | 235 runtime·cgocallbackg(void) |
236 { | 236 { |
237 » if(g != m->curg) { | 237 » if(g != g->m->curg) { |
238 runtime·prints("runtime: bad g in cgocallback"); | 238 runtime·prints("runtime: bad g in cgocallback"); |
239 runtime·exit(2); | 239 runtime·exit(2); |
240 } | 240 } |
241 | 241 |
242 runtime·exitsyscall(); // coming out of cgo call | 242 runtime·exitsyscall(); // coming out of cgo call |
243 runtime·cgocallbackg1(); | 243 runtime·cgocallbackg1(); |
244 runtime·entersyscall(); // going back to cgo call | 244 runtime·entersyscall(); // going back to cgo call |
245 } | 245 } |
246 | 246 |
247 void | 247 void |
248 runtime·cgocallbackg1(void) | 248 runtime·cgocallbackg1(void) |
249 { | 249 { |
250 CallbackArgs *cb; | 250 CallbackArgs *cb; |
251 Defer d; | 251 Defer d; |
252 | 252 |
253 » if(m->needextram) { | 253 » if(g->m->needextram) { |
254 » » m->needextram = 0; | 254 » » g->m->needextram = 0; |
255 runtime·newextram(); | 255 runtime·newextram(); |
256 } | 256 } |
257 | 257 |
258 // Add entry to defer stack in case of panic. | 258 // Add entry to defer stack in case of panic. |
259 d.fn = &unwindmf; | 259 d.fn = &unwindmf; |
260 d.siz = 0; | 260 d.siz = 0; |
261 d.link = g->defer; | 261 d.link = g->defer; |
262 d.argp = NoArgs; | 262 d.argp = NoArgs; |
263 d.special = true; | 263 d.special = true; |
264 g->defer = &d; | 264 g->defer = &d; |
(...skipping 19 matching lines...) Expand all Loading... |
284 static void | 284 static void |
285 unwindm(void) | 285 unwindm(void) |
286 { | 286 { |
287 // Restore sp saved by cgocallback during | 287 // Restore sp saved by cgocallback during |
288 // unwind of g's stack (see comment at top of file). | 288 // unwind of g's stack (see comment at top of file). |
289 switch(thechar){ | 289 switch(thechar){ |
290 default: | 290 default: |
291 runtime·throw("runtime: unwindm not implemented"); | 291 runtime·throw("runtime: unwindm not implemented"); |
292 case '8': | 292 case '8': |
293 case '6': | 293 case '6': |
294 » » m->g0->sched.sp = *(uintptr*)m->g0->sched.sp; | 294 » » g->m->g0->sched.sp = *(uintptr*)g->m->g0->sched.sp; |
295 break; | 295 break; |
296 case '5': | 296 case '5': |
297 » » m->g0->sched.sp = *(uintptr*)((byte*)m->g0->sched.sp + 4); | 297 » » g->m->g0->sched.sp = *(uintptr*)((byte*)g->m->g0->sched.sp + 4); |
298 break; | 298 break; |
299 } | 299 } |
300 } | 300 } |
301 | 301 |
302 void | 302 void |
303 runtime·badcgocallback(void) // called from assembly | 303 runtime·badcgocallback(void) // called from assembly |
304 { | 304 { |
305 runtime·throw("runtime: misaligned stack in cgocallback"); | 305 runtime·throw("runtime: misaligned stack in cgocallback"); |
306 } | 306 } |
307 | 307 |
308 void | 308 void |
309 runtime·cgounimpl(void) // called from (incomplete) assembly | 309 runtime·cgounimpl(void) // called from (incomplete) assembly |
310 { | 310 { |
311 runtime·throw("runtime: cgo not implemented"); | 311 runtime·throw("runtime: cgo not implemented"); |
312 } | 312 } |
313 | 313 |
314 // For cgo-using programs with external linking, | 314 // For cgo-using programs with external linking, |
315 // export "main" (defined in assembly) so that libc can handle basic | 315 // export "main" (defined in assembly) so that libc can handle basic |
316 // C runtime startup and call the Go program as if it were | 316 // C runtime startup and call the Go program as if it were |
317 // the C main function. | 317 // the C main function. |
318 #pragma cgo_export_static main | 318 #pragma cgo_export_static main |
OLD | NEW |