Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(5)

Delta Between Two Patch Sets: src/pkg/runtime/stack.c

Issue 160200044: [dev.power64] code review 160200044: build: merge default into dev.power64 (Closed)
Left Patch Set: Created 10 years, 4 months ago
Right Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/stack.h ('k') | src/pkg/runtime/stack.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 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 "malloc.h" 7 #include "malloc.h"
8 #include "stack.h" 8 #include "stack.h"
9 #include "funcdata.h" 9 #include "funcdata.h"
10 #include "typekind.h" 10 #include "typekind.h"
11 #include "type.h" 11 #include "type.h"
12 #include "race.h" 12 #include "race.h"
13 #include "mgc0.h" 13 #include "mgc0.h"
14 #include "../../cmd/ld/textflag.h" 14 #include "textflag.h"
15 15
16 enum 16 enum
17 { 17 {
18 // StackDebug == 0: no logging 18 // StackDebug == 0: no logging
19 // == 1: logging of per-stack operations 19 // == 1: logging of per-stack operations
20 // == 2: logging of per-frame operations 20 // == 2: logging of per-frame operations
21 // == 3: logging of per-word updates 21 // == 3: logging of per-word updates
22 // == 4: logging of per-word reads 22 // == 4: logging of per-word reads
23 StackDebug = 0, 23 StackDebug = 0,
24 StackFromSystem = 0, // allocate stacks from system memory instead of the heap 24 StackFromSystem = 0, // allocate stacks from system memory instead of the heap
25 StackFaultOnFree = 0, // old stacks are mapped noaccess to detect use after free 25 StackFaultOnFree = 0, // old stacks are mapped noaccess to detect use after free
26 26
27 StackCache = 1, 27 StackCache = 1,
28 ········
29 StackCopyAlways = 0, // expect to be able to copy stacks 100% of the time
28 }; 30 };
29 31
30 // Global pool of spans that have free stacks. 32 // Global pool of spans that have free stacks.
31 // Stacks are assigned an order according to size. 33 // Stacks are assigned an order according to size.
32 // order = log_2(size/FixedStack) 34 // order = log_2(size/FixedStack)
33 // There is a free list for each order. 35 // There is a free list for each order.
34 static MSpan stackpool[NumStackOrders]; 36 static MSpan stackpool[NumStackOrders];
35 static Lock stackpoolmu; 37 static Mutex stackpoolmu;
36 // TODO: one lock per order? 38 // TODO: one lock per order?
37 39
38 void 40 void
39 runtime·stackinit(void) 41 runtime·stackinit(void)
40 { 42 {
41 int32 i; 43 int32 i;
42 44
43 if((StackCacheSize & PageMask) != 0) 45 if((StackCacheSize & PageMask) != 0)
44 runtime·throw("cache size must be a multiple of page size"); 46 runtime·throw("cache size must be a multiple of page size");
45 47
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // Doing so would cause a deadlock (issue 1547). 201 // Doing so would cause a deadlock (issue 1547).
200 if(g != g->m->g0) 202 if(g != g->m->g0)
201 runtime·throw("stackalloc not on scheduler stack"); 203 runtime·throw("stackalloc not on scheduler stack");
202 if((n & (n-1)) != 0) 204 if((n & (n-1)) != 0)
203 runtime·throw("stack size not a power of 2"); 205 runtime·throw("stack size not a power of 2");
204 if(StackDebug >= 1) 206 if(StackDebug >= 1)
205 runtime·printf("stackalloc %d\n", n); 207 runtime·printf("stackalloc %d\n", n);
206 208
207 gp->stacksize += n; 209 gp->stacksize += n;
208 if(runtime·debug.efence || StackFromSystem) { 210 if(runtime·debug.efence || StackFromSystem) {
209 » » v = runtime·SysAlloc(ROUND(n, PageSize), &mstats.stacks_sys); 211 » » v = runtime·sysAlloc(ROUND(n, PageSize), &mstats.stacks_sys);
210 if(v == nil) 212 if(v == nil)
211 runtime·throw("out of memory (stackalloc)"); 213 runtime·throw("out of memory (stackalloc)");
212 return v; 214 return v;
213 } 215 }
214 216
215 // Small stacks are allocated with a fixed-size free-list allocator. 217 // Small stacks are allocated with a fixed-size free-list allocator.
216 // If we need a stack of a bigger size, we fall back on allocating 218 // If we need a stack of a bigger size, we fall back on allocating
217 // a dedicated span. 219 // a dedicated span.
218 if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) { 220 if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
219 order = 0; 221 order = 0;
220 n2 = n; 222 n2 = n;
221 while(n2 > FixedStack) { 223 while(n2 > FixedStack) {
222 order++; 224 order++;
223 n2 >>= 1; 225 n2 >>= 1;
224 } 226 }
225 c = g->m->mcache; 227 c = g->m->mcache;
226 » » if(c == nil) { 228 » » if(c == nil || g->m->gcing || g->m->helpgc) {
227 » » » // This can happen in the guts of exitsyscall or 229 » » » // c == nil can happen in the guts of exitsyscall or
228 // procresize. Just get a stack from the global pool. 230 // procresize. Just get a stack from the global pool.
231 // Also don't touch stackcache during gc
232 // as it's flushed concurrently.
229 runtime·lock(&stackpoolmu); 233 runtime·lock(&stackpoolmu);
230 x = poolalloc(order); 234 x = poolalloc(order);
231 runtime·unlock(&stackpoolmu); 235 runtime·unlock(&stackpoolmu);
232 } else { 236 } else {
233 x = c->stackcache[order].list; 237 x = c->stackcache[order].list;
234 if(x == nil) { 238 if(x == nil) {
235 stackcacherefill(c, order); 239 stackcacherefill(c, order);
236 x = c->stackcache[order].list; 240 x = c->stackcache[order].list;
237 } 241 }
238 c->stackcache[order].list = x->next; 242 c->stackcache[order].list = x->next;
(...skipping 20 matching lines...) Expand all
259 { 263 {
260 uint8 order; 264 uint8 order;
261 uintptr n, n2; 265 uintptr n, n2;
262 MSpan *s; 266 MSpan *s;
263 MLink *x; 267 MLink *x;
264 MCache *c; 268 MCache *c;
265 ········ 269 ········
266 n = (uintptr)(top+1) - (uintptr)v; 270 n = (uintptr)(top+1) - (uintptr)v;
267 if(n & (n-1)) 271 if(n & (n-1))
268 runtime·throw("stack not a power of 2"); 272 runtime·throw("stack not a power of 2");
269 » if(StackDebug >= 1) 273 » if(StackDebug >= 1) {
270 runtime·printf("stackfree %p %d\n", v, (int32)n); 274 runtime·printf("stackfree %p %d\n", v, (int32)n);
275 runtime·memclr(v, n); // for testing, clobber stack data
276 }
271 gp->stacksize -= n; 277 gp->stacksize -= n;
272 if(runtime·debug.efence || StackFromSystem) { 278 if(runtime·debug.efence || StackFromSystem) {
273 if(runtime·debug.efence || StackFaultOnFree) 279 if(runtime·debug.efence || StackFaultOnFree)
274 runtime·SysFault(v, n); 280 runtime·SysFault(v, n);
275 else 281 else
276 runtime·SysFree(v, n, &mstats.stacks_sys); 282 runtime·SysFree(v, n, &mstats.stacks_sys);
277 return; 283 return;
278 } 284 }
279 if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) { 285 if(StackCache && n < FixedStack << NumStackOrders && n < StackCacheSize) {
280 order = 0; 286 order = 0;
281 n2 = n; 287 n2 = n;
282 while(n2 > FixedStack) { 288 while(n2 > FixedStack) {
283 order++; 289 order++;
284 n2 >>= 1; 290 n2 >>= 1;
285 } 291 }
286 x = (MLink*)v; 292 x = (MLink*)v;
287 c = g->m->mcache; 293 c = g->m->mcache;
288 » » if(c == nil) { 294 » » if(c == nil || g->m->gcing || g->m->helpgc) {
289 runtime·lock(&stackpoolmu); 295 runtime·lock(&stackpoolmu);
290 poolfree(x, order); 296 poolfree(x, order);
291 runtime·unlock(&stackpoolmu); 297 runtime·unlock(&stackpoolmu);
292 } else { 298 } else {
293 if(c->stackcache[order].size >= StackCacheSize) 299 if(c->stackcache[order].size >= StackCacheSize)
294 stackcacherelease(c, order); 300 stackcacherelease(c, order);
295 x->next = c->stackcache[order].list; 301 x->next = c->stackcache[order].list;
296 c->stackcache[order].list = x; 302 c->stackcache[order].list = x;
297 c->stackcache[order].size += n; 303 c->stackcache[order].size += n;
298 } 304 }
(...skipping 14 matching lines...) Expand all
313 runtime·oldstack(void) 319 runtime·oldstack(void)
314 { 320 {
315 Stktop *top; 321 Stktop *top;
316 uint32 argsize; 322 uint32 argsize;
317 byte *sp, *old; 323 byte *sp, *old;
318 uintptr *src, *dst, *dstend; 324 uintptr *src, *dst, *dstend;
319 G *gp; 325 G *gp;
320 int64 goid; 326 int64 goid;
321 int32 oldstatus; 327 int32 oldstatus;
322 328
329 if(StackCopyAlways)
330 runtime·throw("unexpected call to oldstack");
331
323 gp = g->m->curg; 332 gp = g->m->curg;
324 top = (Stktop*)gp->stackbase; 333 top = (Stktop*)gp->stackbase;
325 if(top == nil) 334 if(top == nil)
326 runtime·throw("nil stackbase"); 335 runtime·throw("nil stackbase");
327 old = (byte*)gp->stackguard - StackGuard; 336 old = (byte*)gp->stackguard - StackGuard;
328 sp = (byte*)top; 337 sp = (byte*)top;
329 argsize = top->argsize; 338 argsize = top->argsize;
330 339
331 if(StackDebug >= 1) { 340 if(StackDebug >= 1) {
332 runtime·printf("runtime: oldstack gobuf={pc:%p sp:%p lr:%p} cret =%p argsize=%p\n", 341 runtime·printf("runtime: oldstack gobuf={pc:%p sp:%p lr:%p} cret =%p argsize=%p\n",
333 top->gobuf.pc, top->gobuf.sp, top->gobuf.lr, (uintptr)g- >m->cret, (uintptr)argsize); 342 top->gobuf.pc, top->gobuf.sp, top->gobuf.lr, (uintptr)g- >m->cret, (uintptr)argsize);
334 } 343 }
335 344
336 // gp->status is usually Grunning, but it could be Gsyscall if a stack o verflow
337 // happens during a function call inside entersyscall.
338 oldstatus = gp->status;
339 ········
340 gp->sched = top->gobuf; 345 gp->sched = top->gobuf;
341 gp->sched.ret = g->m->cret; 346 gp->sched.ret = g->m->cret;
342 g->m->cret = 0; // drop reference 347 g->m->cret = 0; // drop reference
343 » gp->status = Gwaiting; 348 » // gp->status is usually Grunning, but it could be Gsyscall if a stack o verflow
344 » gp->waitreason = "stack unsplit"; 349 » // happens during a function call inside entersyscall.
350
351 » oldstatus = runtime·readgstatus(gp);
352 » oldstatus &= ~Gscan;
353 » if(oldstatus != Grunning && oldstatus != Gsyscall) {
354 » » runtime·printf("runtime: oldstack status=%d\n", oldstatus);
355 » » runtime·throw("oldstack");
356 » }
357 » runtime·casgstatus(gp, oldstatus, Gcopystack);
358 » gp->waitreason = runtime·gostringnocopy((byte*)"stack unsplit");»·······
345 359
346 if(argsize > 0) { 360 if(argsize > 0) {
347 sp -= argsize; 361 sp -= argsize;
348 dst = (uintptr*)top->argp; 362 dst = (uintptr*)top->argp;
349 dstend = dst + argsize/sizeof(*dst); 363 dstend = dst + argsize/sizeof(*dst);
350 src = (uintptr*)sp; 364 src = (uintptr*)sp;
351 while(dst < dstend) 365 while(dst < dstend)
352 *dst++ = *src++; 366 *dst++ = *src++;
353 } 367 }
354 goid = top->gobuf.g->goid; // fault if g is bad, before gogo 368 goid = top->gobuf.g->goid; // fault if g is bad, before gogo
355 USED(goid); 369 USED(goid);
356 370
357 gp->stackbase = top->stackbase; 371 gp->stackbase = top->stackbase;
358 gp->stackguard = top->stackguard; 372 gp->stackguard = top->stackguard;
359 gp->stackguard0 = gp->stackguard; 373 gp->stackguard0 = gp->stackguard;
360 gp->panicwrap = top->panicwrap;
361 runtime·stackfree(gp, old, top); 374 runtime·stackfree(gp, old, top);
362 375 » runtime·casgstatus(gp, Gcopystack, oldstatus); // oldstatus is Grunning or Gsyscall
363 » gp->status = oldstatus;
364 runtime·gogo(&gp->sched); 376 runtime·gogo(&gp->sched);
365 } 377 }
366 378
367 uintptr runtime·maxstacksize = 1<<20; // enough until runtime.main sets it for r eal 379 uintptr runtime·maxstacksize = 1<<20; // enough until runtime.main sets it for r eal
368 380
369 static uint8* 381 static uint8*
370 mapnames[] = { 382 mapnames[] = {
371 (uint8*)"---", 383 (uint8*)"---",
372 (uint8*)"scalar", 384 (uint8*)"scalar",
373 (uint8*)"ptr", 385 (uint8*)"ptr",
(...skipping 16 matching lines...) Expand all
390 // (arm: TODO) 402 // (arm: TODO)
391 403
392 typedef struct CopyableInfo CopyableInfo; 404 typedef struct CopyableInfo CopyableInfo;
393 struct CopyableInfo { 405 struct CopyableInfo {
394 byte *stk; // bottom address of segment 406 byte *stk; // bottom address of segment
395 byte *base; // top address of segment (including Stktop) 407 byte *base; // top address of segment (including Stktop)
396 int32 frames; // count of copyable frames (-1 = not copyable) 408 int32 frames; // count of copyable frames (-1 = not copyable)
397 }; 409 };
398 410
399 void runtime·main(void); 411 void runtime·main(void);
412 void runtime·switchtoM(void(*)(void));
400 413
401 static bool 414 static bool
402 checkframecopy(Stkframe *frame, void *arg) 415 checkframecopy(Stkframe *frame, void *arg)
403 { 416 {
404 CopyableInfo *cinfo; 417 CopyableInfo *cinfo;
405 Func *f; 418 Func *f;
406 StackMap *stackmap; 419 StackMap *stackmap;
407 420
408 cinfo = arg; 421 cinfo = arg;
409 f = frame->fn; 422 f = frame->fn;
410 if(StackDebug >= 2) 423 if(StackDebug >= 2)
411 runtime·printf(" checking %s frame=[%p,%p] stk=[%p,%p]\n", ru ntime·funcname(f), frame->sp, frame->fp, cinfo->stk, cinfo->base); 424 runtime·printf(" checking %s frame=[%p,%p] stk=[%p,%p]\n", ru ntime·funcname(f), frame->sp, frame->fp, cinfo->stk, cinfo->base);
412 // if we're not in the segment any more, return immediately. 425 // if we're not in the segment any more, return immediately.
413 » if(frame->varp < cinfo->stk || frame->varp >= cinfo->base) { 426 » if((byte*)frame->varp < cinfo->stk || (byte*)frame->varp >= cinfo->base) {
414 if(StackDebug >= 2) 427 if(StackDebug >= 2)
415 runtime·printf(" <next segment>\n"); 428 runtime·printf(" <next segment>\n");
416 return false; // stop traceback 429 return false; // stop traceback
417 } 430 }
418 if(f->entry == (uintptr)runtime·main) { 431 if(f->entry == (uintptr)runtime·main) {
419 // A special routine at the TOS of the main routine. 432 // A special routine at the TOS of the main routine.
420 // We will allow it to be copied even though we don't 433 // We will allow it to be copied even though we don't
421 // have full GC info for it (because it is written in C). 434 // have full GC info for it (because it is written in C).
422 cinfo->frames++; 435 cinfo->frames++;
423 return false; // stop traceback 436 return false; // stop traceback
424 } 437 }
425 » if(frame->varp != (byte*)frame->sp) { // not in prologue (and has at lea st one local or outarg) 438 » if(f->entry == (uintptr)runtime·switchtoM) {
439 » » // A special routine at the bottom of stack of a goroutine that does onM call.
440 » » // We will allow it to be copied even though we don't
441 » » // have full GC info for it (because it is written in asm).
442 » » cinfo->frames++;
443 » » return true;
444 » }
445 » if((byte*)frame->varp != (byte*)frame->sp) { // not in prologue (and has at least one local or outarg)
426 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps); 446 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
427 if(stackmap == nil) { 447 if(stackmap == nil) {
428 cinfo->frames = -1; 448 cinfo->frames = -1;
429 » » » if(StackDebug >= 1) 449 » » » if(StackDebug >= 1 || StackCopyAlways)
430 » » » » runtime·printf("copystack: no locals info for %s \n", runtime·funcname(f)); 450 » » » » runtime·printf("runtime: copystack: no locals in fo for %s\n", runtime·funcname(f));
431 return false; 451 return false;
432 } 452 }
433 if(stackmap->n <= 0) { 453 if(stackmap->n <= 0) {
434 cinfo->frames = -1; 454 cinfo->frames = -1;
435 » » » if(StackDebug >= 1) 455 » » » if(StackDebug >= 1 || StackCopyAlways)
436 » » » » runtime·printf("copystack: locals size info only for %s\n", runtime·funcname(f)); 456 » » » » runtime·printf("runtime: copystack: locals size info only for %s\n", runtime·funcname(f));
437 return false; 457 return false;
438 } 458 }
439 } 459 }
440 if(frame->arglen != 0) { 460 if(frame->arglen != 0) {
441 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps); 461 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
442 if(stackmap == nil) { 462 if(stackmap == nil) {
443 cinfo->frames = -1; 463 cinfo->frames = -1;
444 » » » if(StackDebug >= 1) 464 » » » if(StackDebug >= 1 || StackCopyAlways)
445 » » » » runtime·printf("copystack: no arg info for %s\n" , runtime·funcname(f)); 465 » » » » runtime·printf("runtime: copystack: no arg info for %s\n", runtime·funcname(f));
446 return false; 466 return false;
447 } 467 }
448 } 468 }
449 cinfo->frames++; 469 cinfo->frames++;
450 return true; // this frame is ok; keep going 470 return true; // this frame is ok; keep going
451 } 471 }
452 472
453 // If the top segment of the stack contains an uncopyable 473 // If the top segment of the stack contains an uncopyable
454 // frame, return -1. Otherwise return the number of frames 474 // frame, return -1. Otherwise return the number of frames
455 // in the top segment, all of which are copyable. 475 // in the top segment, all of which are copyable.
456 static int32 476 static int32
457 copyabletopsegment(G *gp) 477 copyabletopsegment(G *gp)
458 { 478 {
459 CopyableInfo cinfo; 479 CopyableInfo cinfo;
460 Defer *d; 480 Defer *d;
461 Func *f; 481 Func *f;
462 FuncVal *fn; 482 FuncVal *fn;
463 StackMap *stackmap; 483 StackMap *stackmap;
484 bool (*cb)(Stkframe*, void*);
464 485
465 if(gp->stackbase == 0) 486 if(gp->stackbase == 0)
466 runtime·throw("stackbase == 0"); 487 runtime·throw("stackbase == 0");
467 cinfo.stk = (byte*)gp->stackguard - StackGuard; 488 cinfo.stk = (byte*)gp->stackguard - StackGuard;
468 cinfo.base = (byte*)gp->stackbase + sizeof(Stktop); 489 cinfo.base = (byte*)gp->stackbase + sizeof(Stktop);
469 cinfo.frames = 0; 490 cinfo.frames = 0;
470 491
471 // Check that each frame is copyable. As a side effect, 492 // Check that each frame is copyable. As a side effect,
472 // count the frames. 493 // count the frames.
473 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff , checkframecopy, &cinfo, false); 494 » cb = checkframecopy;
495 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, 0x7fffffff , &cb, &cinfo, false);
474 if(StackDebug >= 1 && cinfo.frames != -1) 496 if(StackDebug >= 1 && cinfo.frames != -1)
475 runtime·printf("copystack: %d copyable frames\n", cinfo.frames); 497 runtime·printf("copystack: %d copyable frames\n", cinfo.frames);
498
499 if(cinfo.frames == -1)
500 return -1;
476 501
477 // Check to make sure all Defers are copyable 502 // Check to make sure all Defers are copyable
478 for(d = gp->defer; d != nil; d = d->link) { 503 for(d = gp->defer; d != nil; d = d->link) {
479 if(cinfo.stk <= (byte*)d && (byte*)d < cinfo.base) { 504 if(cinfo.stk <= (byte*)d && (byte*)d < cinfo.base) {
480 // Defer is on the stack. Its copyableness has 505 // Defer is on the stack. Its copyableness has
481 // been established during stack walking. 506 // been established during stack walking.
482 // For now, this only happens with the Defer in runtime. main. 507 // For now, this only happens with the Defer in runtime. main.
483 continue; 508 continue;
484 } 509 }
485 » » if(d->argp < cinfo.stk || cinfo.base <= d->argp) 510 » » if((byte*)d->argp < cinfo.stk || cinfo.base <= (byte*)d->argp)
486 break; // a defer for the next segment 511 break; // a defer for the next segment
487 fn = d->fn; 512 fn = d->fn;
488 if(fn == nil) // See issue 8047 513 if(fn == nil) // See issue 8047
489 continue; 514 continue;
490 f = runtime·findfunc((uintptr)fn->fn); 515 f = runtime·findfunc((uintptr)fn->fn);
491 » » if(f == nil) 516 » » if(f == nil) {
517 » » » if(StackDebug >= 1 || StackCopyAlways)
518 » » » » runtime·printf("runtime: copystack: no func for deferred pc %p\n", fn->fn);
492 return -1; 519 return -1;
520 }
493 521
494 // Check to make sure we have an args pointer map for the defer' s args. 522 // Check to make sure we have an args pointer map for the defer' s args.
495 // We only need the args map, but we check 523 // We only need the args map, but we check
496 // for the locals map also, because when the locals map 524 // for the locals map also, because when the locals map
497 // isn't provided it means the ptr map came from C and 525 // isn't provided it means the ptr map came from C and
498 // C (particularly, cgo) lies to us. See issue 7695. 526 // C (particularly, cgo) lies to us. See issue 7695.
499 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps); 527 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
500 » » if(stackmap == nil || stackmap->n <= 0) 528 » » if(stackmap == nil || stackmap->n <= 0) {
529 » » » if(StackDebug >= 1 || StackCopyAlways)
530 » » » » runtime·printf("runtime: copystack: no arg info for deferred %s\n", runtime·funcname(f));
501 return -1; 531 return -1;
532 }
502 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps); 533 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
503 » » if(stackmap == nil || stackmap->n <= 0) 534 » » if(stackmap == nil || stackmap->n <= 0) {
535 » » » if(StackDebug >= 1 || StackCopyAlways)
536 » » » » runtime·printf("runtime: copystack: no local inf o for deferred %s\n", runtime·funcname(f));
504 return -1; 537 return -1;
538 }
505 539
506 if(cinfo.stk <= (byte*)fn && (byte*)fn < cinfo.base) { 540 if(cinfo.stk <= (byte*)fn && (byte*)fn < cinfo.base) {
507 // FuncVal is on the stack. Again, its copyableness 541 // FuncVal is on the stack. Again, its copyableness
508 // was established during stack walking. 542 // was established during stack walking.
509 continue; 543 continue;
510 } 544 }
511 // The FuncVal may have pointers in it, but fortunately for us 545 // The FuncVal may have pointers in it, but fortunately for us
512 // the compiler won't put pointers into the stack in a 546 // the compiler won't put pointers into the stack in a
513 // heap-allocated FuncVal. 547 // heap-allocated FuncVal.
514 // One day if we do need to check this, we'll need maps of the 548 // One day if we do need to check this, we'll need maps of the
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 runtime·throw("bad pointer!"); 595 runtime·throw("bad pointer!");
562 } 596 }
563 if(minp <= p && p < maxp) { 597 if(minp <= p && p < maxp) {
564 if(StackDebug >= 3) 598 if(StackDebug >= 3)
565 runtime·printf("adjust ptr %p %s\n", p, runtime·funcname(f)); 599 runtime·printf("adjust ptr %p %s\n", p, runtime·funcname(f));
566 scanp[i] = p + delta; 600 scanp[i] = p + delta;
567 } 601 }
568 break; 602 break;
569 case BitsMultiWord: 603 case BitsMultiWord:
570 switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i +1) * BitsPerPointer & 7) & 3) { 604 switch(bv->bytedata[(i+1) / (8 / BitsPerPointer)] >> ((i +1) * BitsPerPointer & 7) & 3) {
571 » » » case BitsString: 605 » » » default:
572 » » » » // string referents are never on the stack, neve r need to be adjusted 606 » » » » runtime·throw("unexpected garbage collection bit s");
573 » » » » i++; // skip len
574 » » » » break;
575 » » » case BitsSlice:
576 » » » » p = scanp[i];
577 » » » » if(minp <= p && p < maxp) {
578 » » » » » if(StackDebug >= 3)
579 » » » » » » runtime·printf("adjust slice %p\ n", p);
580 » » » » » scanp[i] = p + delta;
581 » » » » }
582 » » » » i += 2; // skip len, cap
583 » » » » break;
584 case BitsEface: 607 case BitsEface:
585 t = (Type*)scanp[i]; 608 t = (Type*)scanp[i];
586 » » » » if(t != nil && (t->size > PtrSize || (t->kind & KindNoPointers) == 0)) { 609 » » » » if(t != nil && ((t->kind & KindDirectIface) == 0 || (t->kind & KindNoPointers) == 0)) {
587 p = scanp[i+1]; 610 p = scanp[i+1];
588 if(minp <= p && p < maxp) { 611 if(minp <= p && p < maxp) {
589 if(StackDebug >= 3) 612 if(StackDebug >= 3)
590 runtime·printf("adjust e face %p\n", p); 613 runtime·printf("adjust e face %p\n", p);
591 if(t->size > PtrSize) // current ly we always allocate such objects on the heap 614 if(t->size > PtrSize) // current ly we always allocate such objects on the heap
592 runtime·throw("large int erface value found on stack"); 615 runtime·throw("large int erface value found on stack");
593 scanp[i+1] = p + delta; 616 scanp[i+1] = p + delta;
594 } 617 }
595 } 618 }
596 i++; 619 i++;
597 break; 620 break;
598 case BitsIface: 621 case BitsIface:
599 tab = (Itab*)scanp[i]; 622 tab = (Itab*)scanp[i];
600 if(tab != nil) { 623 if(tab != nil) {
601 t = tab->type; 624 t = tab->type;
602 //runtime·printf(" type=%p\n", t); 625 //runtime·printf(" type=%p\n", t);
603 » » » » » if(t->size > PtrSize || (t->kind & KindN oPointers) == 0) { 626 » » » » » if((t->kind & KindDirectIface) == 0 || ( t->kind & KindNoPointers) == 0) {
604 p = scanp[i+1]; 627 p = scanp[i+1];
605 if(minp <= p && p < maxp) { 628 if(minp <= p && p < maxp) {
606 if(StackDebug >= 3) 629 if(StackDebug >= 3)
607 runtime·printf(" adjust iface %p\n", p); 630 runtime·printf(" adjust iface %p\n", p);
608 if(t->size > PtrSize) // currently we always allocate such objects on the heap 631 if(t->size > PtrSize) // currently we always allocate such objects on the heap
609 runtime·throw("l arge interface value found on stack"); 632 runtime·throw("l arge interface value found on stack");
610 scanp[i+1] = p + delta; 633 scanp[i+1] = p + delta;
611 } 634 }
612 } 635 }
613 } 636 }
(...skipping 13 matching lines...) Expand all
627 Func *f; 650 Func *f;
628 StackMap *stackmap; 651 StackMap *stackmap;
629 int32 pcdata; 652 int32 pcdata;
630 BitVector bv; 653 BitVector bv;
631 uintptr targetpc; 654 uintptr targetpc;
632 655
633 adjinfo = arg; 656 adjinfo = arg;
634 f = frame->fn; 657 f = frame->fn;
635 if(StackDebug >= 2) 658 if(StackDebug >= 2)
636 runtime·printf(" adjusting %s frame=[%p,%p] pc=%p continpc=%p \n", runtime·funcname(f), frame->sp, frame->fp, frame->pc, frame->continpc); 659 runtime·printf(" adjusting %s frame=[%p,%p] pc=%p continpc=%p \n", runtime·funcname(f), frame->sp, frame->fp, frame->pc, frame->continpc);
637 » if(f->entry == (uintptr)runtime·main) 660 » if(f->entry == (uintptr)runtime·main ||
661 » » f->entry == (uintptr)runtime·switchtoM)
638 return true; 662 return true;
639 targetpc = frame->continpc; 663 targetpc = frame->continpc;
640 if(targetpc == 0) { 664 if(targetpc == 0) {
641 // Frame is dead. 665 // Frame is dead.
642 return true; 666 return true;
643 } 667 }
644 if(targetpc != f->entry) 668 if(targetpc != f->entry)
645 targetpc--; 669 targetpc--;
646 pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc); 670 pcdata = runtime·pcdatavalue(f, PCDATA_StackMapIndex, targetpc);
647 if(pcdata == -1) 671 if(pcdata == -1)
648 pcdata = 0; // in prologue 672 pcdata = 0; // in prologue
649 673
650 // adjust local pointers 674 // adjust local pointers
651 » if(frame->varp != (byte*)frame->sp) { 675 » if((byte*)frame->varp != (byte*)frame->sp) {
652 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps); 676 stackmap = runtime·funcdata(f, FUNCDATA_LocalsPointerMaps);
653 if(stackmap == nil) 677 if(stackmap == nil)
654 runtime·throw("no locals info"); 678 runtime·throw("no locals info");
655 if(stackmap->n <= 0) 679 if(stackmap->n <= 0)
656 runtime·throw("locals size info only"); 680 runtime·throw("locals size info only");
657 bv = runtime·stackmapdata(stackmap, pcdata); 681 bv = runtime·stackmapdata(stackmap, pcdata);
658 if(StackDebug >= 3) 682 if(StackDebug >= 3)
659 runtime·printf(" locals\n"); 683 runtime·printf(" locals\n");
660 adjustpointers((byte**)frame->varp - bv.n / BitsPerPointer, &bv, adjinfo, f); 684 adjustpointers((byte**)frame->varp - bv.n / BitsPerPointer, &bv, adjinfo, f);
661 } 685 }
662 // adjust inargs and outargs 686 // adjust inargs and outargs
663 if(frame->arglen != 0) { 687 if(frame->arglen != 0) {
664 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps); 688 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps);
665 » » if(stackmap == nil) 689 » » if(stackmap == nil) {
690 » » » runtime·printf("size %d\n", (int32)frame->arglen);
666 runtime·throw("no arg info"); 691 runtime·throw("no arg info");
692 }
667 bv = runtime·stackmapdata(stackmap, pcdata); 693 bv = runtime·stackmapdata(stackmap, pcdata);
668 if(StackDebug >= 3) 694 if(StackDebug >= 3)
669 runtime·printf(" args\n"); 695 runtime·printf(" args\n");
670 adjustpointers((byte**)frame->argp, &bv, adjinfo, nil); 696 adjustpointers((byte**)frame->argp, &bv, adjinfo, nil);
671 } 697 }
672 return true; 698 return true;
673 } 699 }
674 700
675 static void 701 static void
676 adjustctxt(G *gp, AdjustInfo *adjinfo) 702 adjustctxt(G *gp, AdjustInfo *adjinfo)
677 { 703 {
678 if(adjinfo->oldstk <= (byte*)gp->sched.ctxt && (byte*)gp->sched.ctxt < a djinfo->oldbase) 704 if(adjinfo->oldstk <= (byte*)gp->sched.ctxt && (byte*)gp->sched.ctxt < a djinfo->oldbase)
679 gp->sched.ctxt = (byte*)gp->sched.ctxt + adjinfo->delta; 705 gp->sched.ctxt = (byte*)gp->sched.ctxt + adjinfo->delta;
680 } 706 }
681 707
682 static void 708 static void
683 adjustdefers(G *gp, AdjustInfo *adjinfo) 709 adjustdefers(G *gp, AdjustInfo *adjinfo)
684 { 710 {
685 Defer *d, **dp; 711 Defer *d, **dp;
686 Func *f; 712 Func *f;
687 FuncVal *fn; 713 FuncVal *fn;
688 StackMap *stackmap; 714 StackMap *stackmap;
689 BitVector bv; 715 BitVector bv;
690 716
691 for(dp = &gp->defer, d = *dp; d != nil; dp = &d->link, d = *dp) { 717 for(dp = &gp->defer, d = *dp; d != nil; dp = &d->link, d = *dp) {
692 if(adjinfo->oldstk <= (byte*)d && (byte*)d < adjinfo->oldbase) { 718 if(adjinfo->oldstk <= (byte*)d && (byte*)d < adjinfo->oldbase) {
693 // The Defer record is on the stack. Its fields will 719 // The Defer record is on the stack. Its fields will
694 // get adjusted appropriately. 720 // get adjusted appropriately.
695 » » » // This only happens for runtime.main now, but a compile r 721 » » » // This only happens for runtime.main and runtime.gopani c now,
696 » » » // optimization could do more of this. 722 » » » // but a compiler optimization could do more of this.
697 *dp = (Defer*)((byte*)d + adjinfo->delta); 723 *dp = (Defer*)((byte*)d + adjinfo->delta);
698 continue; 724 continue;
699 } 725 }
700 » » if(d->argp < adjinfo->oldstk || adjinfo->oldbase <= d->argp) 726 » » if((byte*)d->argp < adjinfo->oldstk || adjinfo->oldbase <= (byte *)d->argp)
701 break; // a defer for the next segment 727 break; // a defer for the next segment
702 fn = d->fn; 728 fn = d->fn;
703 if(fn == nil) { 729 if(fn == nil) {
704 // Defer of nil function. It will panic when run, and t here 730 // Defer of nil function. It will panic when run, and t here
705 // aren't any args to adjust. See issue 8047. 731 // aren't any args to adjust. See issue 8047.
706 d->argp += adjinfo->delta; 732 d->argp += adjinfo->delta;
707 continue; 733 continue;
708 } 734 }
709 f = runtime·findfunc((uintptr)fn->fn); 735 f = runtime·findfunc((uintptr)fn->fn);
710 if(f == nil) 736 if(f == nil)
(...skipping 12 matching lines...) Expand all
723 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps) ; 749 stackmap = runtime·funcdata(f, FUNCDATA_ArgsPointerMaps) ;
724 if(stackmap == nil) 750 if(stackmap == nil)
725 runtime·throw("runtime: deferred function has no arg ptr map"); 751 runtime·throw("runtime: deferred function has no arg ptr map");
726 bv = runtime·stackmapdata(stackmap, 0); 752 bv = runtime·stackmapdata(stackmap, 0);
727 adjustpointers(d->args, &bv, adjinfo, f); 753 adjustpointers(d->args, &bv, adjinfo, f);
728 } 754 }
729 d->argp += adjinfo->delta; 755 d->argp += adjinfo->delta;
730 } 756 }
731 } 757 }
732 758
759 static void
760 adjustpanics(G *gp, AdjustInfo *adjinfo)
761 {
762 Panic *p, **l;
763
764 // only the topmost panic is on the current stack
765 for(l = &gp->panic; (p = *l) != nil; ) {
766 if(adjinfo->oldstk <= (byte*)p && (byte*)p < adjinfo->oldbase)
767 *l = (Panic*)((byte*)p + adjinfo->delta);
768 l = &p->link;
769 ················
770 if(adjinfo->oldstk <= (byte*)p->argp && (byte*)p->argp < adjinfo ->oldbase)
771 p->argp += adjinfo->delta;
772 }
773 }
774
775 static void
776 adjustsudogs(G *gp, AdjustInfo *adjinfo)
777 {
778 SudoG *s;
779 byte *e;
780
781 // the data elements pointed to by a SudoG structure
782 // might be in the stack.
783 for(s = gp->waiting; s != nil; s = s->waitlink) {
784 e = s->elem;
785 if(adjinfo->oldstk <= e && e < adjinfo->oldbase)
786 s->elem = e + adjinfo->delta;
787 e = (byte*)s->selectdone;
788 if(adjinfo->oldstk <= e && e < adjinfo->oldbase)
789 s->selectdone = (uint32*)(e + adjinfo->delta);
790 }
791 }
792
733 // Copies the top stack segment of gp to a new stack segment of a 793 // Copies the top stack segment of gp to a new stack segment of a
734 // different size. The top segment must contain nframes frames. 794 // different size. The top segment must contain nframes frames.
735 static void 795 static void
736 copystack(G *gp, uintptr nframes, uintptr newsize) 796 copystack(G *gp, uintptr nframes, uintptr newsize)
737 { 797 {
738 byte *oldstk, *oldbase, *newstk, *newbase; 798 byte *oldstk, *oldbase, *newstk, *newbase;
739 uintptr oldsize, used; 799 uintptr oldsize, used;
740 AdjustInfo adjinfo; 800 AdjustInfo adjinfo;
741 Stktop *oldtop, *newtop; 801 Stktop *oldtop, *newtop;
802 uint32 oldstatus;
803 bool (*cb)(Stkframe*, void*);
742 804
743 if(gp->syscallstack != 0) 805 if(gp->syscallstack != 0)
744 runtime·throw("can't handle stack copy in syscall yet"); 806 runtime·throw("can't handle stack copy in syscall yet");
745 oldstk = (byte*)gp->stackguard - StackGuard; 807 oldstk = (byte*)gp->stackguard - StackGuard;
746 if(gp->stackbase == 0) 808 if(gp->stackbase == 0)
747 runtime·throw("nil stackbase"); 809 runtime·throw("nil stackbase");
748 oldbase = (byte*)gp->stackbase + sizeof(Stktop); 810 oldbase = (byte*)gp->stackbase + sizeof(Stktop);
749 oldsize = oldbase - oldstk; 811 oldsize = oldbase - oldstk;
750 used = oldbase - (byte*)gp->sched.sp; 812 used = oldbase - (byte*)gp->sched.sp;
751 oldtop = (Stktop*)gp->stackbase; 813 oldtop = (Stktop*)gp->stackbase;
752 814
753 // allocate new stack 815 // allocate new stack
754 newstk = runtime·stackalloc(gp, newsize); 816 newstk = runtime·stackalloc(gp, newsize);
755 newbase = newstk + newsize; 817 newbase = newstk + newsize;
756 newtop = (Stktop*)(newbase - sizeof(Stktop)); 818 newtop = (Stktop*)(newbase - sizeof(Stktop));
757 819
758 if(StackDebug >= 1) 820 if(StackDebug >= 1)
759 runtime·printf("copystack gp=%p [%p %p]/%d -> [%p %p]/%d\n", gp, oldstk, oldbase, (int32)oldsize, newstk, newbase, (int32)newsize); 821 runtime·printf("copystack gp=%p [%p %p]/%d -> [%p %p]/%d\n", gp, oldstk, oldbase, (int32)oldsize, newstk, newbase, (int32)newsize);
760 USED(oldsize); 822 USED(oldsize);
761 ········ 823 ········
762 // adjust pointers in the to-be-copied frames 824 // adjust pointers in the to-be-copied frames
763 adjinfo.oldstk = oldstk; 825 adjinfo.oldstk = oldstk;
764 adjinfo.oldbase = oldbase; 826 adjinfo.oldbase = oldbase;
765 adjinfo.delta = newbase - oldbase; 827 adjinfo.delta = newbase - oldbase;
766 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, nframes, a djustframe, &adjinfo, false); 828 » cb = adjustframe;
829 » runtime·gentraceback(~(uintptr)0, ~(uintptr)0, 0, gp, 0, nil, nframes, & cb, &adjinfo, false);
767 ········ 830 ········
768 // adjust other miscellaneous things that have pointers into stacks. 831 // adjust other miscellaneous things that have pointers into stacks.
769 adjustctxt(gp, &adjinfo); 832 adjustctxt(gp, &adjinfo);
770 adjustdefers(gp, &adjinfo); 833 adjustdefers(gp, &adjinfo);
834 adjustpanics(gp, &adjinfo);
835 adjustsudogs(gp, &adjinfo);
771 ········ 836 ········
772 // copy the stack (including Stktop) to the new location 837 // copy the stack (including Stktop) to the new location
773 runtime·memmove(newbase - used, oldbase - used, used); 838 runtime·memmove(newbase - used, oldbase - used, used);
774 » 839 » oldstatus = runtime·readgstatus(gp);
840 » oldstatus &= ~Gscan;
841 » if (oldstatus == Gwaiting || oldstatus == Grunnable)
842 » » runtime·casgstatus(gp, oldstatus, Gcopystack); // oldstatus is G waiting or Grunnable
843 » else
844 » » runtime·throw("copystack: bad status, not Gwaiting or Grunnable" );
775 // Swap out old stack for new one 845 // Swap out old stack for new one
776 gp->stackbase = (uintptr)newtop; 846 gp->stackbase = (uintptr)newtop;
777 gp->stackguard = (uintptr)newstk + StackGuard; 847 gp->stackguard = (uintptr)newstk + StackGuard;
778 gp->stackguard0 = (uintptr)newstk + StackGuard; // NOTE: might clobber a preempt request 848 gp->stackguard0 = (uintptr)newstk + StackGuard; // NOTE: might clobber a preempt request
779 if(gp->stack0 == (uintptr)oldstk) 849 if(gp->stack0 == (uintptr)oldstk)
780 gp->stack0 = (uintptr)newstk; 850 gp->stack0 = (uintptr)newstk;
781 gp->sched.sp = (uintptr)(newbase - used); 851 gp->sched.sp = (uintptr)(newbase - used);
782 852
853 runtime·casgstatus(gp, Gcopystack, oldstatus); // oldstatus is Gwaiting or Grunnable
854
783 // free old stack 855 // free old stack
784 runtime·stackfree(gp, oldstk, oldtop); 856 runtime·stackfree(gp, oldstk, oldtop);
785 } 857 }
786 858
787 // round x up to a power of 2. 859 // round x up to a power of 2.
788 int32 860 int32
789 runtime·round2(int32 x) 861 runtime·round2(int32 x)
790 { 862 {
791 int32 s; 863 int32 s;
792 864
793 s = 0; 865 s = 0;
794 while((1 << s) < x) 866 while((1 << s) < x)
795 s++; 867 s++;
796 return 1 << s; 868 return 1 << s;
797 } 869 }
798 870
799 // Called from runtime·newstackcall or from runtime·morestack when a new 871 // Called from runtime·morestack when a new stack segment is needed.
800 // stack segment is needed. Allocate a new stack big enough for 872 // Allocate a new stack big enough for m->moreframesize bytes,
801 // m->moreframesize bytes, copy m->moreargsize bytes to the new frame, 873 // copy m->moreargsize bytes to the new frame,
802 // and then act as though runtime·lessstack called the function at 874 // and then act as though runtime·lessstack called the function at m->morepc.
803 // m->morepc. 875 //
876 // g->atomicstatus will be Grunning, Gsyscall or Gscanrunning, Gscansyscall upon entry.·
877 // If the GC is trying to stop this g then it will set preemptscan to true.
804 void 878 void
805 runtime·newstack(void) 879 runtime·newstack(void)
806 { 880 {
807 int32 framesize, argsize, oldstatus, oldsize, newsize, nframes; 881 int32 framesize, argsize, oldstatus, oldsize, newsize, nframes;
808 » Stktop *top, *oldtop; 882 » Stktop *top;
809 byte *stk, *oldstk, *oldbase; 883 byte *stk, *oldstk, *oldbase;
810 uintptr sp; 884 uintptr sp;
811 uintptr *src, *dst, *dstend; 885 uintptr *src, *dst, *dstend;
812 G *gp; 886 G *gp;
813 Gobuf label, morebuf; 887 Gobuf label, morebuf;
814 void *moreargp; 888 void *moreargp;
815 bool newstackcall;
816 889
817 if(g->m->forkstackguard) 890 if(g->m->forkstackguard)
818 runtime·throw("split stack after fork"); 891 runtime·throw("split stack after fork");
819 if(g->m->morebuf.g != g->m->curg) { 892 if(g->m->morebuf.g != g->m->curg) {
820 runtime·printf("runtime: newstack called from g=%p\n" 893 runtime·printf("runtime: newstack called from g=%p\n"
821 "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n", 894 "\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
822 g->m->morebuf.g, g->m, g->m->curg, g->m->g0, g->m->gsign al); 895 g->m->morebuf.g, g->m, g->m->curg, g->m->g0, g->m->gsign al);
896 morebuf = g->m->morebuf;
897 runtime·traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g) ;
823 runtime·throw("runtime: wrong goroutine in newstack"); 898 runtime·throw("runtime: wrong goroutine in newstack");
824 } 899 }
900 if(g->throwsplit)
901 runtime·throw("runtime: stack split at bad time");
902
903 // The goroutine must be executing in order to call newstack, so the pos sible states are
904 // Grunning and Gsyscall (and, due to GC, also Gscanrunning and Gscansys call).··
825 905
826 // gp->status is usually Grunning, but it could be Gsyscall if a stack o verflow 906 // gp->status is usually Grunning, but it could be Gsyscall if a stack o verflow
827 // happens during a function call inside entersyscall. 907 // happens during a function call inside entersyscall.
828 gp = g->m->curg; 908 gp = g->m->curg;
829 » oldstatus = gp->status; 909 » oldstatus = runtime·readgstatus(gp) & ~Gscan;
830
831 framesize = g->m->moreframesize; 910 framesize = g->m->moreframesize;
832 argsize = g->m->moreargsize; 911 argsize = g->m->moreargsize;
833 moreargp = g->m->moreargp; 912 moreargp = g->m->moreargp;
834 g->m->moreargp = nil; 913 g->m->moreargp = nil;
835 morebuf = g->m->morebuf; 914 morebuf = g->m->morebuf;
836 g->m->morebuf.pc = (uintptr)nil; 915 g->m->morebuf.pc = (uintptr)nil;
837 g->m->morebuf.lr = (uintptr)nil; 916 g->m->morebuf.lr = (uintptr)nil;
838 g->m->morebuf.sp = (uintptr)nil; 917 g->m->morebuf.sp = (uintptr)nil;
839 » gp->status = Gwaiting; 918
840 » gp->waitreason = "stack growth"; 919 » runtime·casgstatus(gp, oldstatus, Gwaiting); // oldstatus is not in a Gs can status
841 » newstackcall = framesize==1; 920 » gp->waitreason = runtime·gostringnocopy((byte*)"stack growth");
842 » if(newstackcall) 921
843 » » framesize = 0; 922 » runtime·rewindmorestack(&gp->sched);
844
845 » // For newstackcall the context already points to beginning of runtime·n ewstackcall.
846 » if(!newstackcall)
847 » » runtime·rewindmorestack(&gp->sched);
848 923
849 if(gp->stackbase == 0) 924 if(gp->stackbase == 0)
850 runtime·throw("nil stackbase"); 925 runtime·throw("nil stackbase");
851 sp = gp->sched.sp; 926 sp = gp->sched.sp;
852 if(thechar == '6' || thechar == '8') { 927 if(thechar == '6' || thechar == '8') {
853 // The call to morestack cost a word. 928 // The call to morestack cost a word.
854 » » sp -= sizeof(uintptr); 929 » » sp -= sizeof(uintreg);
855 } 930 }
856 if(StackDebug >= 1 || sp < gp->stackguard - StackGuard) { 931 if(StackDebug >= 1 || sp < gp->stackguard - StackGuard) {
857 runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p stack=[%p, %p]\n" 932 runtime·printf("runtime: newstack framesize=%p argsize=%p sp=%p stack=[%p, %p]\n"
858 "\tmorebuf={pc:%p sp:%p lr:%p}\n" 933 "\tmorebuf={pc:%p sp:%p lr:%p}\n"
859 "\tsched={pc:%p sp:%p lr:%p ctxt:%p}\n", 934 "\tsched={pc:%p sp:%p lr:%p ctxt:%p}\n",
860 (uintptr)framesize, (uintptr)argsize, sp, gp->stackguard - StackGuard, gp->stackbase, 935 (uintptr)framesize, (uintptr)argsize, sp, gp->stackguard - StackGuard, gp->stackbase,
861 g->m->morebuf.pc, g->m->morebuf.sp, g->m->morebuf.lr, 936 g->m->morebuf.pc, g->m->morebuf.sp, g->m->morebuf.lr,
862 gp->sched.pc, gp->sched.sp, gp->sched.lr, gp->sched.ctxt ); 937 gp->sched.pc, gp->sched.sp, gp->sched.lr, gp->sched.ctxt );
863 } 938 }
864 if(sp < gp->stackguard - StackGuard) { 939 if(sp < gp->stackguard - StackGuard) {
940 runtime·printf("runtime: gp=%p, gp->status=%d, oldstatus=%d\n ", (void*)gp, runtime·readgstatus(gp), oldstatus);
865 runtime·printf("runtime: split stack overflow: %p < %p\n", sp, g p->stackguard - StackGuard); 941 runtime·printf("runtime: split stack overflow: %p < %p\n", sp, g p->stackguard - StackGuard);
866 runtime·throw("runtime: split stack overflow"); 942 runtime·throw("runtime: split stack overflow");
867 } 943 }
868 944
869 if(argsize % sizeof(uintptr) != 0) { 945 if(argsize % sizeof(uintptr) != 0) {
870 runtime·printf("runtime: stack growth with misaligned argsize %d \n", argsize); 946 runtime·printf("runtime: stack growth with misaligned argsize %d \n", argsize);
871 runtime·throw("runtime: stack growth argsize"); 947 runtime·throw("runtime: stack growth argsize");
872 } 948 }
873 949
874 if(gp->stackguard0 == (uintptr)StackPreempt) { 950 if(gp->stackguard0 == (uintptr)StackPreempt) {
875 if(gp == g->m->g0) 951 if(gp == g->m->g0)
876 runtime·throw("runtime: preempt g0"); 952 runtime·throw("runtime: preempt g0");
877 if(oldstatus == Grunning && g->m->p == nil && g->m->locks == 0) 953 if(oldstatus == Grunning && g->m->p == nil && g->m->locks == 0)
878 runtime·throw("runtime: g is running but p is not"); 954 runtime·throw("runtime: g is running but p is not");
879 if(oldstatus == Gsyscall && g->m->locks == 0) 955 if(oldstatus == Gsyscall && g->m->locks == 0)
880 runtime·throw("runtime: stack growth during syscall"); 956 runtime·throw("runtime: stack growth during syscall");
957 if(oldstatus == Grunning && gp->preemptscan) {
958 runtime·gcphasework(gp);
959 runtime·casgstatus(gp, Gwaiting, Grunning);
960 gp->stackguard0 = gp->stackguard;
961 gp->preempt = false;·
962 gp->preemptscan = false; // Tells the GC premptio n was successful.
963 runtime·gogo(&gp->sched); // never return·
964 }
965
881 // Be conservative about where we preempt. 966 // Be conservative about where we preempt.
882 // We are interested in preempting user Go code, not runtime cod e. 967 // We are interested in preempting user Go code, not runtime cod e.
883 if(oldstatus != Grunning || g->m->locks || g->m->mallocing || g- >m->gcing || g->m->p->status != Prunning) { 968 if(oldstatus != Grunning || g->m->locks || g->m->mallocing || g- >m->gcing || g->m->p->status != Prunning) {
884 // Let the goroutine keep running for now. 969 // Let the goroutine keep running for now.
885 // gp->preempt is set, so it will be preempted next time . 970 // gp->preempt is set, so it will be preempted next time .
886 gp->stackguard0 = gp->stackguard; 971 gp->stackguard0 = gp->stackguard;
887 » » » gp->status = oldstatus; 972 » » » runtime·casgstatus(gp, Gwaiting, oldstatus); // oldstatu s is Gsyscall or Grunning
888 runtime·gogo(&gp->sched); // never return 973 runtime·gogo(&gp->sched); // never return
889 } 974 }
890 // Act like goroutine called runtime.Gosched. 975 // Act like goroutine called runtime.Gosched.
891 » » gp->status = oldstatus; 976 » » runtime·casgstatus(gp, Gwaiting, oldstatus); // oldstatus is Gsy scall or Grunning
892 » » runtime·gosched0(gp);» // never return 977 » » runtime·gosched_m(gp);» // never return
893 } 978 }
894 979
895 // If every frame on the top segment is copyable, allocate a bigger segm ent 980 // If every frame on the top segment is copyable, allocate a bigger segm ent
896 // and move the segment instead of allocating a new segment. 981 // and move the segment instead of allocating a new segment.
897 if(runtime·copystack) { 982 if(runtime·copystack) {
898 if(!runtime·precisestack) 983 if(!runtime·precisestack)
899 runtime·throw("can't copy stacks without precise stacks" ); 984 runtime·throw("can't copy stacks without precise stacks" );
900 nframes = copyabletopsegment(gp); 985 nframes = copyabletopsegment(gp);
901 if(nframes != -1) { 986 if(nframes != -1) {
902 oldstk = (byte*)gp->stackguard - StackGuard; 987 oldstk = (byte*)gp->stackguard - StackGuard;
903 oldbase = (byte*)gp->stackbase + sizeof(Stktop); 988 oldbase = (byte*)gp->stackbase + sizeof(Stktop);
904 oldsize = oldbase - oldstk; 989 oldsize = oldbase - oldstk;
905 newsize = oldsize * 2; 990 newsize = oldsize * 2;
991 // Note that the concurrent GC might be scanning the sta ck as we try to replace it.
992 // copystack takes care of the appropriate coordination with the stack scanner.
906 copystack(gp, nframes, newsize); 993 copystack(gp, nframes, newsize);
907 if(StackDebug >= 1) 994 if(StackDebug >= 1)
908 runtime·printf("stack grow done\n"); 995 runtime·printf("stack grow done\n");
909 if(gp->stacksize > runtime·maxstacksize) { 996 if(gp->stacksize > runtime·maxstacksize) {
910 runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n", (uint64)runtime·maxstacksize); 997 runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n", (uint64)runtime·maxstacksize);
911 runtime·throw("stack overflow"); 998 runtime·throw("stack overflow");
912 } 999 }
913 » » » gp->status = oldstatus; 1000 » » » runtime·casgstatus(gp, Gwaiting, oldstatus); // oldstatu s is Gsyscall or Grunning
914 runtime·gogo(&gp->sched); 1001 runtime·gogo(&gp->sched);
915 } 1002 }
916 // TODO: if stack is uncopyable because we're in C code, patch r eturn value at 1003 // TODO: if stack is uncopyable because we're in C code, patch r eturn value at
917 // end of C code to trigger a copy as soon as C code exits. Tha t way, we'll 1004 // end of C code to trigger a copy as soon as C code exits. Tha t way, we'll
918 // have stack available if we get this deep again. 1005 // have stack available if we get this deep again.
919 } 1006 }
1007 ········
1008 if(StackCopyAlways)
1009 runtime·throw("split stack not allowed");
920 1010
921 // allocate new segment. 1011 // allocate new segment.
922 framesize += argsize; 1012 framesize += argsize;
923 framesize += StackExtra; // room for more functions, Stktop. 1013 framesize += StackExtra; // room for more functions, Stktop.
924 if(framesize < StackMin) 1014 if(framesize < StackMin)
925 framesize = StackMin; 1015 framesize = StackMin;
926 framesize += StackSystem; 1016 framesize += StackSystem;
927 framesize = runtime·round2(framesize); 1017 framesize = runtime·round2(framesize);
928 stk = runtime·stackalloc(gp, framesize); 1018 stk = runtime·stackalloc(gp, framesize);
929 if(gp->stacksize > runtime·maxstacksize) { 1019 if(gp->stacksize > runtime·maxstacksize) {
930 runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n ", (uint64)runtime·maxstacksize); 1020 runtime·printf("runtime: goroutine stack exceeds %D-byte limit\n ", (uint64)runtime·maxstacksize);
931 runtime·throw("stack overflow"); 1021 runtime·throw("stack overflow");
932 } 1022 }
933 top = (Stktop*)(stk+framesize-sizeof(*top)); 1023 top = (Stktop*)(stk+framesize-sizeof(*top));
934 1024
935 if(StackDebug >= 1) { 1025 if(StackDebug >= 1) {
936 runtime·printf("\t-> new stack gp=%p [%p, %p]\n", gp, stk, top); 1026 runtime·printf("\t-> new stack gp=%p [%p, %p]\n", gp, stk, top);
937 } 1027 }
938 1028
939 top->stackbase = gp->stackbase; 1029 top->stackbase = gp->stackbase;
940 top->stackguard = gp->stackguard; 1030 top->stackguard = gp->stackguard;
941 top->gobuf = morebuf; 1031 top->gobuf = morebuf;
942 top->argp = moreargp; 1032 top->argp = moreargp;
943 top->argsize = argsize; 1033 top->argsize = argsize;
944 1034
945 // copy flag from panic
946 top->panic = gp->ispanic;
947 gp->ispanic = false;
948 ········
949 // if this isn't a panic, maybe we're splitting the stack for a panic.
950 // if we're splitting in the top frame, propagate the panic flag
951 // forward so that recover will know we're in a panic.
952 oldtop = (Stktop*)top->stackbase;
953 if(oldtop != nil && oldtop->panic && top->argp == (byte*)oldtop - oldtop ->argsize - gp->panicwrap)
954 top->panic = true;
955
956 top->panicwrap = gp->panicwrap;
957 gp->panicwrap = 0;
958
959 gp->stackbase = (uintptr)top; 1035 gp->stackbase = (uintptr)top;
960 gp->stackguard = (uintptr)stk + StackGuard; 1036 gp->stackguard = (uintptr)stk + StackGuard;
961 gp->stackguard0 = gp->stackguard; 1037 gp->stackguard0 = gp->stackguard;
962 1038
963 sp = (uintptr)top; 1039 sp = (uintptr)top;
964 if(argsize > 0) { 1040 if(argsize > 0) {
965 sp -= argsize; 1041 sp -= argsize;
966 dst = (uintptr*)sp; 1042 dst = (uintptr*)sp;
967 dstend = dst + argsize/sizeof(*dst); 1043 dstend = dst + argsize/sizeof(*dst);
968 src = (uintptr*)top->argp; 1044 src = (uintptr*)top->argp;
969 while(dst < dstend) 1045 while(dst < dstend)
970 *dst++ = *src++; 1046 *dst++ = *src++;
971 } 1047 }
1048 ········
972 if(thechar == '5' || thechar == '9') { 1049 if(thechar == '5' || thechar == '9') {
973 // caller would have saved its LR below args. 1050 // caller would have saved its LR below args.
974 sp -= sizeof(void*); 1051 sp -= sizeof(void*);
975 *(void**)sp = nil; 1052 *(void**)sp = nil;
976 } 1053 }
977 1054
978 // Continue as if lessstack had just called m->morepc 1055 // Continue as if lessstack had just called m->morepc
979 // (the PC that decided to grow the stack). 1056 // (the PC that decided to grow the stack).
980 runtime·memclr((byte*)&label, sizeof label); 1057 runtime·memclr((byte*)&label, sizeof label);
981 label.sp = sp; 1058 label.sp = sp;
982 label.pc = (uintptr)runtime·lessstack; 1059 label.pc = (uintptr)runtime·lessstack;
983 label.g = g->m->curg; 1060 label.g = g->m->curg;
984 » if(newstackcall) 1061 » runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sched.ctxt) ;
985 » » runtime·gostartcallfn(&label, (FuncVal*)g->m->cret); 1062 » gp->sched.ctxt = nil;
986 » else { 1063 » runtime·casgstatus(gp, Gwaiting, oldstatus); // oldstatus is Grunning or Gsyscall
987 » » runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sch ed.ctxt);
988 » » gp->sched.ctxt = nil;
989 » }
990 » gp->status = oldstatus;
991 runtime·gogo(&label); 1064 runtime·gogo(&label);
992 1065
993 *(int32*)345 = 123; // never return 1066 *(int32*)345 = 123; // never return
994 } 1067 }
995 1068
996 #pragma textflag NOSPLIT 1069 #pragma textflag NOSPLIT
997 void 1070 void
998 runtime·nilfunc(void) 1071 runtime·nilfunc(void)
999 { 1072 {
1000 *(byte*)0 = 0; 1073 *(byte*)0 = 0;
(...skipping 17 matching lines...) Expand all
1018 // Called at garbage collection time. 1091 // Called at garbage collection time.
1019 void 1092 void
1020 runtime·shrinkstack(G *gp) 1093 runtime·shrinkstack(G *gp)
1021 { 1094 {
1022 int32 nframes; 1095 int32 nframes;
1023 byte *oldstk, *oldbase; 1096 byte *oldstk, *oldbase;
1024 uintptr used, oldsize, newsize; 1097 uintptr used, oldsize, newsize;
1025 1098
1026 if(!runtime·copystack) 1099 if(!runtime·copystack)
1027 return; 1100 return;
1028 » if(gp->status == Gdead) 1101 » if(runtime·readgstatus(gp) == Gdead)
1029 return; 1102 return;
1030 if(gp->stackbase == 0) 1103 if(gp->stackbase == 0)
1031 runtime·throw("stackbase == 0"); 1104 runtime·throw("stackbase == 0");
1032 //return; // TODO: why does this happen? 1105 //return; // TODO: why does this happen?
1033 oldstk = (byte*)gp->stackguard - StackGuard; 1106 oldstk = (byte*)gp->stackguard - StackGuard;
1034 oldbase = (byte*)gp->stackbase + sizeof(Stktop); 1107 oldbase = (byte*)gp->stackbase + sizeof(Stktop);
1035 oldsize = oldbase - oldstk; 1108 oldsize = oldbase - oldstk;
1036 newsize = oldsize / 2; 1109 newsize = oldsize / 2;
1037 if(newsize < FixedStack) 1110 if(newsize < FixedStack)
1038 return; // don't shrink below the minimum-sized stack 1111 return; // don't shrink below the minimum-sized stack
1039 used = oldbase - (byte*)gp->sched.sp; 1112 used = oldbase - (byte*)gp->sched.sp;
1040 if(used >= oldsize / 4) 1113 if(used >= oldsize / 4)
1041 return; // still using at least 1/4 of the segment. 1114 return; // still using at least 1/4 of the segment.
1042 1115
1043 if(gp->syscallstack != (uintptr)nil) // TODO: can we handle this case? 1116 if(gp->syscallstack != (uintptr)nil) // TODO: can we handle this case?
1044 return; 1117 return;
1045 #ifdef GOOS_windows 1118 #ifdef GOOS_windows
1046 if(gp->m != nil && gp->m->libcallsp != 0) 1119 if(gp->m != nil && gp->m->libcallsp != 0)
1047 return; 1120 return;
1048 #endif 1121 #endif
1122 if(StackDebug > 0)
1123 runtime·printf("shrinking stack %D->%D\n", (uint64)oldsize, (uin t64)newsize);
1049 nframes = copyabletopsegment(gp); 1124 nframes = copyabletopsegment(gp);
1050 if(nframes == -1) 1125 if(nframes == -1)
1051 return; 1126 return;
1052 copystack(gp, nframes, newsize); 1127 copystack(gp, nframes, newsize);
1053 } 1128 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b