LEFT | RIGHT |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 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 "malloc.h" | 8 #include "malloc.h" |
| 9 #include "../../cmd/ld/textflag.h" |
9 | 10 |
10 // Code related to defer, panic and recover. | 11 // Code related to defer, panic and recover. |
11 | 12 |
12 uint32 runtime·panicking; | 13 uint32 runtime·panicking; |
13 static Lock paniclk; | 14 static Lock paniclk; |
14 | 15 |
15 enum | 16 enum |
16 { | 17 { |
17 DeferChunkSize = 2048 | 18 DeferChunkSize = 2048 |
18 }; | 19 }; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 runtime·memclr((byte*)d, total); | 116 runtime·memclr((byte*)d, total); |
116 } | 117 } |
117 } | 118 } |
118 | 119 |
119 // Create a new deferred function fn with siz bytes of arguments. | 120 // Create a new deferred function fn with siz bytes of arguments. |
120 // The compiler turns a defer statement into a call to this. | 121 // The compiler turns a defer statement into a call to this. |
121 // Cannot split the stack because it assumes that the arguments | 122 // Cannot split the stack because it assumes that the arguments |
122 // are available sequentially after &fn; they would not be | 123 // are available sequentially after &fn; they would not be |
123 // copied if a stack split occurred. It's OK for this to call | 124 // copied if a stack split occurred. It's OK for this to call |
124 // functions that split the stack. | 125 // functions that split the stack. |
125 #pragma textflag 7 | 126 #pragma textflag NOSPLIT |
126 uintptr | 127 uintptr |
127 runtime·deferproc(int32 siz, FuncVal *fn, ...) | 128 runtime·deferproc(int32 siz, FuncVal *fn, ...) |
128 { | 129 { |
129 Defer *d; | 130 Defer *d; |
130 | 131 |
131 d = newdefer(siz); | 132 d = newdefer(siz); |
132 d->fn = fn; | 133 d->fn = fn; |
133 d->pc = runtime·getcallerpc(&siz); | 134 d->pc = runtime·getcallerpc(&siz); |
134 if(thechar == '5') | 135 if(thechar == '5') |
135 d->argp = (byte*)(&fn+2); // skip caller's saved link register | 136 d->argp = (byte*)(&fn+2); // skip caller's saved link register |
(...skipping 18 matching lines...) Expand all Loading... |
154 // to have been called by the caller of deferreturn at the point | 155 // to have been called by the caller of deferreturn at the point |
155 // just before deferreturn was called. The effect is that deferreturn | 156 // just before deferreturn was called. The effect is that deferreturn |
156 // is called again and again until there are no more deferred functions. | 157 // is called again and again until there are no more deferred functions. |
157 // Cannot split the stack because we reuse the caller's frame to | 158 // Cannot split the stack because we reuse the caller's frame to |
158 // call the deferred function. | 159 // call the deferred function. |
159 // | 160 // |
160 // The ... in the prototype keeps the compiler from declaring | 161 // The ... in the prototype keeps the compiler from declaring |
161 // an argument frame size. deferreturn is a very special function, | 162 // an argument frame size. deferreturn is a very special function, |
162 // and if the runtime ever asks for its frame size, that means | 163 // and if the runtime ever asks for its frame size, that means |
163 // the traceback routines are probably broken. | 164 // the traceback routines are probably broken. |
164 #pragma textflag 7 | 165 #pragma textflag NOSPLIT |
165 void | 166 void |
166 runtime·deferreturn(uintptr arg0, ...) | 167 runtime·deferreturn(uintptr arg0, ...) |
167 { | 168 { |
168 Defer *d; | 169 Defer *d; |
169 byte *argp; | 170 byte *argp; |
170 FuncVal *fn; | 171 FuncVal *fn; |
171 | 172 |
172 d = g->defer; | 173 d = g->defer; |
173 if(d == nil) | 174 if(d == nil) |
174 return; | 175 return; |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 | 328 |
328 if(sp != nil && (sp < (byte*)gp->stackguard - StackGuard || (byte*)gp->s
tackbase < sp)) { | 329 if(sp != nil && (sp < (byte*)gp->stackguard - StackGuard || (byte*)gp->s
tackbase < sp)) { |
329 runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackgua
rd - StackGuard, gp->stackbase); | 330 runtime·printf("recover: %p not in [%p, %p]\n", sp, gp->stackgua
rd - StackGuard, gp->stackbase); |
330 runtime·throw("bad unwindstack"); | 331 runtime·throw("bad unwindstack"); |
331 } | 332 } |
332 } | 333 } |
333 | 334 |
334 // The implementation of the predeclared function recover. | 335 // The implementation of the predeclared function recover. |
335 // Cannot split the stack because it needs to reliably | 336 // Cannot split the stack because it needs to reliably |
336 // find the stack segment of its caller. | 337 // find the stack segment of its caller. |
337 #pragma textflag 7 | 338 #pragma textflag NOSPLIT |
338 void | 339 void |
339 runtime·recover(byte *argp, Eface ret) | 340 runtime·recover(byte *argp, Eface ret) |
340 { | 341 { |
341 Stktop *top, *oldtop; | 342 Stktop *top, *oldtop; |
342 Panic *p; | 343 Panic *p; |
343 | 344 |
344 // Must be a panic going on. | 345 // Must be a panic going on. |
345 if((p = g->panic) == nil || p->recovered) | 346 if((p = g->panic) == nil || p->recovered) |
346 goto nomatch; | 347 goto nomatch; |
347 | 348 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 m->mcache = runtime·allocmcache(); | 415 m->mcache = runtime·allocmcache(); |
415 if(m->dying) { | 416 if(m->dying) { |
416 runtime·printf("panic during panic\n"); | 417 runtime·printf("panic during panic\n"); |
417 runtime·exit(3); | 418 runtime·exit(3); |
418 } | 419 } |
419 m->dying = 1; | 420 m->dying = 1; |
420 if(g != nil) | 421 if(g != nil) |
421 g->writebuf = nil; | 422 g->writebuf = nil; |
422 runtime·xadd(&runtime·panicking, 1); | 423 runtime·xadd(&runtime·panicking, 1); |
423 runtime·lock(&paniclk); | 424 runtime·lock(&paniclk); |
| 425 if(runtime·debug.schedtrace > 0 || runtime·debug.scheddetail > 0) |
| 426 runtime·schedtrace(true); |
424 runtime·freezetheworld(); | 427 runtime·freezetheworld(); |
425 } | 428 } |
426 | 429 |
427 void | 430 void |
428 runtime·dopanic(int32 unused) | 431 runtime·dopanic(int32 unused) |
429 { | 432 { |
430 static bool didothers; | 433 static bool didothers; |
431 bool crash; | 434 bool crash; |
432 int32 t; | 435 int32 t; |
433 | 436 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err); | 519 runtime·newErrorString(runtime·gostringnocopy((byte*)s), &err); |
517 runtime·panic(err); | 520 runtime·panic(err); |
518 } | 521 } |
519 | 522 |
520 void | 523 void |
521 runtime·Goexit(void) | 524 runtime·Goexit(void) |
522 { | 525 { |
523 rundefer(); | 526 rundefer(); |
524 runtime·goexit(); | 527 runtime·goexit(); |
525 } | 528 } |
LEFT | RIGHT |