github.com/golang/gofrontend@v0.0.0-20240429183944-60f985a78526/libgo/runtime/proc.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <errno.h> 6 #include <limits.h> 7 #include <signal.h> 8 #include <stdlib.h> 9 #include <pthread.h> 10 #include <unistd.h> 11 12 #include "config.h" 13 14 #ifdef HAVE_DL_ITERATE_PHDR 15 #include <link.h> 16 #endif 17 18 #include "runtime.h" 19 #include "arch.h" 20 #include "defs.h" 21 22 #ifdef USING_SPLIT_STACK 23 24 /* FIXME: These are not declared anywhere. */ 25 26 extern void __splitstack_getcontext(void *context[10]); 27 28 extern void __splitstack_setcontext(void *context[10]); 29 30 extern void *__splitstack_makecontext(size_t, void *context[10], size_t *); 31 32 extern void * __splitstack_resetcontext(void *context[10], size_t *); 33 34 extern void __splitstack_releasecontext(void *context[10]); 35 36 extern void *__splitstack_find(void *, void *, size_t *, void **, void **, 37 void **); 38 39 extern void __splitstack_block_signals (int *, int *); 40 41 extern void __splitstack_block_signals_context (void *context[10], int *, 42 int *); 43 44 #endif 45 46 #ifndef PTHREAD_STACK_MIN 47 # define PTHREAD_STACK_MIN 8192 48 #endif 49 50 #if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK) 51 # define StackMin PTHREAD_STACK_MIN 52 #else 53 # define StackMin ((sizeof(char *) < 8) ? 2 * 1024 * 1024 : 4 * 1024 * 1024) 54 #endif 55 56 uintptr runtime_stacks_sys; 57 58 void gtraceback(G*) 59 __asm__(GOSYM_PREFIX "runtime.gtraceback"); 60 61 static void gscanstack(G*); 62 63 #ifdef __rtems__ 64 #define __thread 65 #endif 66 67 __thread G *g __asm__(GOSYM_PREFIX "runtime.g"); 68 69 #ifndef SETCONTEXT_CLOBBERS_TLS 70 71 static inline void 72 initcontext(void) 73 { 74 } 75 76 static inline void 77 fixcontext(__go_context_t *c __attribute__ ((unused))) 78 { 79 } 80 81 #else 82 83 # if defined(__x86_64__) && defined(__sun__) 84 85 // x86_64 Solaris 10 and 11 have a bug: setcontext switches the %fs 86 // register to that of the thread which called getcontext. The effect 87 // is that the address of all __thread variables changes. This bug 88 // also affects pthread_self() and pthread_getspecific. We work 89 // around it by clobbering the context field directly to keep %fs the 90 // same. 91 92 static __thread greg_t fs; 93 94 static inline void 95 initcontext(void) 96 { 97 ucontext_t c; 98 99 getcontext(&c); 100 fs = c.uc_mcontext.gregs[REG_FSBASE]; 101 } 102 103 static inline void 104 fixcontext(ucontext_t* c) 105 { 106 c->uc_mcontext.gregs[REG_FSBASE] = fs; 107 } 108 109 # elif defined(__NetBSD__) 110 111 // NetBSD has a bug: setcontext clobbers tlsbase, we need to save 112 // and restore it ourselves. 113 114 static __thread __greg_t tlsbase; 115 116 static inline void 117 initcontext(void) 118 { 119 ucontext_t c; 120 121 getcontext(&c); 122 tlsbase = c.uc_mcontext._mc_tlsbase; 123 } 124 125 static inline void 126 fixcontext(ucontext_t* c) 127 { 128 c->uc_mcontext._mc_tlsbase = tlsbase; 129 } 130 131 # elif defined(__sparc__) 132 133 static inline void 134 initcontext(void) 135 { 136 } 137 138 static inline void 139 fixcontext(ucontext_t *c) 140 { 141 /* ??? Using 142 register unsigned long thread __asm__("%g7"); 143 c->uc_mcontext.gregs[REG_G7] = thread; 144 results in 145 error: variable ‘thread’ might be clobbered by \ 146 ‘longjmp’ or ‘vfork’ [-Werror=clobbered] 147 which ought to be false, as %g7 is a fixed register. */ 148 149 if (sizeof (c->uc_mcontext.gregs[REG_G7]) == 8) 150 asm ("stx %%g7, %0" : "=m"(c->uc_mcontext.gregs[REG_G7])); 151 else 152 asm ("st %%g7, %0" : "=m"(c->uc_mcontext.gregs[REG_G7])); 153 } 154 155 # elif defined(_AIX) 156 157 static inline void 158 initcontext(void) 159 { 160 } 161 162 static inline void 163 fixcontext(ucontext_t* c) 164 { 165 // Thread pointer is in r13, per 64-bit ABI. 166 if (sizeof (c->uc_mcontext.jmp_context.gpr[13]) == 8) 167 asm ("std 13, %0" : "=m"(c->uc_mcontext.jmp_context.gpr[13])); 168 } 169 170 # else 171 172 # error unknown case for SETCONTEXT_CLOBBERS_TLS 173 174 # endif 175 176 #endif 177 178 // ucontext_arg returns a properly aligned ucontext_t value. On some 179 // systems a ucontext_t value must be aligned to a 16-byte boundary. 180 // The g structure that has fields of type ucontext_t is defined in 181 // Go, and Go has no simple way to align a field to such a boundary. 182 // So we make the field larger in runtime2.go and pick an appropriate 183 // offset within the field here. 184 static __go_context_t* 185 ucontext_arg(uintptr_t* go_ucontext) 186 { 187 uintptr_t p = (uintptr_t)go_ucontext; 188 size_t align = __alignof__(__go_context_t); 189 if(align > 16) { 190 // We only ensured space for up to a 16 byte alignment 191 // in libgo/go/runtime/runtime2.go. 192 runtime_throw("required alignment of __go_context_t too large"); 193 } 194 p = (p + align - 1) &~ (uintptr_t)(align - 1); 195 return (__go_context_t*)p; 196 } 197 198 // We can not always refer to the TLS variables directly. The 199 // compiler will call tls_get_addr to get the address of the variable, 200 // and it may hold it in a register across a call to schedule. When 201 // we get back from the call we may be running in a different thread, 202 // in which case the register now points to the TLS variable for a 203 // different thread. We use non-inlinable functions to avoid this 204 // when necessary. 205 206 G* runtime_g(void) __attribute__ ((noinline, no_split_stack)); 207 208 G* 209 runtime_g(void) 210 { 211 return g; 212 } 213 214 M* runtime_m(void) __attribute__ ((noinline, no_split_stack)); 215 216 M* 217 runtime_m(void) 218 { 219 if(g == nil) 220 return nil; 221 return g->m; 222 } 223 224 // Set g. 225 226 void runtime_setg(G*) __attribute__ ((no_split_stack)); 227 228 void 229 runtime_setg(G* gp) 230 { 231 g = gp; 232 } 233 234 void runtime_newosproc(M *) 235 __asm__(GOSYM_PREFIX "runtime.newosproc"); 236 237 // Start a new thread. 238 void 239 runtime_newosproc(M *mp) 240 { 241 pthread_attr_t attr; 242 sigset_t clear, old; 243 pthread_t tid; 244 int tries; 245 int ret; 246 247 if(pthread_attr_init(&attr) != 0) 248 runtime_throw("pthread_attr_init"); 249 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) 250 runtime_throw("pthread_attr_setdetachstate"); 251 252 // Block signals during pthread_create so that the new thread 253 // starts with signals disabled. It will enable them in minit. 254 sigfillset(&clear); 255 256 #ifdef SIGTRAP 257 // Blocking SIGTRAP reportedly breaks gdb on Alpha GNU/Linux. 258 sigdelset(&clear, SIGTRAP); 259 #endif 260 261 sigemptyset(&old); 262 pthread_sigmask(SIG_BLOCK, &clear, &old); 263 264 for (tries = 0; tries < 20; tries++) { 265 ret = pthread_create(&tid, &attr, runtime_mstart, mp); 266 if (ret != EAGAIN) { 267 break; 268 } 269 runtime_usleep((tries + 1) * 1000); // Milliseconds. 270 } 271 272 pthread_sigmask(SIG_SETMASK, &old, nil); 273 274 if (ret != 0) { 275 runtime_printf("pthread_create failed: %d\n", ret); 276 runtime_throw("pthread_create"); 277 } 278 279 if(pthread_attr_destroy(&attr) != 0) 280 runtime_throw("pthread_attr_destroy"); 281 } 282 283 // Switch context to a different goroutine. This is like longjmp. 284 void runtime_gogo(G*) __attribute__ ((noinline)); 285 void 286 runtime_gogo(G* newg) 287 { 288 #ifdef USING_SPLIT_STACK 289 __splitstack_setcontext((void*)(&newg->stackcontext[0])); 290 #endif 291 g = newg; 292 newg->fromgogo = true; 293 fixcontext(ucontext_arg(&newg->context[0])); 294 __go_setcontext(ucontext_arg(&newg->context[0])); 295 runtime_throw("gogo setcontext returned"); 296 } 297 298 // Save context and call fn passing g as a parameter. This is like 299 // setjmp. Because getcontext always returns 0, unlike setjmp, we use 300 // g->fromgogo as a code. It will be true if we got here via 301 // setcontext. g == nil the first time this is called in a new m. 302 void runtime_mcall(FuncVal *) __attribute__ ((noinline)); 303 void 304 runtime_mcall(FuncVal *fv) 305 { 306 M *mp; 307 G *gp; 308 #ifndef USING_SPLIT_STACK 309 void *afterregs; 310 #endif 311 312 // Ensure that all registers are on the stack for the garbage 313 // collector. 314 __builtin_unwind_init(); 315 flush_registers_to_secondary_stack(); 316 317 gp = g; 318 mp = gp->m; 319 if(gp == mp->g0) 320 runtime_throw("runtime: mcall called on m->g0 stack"); 321 322 if(gp != nil) { 323 324 #ifdef USING_SPLIT_STACK 325 __splitstack_getcontext((void*)(&gp->stackcontext[0])); 326 #else 327 // We have to point to an address on the stack that is 328 // below the saved registers. 329 gp->gcnextsp = (uintptr)(&afterregs); 330 gp->gcnextsp2 = (uintptr)(secondary_stack_pointer()); 331 #endif 332 gp->fromgogo = false; 333 __go_getcontext(ucontext_arg(&gp->context[0])); 334 335 // When we return from getcontext, we may be running 336 // in a new thread. That means that g may have 337 // changed. It is a global variables so we will 338 // reload it, but the address of g may be cached in 339 // our local stack frame, and that address may be 340 // wrong. Call the function to reload the value for 341 // this thread. 342 gp = runtime_g(); 343 mp = gp->m; 344 345 if(gp->traceback != 0) 346 gtraceback(gp); 347 if(gp->scang != 0) 348 gscanstack(gp); 349 } 350 if (gp == nil || !gp->fromgogo) { 351 #ifdef USING_SPLIT_STACK 352 __splitstack_setcontext((void*)(&mp->g0->stackcontext[0])); 353 #endif 354 mp->g0->entry = fv; 355 mp->g0->param = gp; 356 357 // It's OK to set g directly here because this case 358 // can not occur if we got here via a setcontext to 359 // the getcontext call just above. 360 g = mp->g0; 361 362 fixcontext(ucontext_arg(&mp->g0->context[0])); 363 __go_setcontext(ucontext_arg(&mp->g0->context[0])); 364 runtime_throw("runtime: mcall function returned"); 365 } 366 } 367 368 // Goroutine scheduler 369 // The scheduler's job is to distribute ready-to-run goroutines over worker threads. 370 // 371 // The main concepts are: 372 // G - goroutine. 373 // M - worker thread, or machine. 374 // P - processor, a resource that is required to execute Go code. 375 // M must have an associated P to execute Go code, however it can be 376 // blocked or in a syscall w/o an associated P. 377 // 378 // Design doc at http://golang.org/s/go11sched. 379 380 extern G* allocg(void) 381 __asm__ (GOSYM_PREFIX "runtime.allocg"); 382 383 bool runtime_isarchive; 384 385 extern void kickoff(void) 386 __asm__(GOSYM_PREFIX "runtime.kickoff"); 387 extern void minit(void) 388 __asm__(GOSYM_PREFIX "runtime.minit"); 389 extern void mstart1() 390 __asm__(GOSYM_PREFIX "runtime.mstart1"); 391 extern void stopm(void) 392 __asm__(GOSYM_PREFIX "runtime.stopm"); 393 extern void mexit(bool) 394 __asm__(GOSYM_PREFIX "runtime.mexit"); 395 extern void handoffp(P*) 396 __asm__(GOSYM_PREFIX "runtime.handoffp"); 397 extern void wakep(void) 398 __asm__(GOSYM_PREFIX "runtime.wakep"); 399 extern void stoplockedm(void) 400 __asm__(GOSYM_PREFIX "runtime.stoplockedm"); 401 extern void schedule(void) 402 __asm__(GOSYM_PREFIX "runtime.schedule"); 403 extern void execute(G*, bool) 404 __asm__(GOSYM_PREFIX "runtime.execute"); 405 extern void reentersyscall(uintptr, uintptr) 406 __asm__(GOSYM_PREFIX "runtime.reentersyscall"); 407 extern void reentersyscallblock(uintptr, uintptr) 408 __asm__(GOSYM_PREFIX "runtime.reentersyscallblock"); 409 extern G* gfget(P*) 410 __asm__(GOSYM_PREFIX "runtime.gfget"); 411 extern void acquirep(P*) 412 __asm__(GOSYM_PREFIX "runtime.acquirep"); 413 extern P* releasep(void) 414 __asm__(GOSYM_PREFIX "runtime.releasep"); 415 extern void incidlelocked(int32) 416 __asm__(GOSYM_PREFIX "runtime.incidlelocked"); 417 extern void globrunqput(G*) 418 __asm__(GOSYM_PREFIX "runtime.globrunqput"); 419 extern P* pidleget(void) 420 __asm__(GOSYM_PREFIX "runtime.pidleget"); 421 extern struct mstats* getMemstats(void) 422 __asm__(GOSYM_PREFIX "runtime.getMemstats"); 423 424 bool runtime_isstarted; 425 426 // Used to determine the field alignment. 427 428 struct field_align 429 { 430 char c; 431 Hchan *p; 432 }; 433 434 void getTraceback(G*, G*) __asm__(GOSYM_PREFIX "runtime.getTraceback"); 435 436 // getTraceback stores a traceback of gp in the g's traceback field 437 // and then returns to me. We expect that gp's traceback is not nil. 438 // It works by saving me's current context, and checking gp's traceback field. 439 // If gp's traceback field is not nil, it starts running gp. 440 // In places where we call getcontext, we check the traceback field. 441 // If it is not nil, we collect a traceback, and then return to the 442 // goroutine stored in the traceback field, which is me. 443 void getTraceback(G* me, G* gp) 444 { 445 M* holdm; 446 447 holdm = gp->m; 448 gp->m = me->m; 449 450 #ifdef USING_SPLIT_STACK 451 __splitstack_getcontext((void*)(&me->stackcontext[0])); 452 #endif 453 __go_getcontext(ucontext_arg(&me->context[0])); 454 455 if (gp->traceback != 0) { 456 runtime_gogo(gp); 457 } 458 459 gp->m = holdm; 460 } 461 462 // Do a stack trace of gp, and then restore the context to 463 // gp->traceback->gp. 464 465 void 466 gtraceback(G* gp) 467 { 468 Traceback* traceback; 469 470 traceback = (Traceback*)gp->traceback; 471 gp->traceback = 0; 472 traceback->c = runtime_callers(1, traceback->locbuf, 473 sizeof traceback->locbuf / sizeof traceback->locbuf[0], false); 474 runtime_gogo(traceback->gp); 475 } 476 477 void doscanstackswitch(G*, G*) __asm__(GOSYM_PREFIX "runtime.doscanstackswitch"); 478 479 // Switch to gp and let it scan its stack. 480 // The first time gp->scang is set (to me). The second time here 481 // gp is done scanning, and has unset gp->scang, so we just return. 482 void 483 doscanstackswitch(G* me, G* gp) 484 { 485 M* holdm; 486 487 __go_assert(me->entry == nil); 488 me->fromgogo = false; 489 490 holdm = gp->m; 491 gp->m = me->m; 492 493 #ifdef USING_SPLIT_STACK 494 __splitstack_getcontext((void*)(&me->stackcontext[0])); 495 #endif 496 __go_getcontext(ucontext_arg(&me->context[0])); 497 498 if(me->entry != nil) { 499 // Got here from mcall. 500 // The stack scanning code may call systemstack, which calls 501 // mcall, which calls setcontext. 502 // Run the function, which at the end will switch back to gp. 503 FuncVal *fv = me->entry; 504 void (*pfn)(G*) = (void (*)(G*))fv->fn; 505 G* gp1 = (G*)me->param; 506 __go_assert(gp1 == gp); 507 me->entry = nil; 508 me->param = nil; 509 __builtin_call_with_static_chain(pfn(gp1), fv); 510 abort(); 511 } 512 513 if (gp->scang != 0) 514 runtime_gogo(gp); 515 516 gp->m = holdm; 517 } 518 519 // Do a stack scan, then switch back to the g that triggers this scan. 520 // We come here from doscanstackswitch. 521 static void 522 gscanstack(G *gp) 523 { 524 G *oldg, *oldcurg; 525 526 oldg = (G*)gp->scang; 527 oldcurg = oldg->m->curg; 528 oldg->m->curg = gp; 529 gp->scang = 0; 530 531 doscanstack(gp, (void*)gp->scangcw); 532 533 gp->scangcw = 0; 534 oldg->m->curg = oldcurg; 535 runtime_gogo(oldg); 536 } 537 538 // Called by pthread_create to start an M. 539 void* 540 runtime_mstart(void *arg) 541 { 542 M* mp; 543 G* gp; 544 545 mp = (M*)(arg); 546 gp = mp->g0; 547 gp->m = mp; 548 549 g = gp; 550 551 gp->entry = nil; 552 gp->param = nil; 553 554 // We have to call minit before we call getcontext, 555 // because getcontext will copy the signal mask. 556 minit(); 557 558 initcontext(); 559 560 // Record top of stack for use by mcall. 561 // Once we call schedule we're never coming back, 562 // so other calls can reuse this stack space. 563 #ifdef USING_SPLIT_STACK 564 __splitstack_getcontext((void*)(&gp->stackcontext[0])); 565 #else 566 gp->gcinitialsp = &arg; 567 // Setting gcstacksize to 0 is a marker meaning that gcinitialsp 568 // is the top of the stack, not the bottom. 569 gp->gcstacksize = 0; 570 gp->gcnextsp = (uintptr)(&arg); 571 gp->gcinitialsp2 = secondary_stack_pointer(); 572 gp->gcnextsp2 = (uintptr)(gp->gcinitialsp2); 573 #endif 574 575 // Save the currently active context. This will return 576 // multiple times via the setcontext call in mcall. 577 __go_getcontext(ucontext_arg(&gp->context[0])); 578 579 if(gp->traceback != 0) { 580 // Got here from getTraceback. 581 // I'm not sure this ever actually happens--getTraceback 582 // may always go to the getcontext call in mcall. 583 gtraceback(gp); 584 } 585 if(gp->scang != 0) 586 // Got here from doscanswitch. Should not happen. 587 runtime_throw("mstart with scang"); 588 589 if(gp->entry != nil) { 590 // Got here from mcall. 591 FuncVal *fv = gp->entry; 592 void (*pfn)(G*) = (void (*)(G*))fv->fn; 593 G* gp1 = (G*)gp->param; 594 gp->entry = nil; 595 gp->param = nil; 596 __builtin_call_with_static_chain(pfn(gp1), fv); 597 abort(); 598 } 599 600 if(mp->exiting) { 601 mexit(true); 602 return nil; 603 } 604 605 // Initial call to getcontext--starting thread. 606 607 #ifdef USING_SPLIT_STACK 608 { 609 int dont_block_signals = 0; 610 __splitstack_block_signals(&dont_block_signals, nil); 611 } 612 #endif 613 614 mstart1(); 615 616 // mstart1 does not return, but we need a return statement 617 // here to avoid a compiler warning. 618 return nil; 619 } 620 621 typedef struct CgoThreadStart CgoThreadStart; 622 struct CgoThreadStart 623 { 624 M *m; 625 G *g; 626 uintptr *tls; 627 void (*fn)(void); 628 }; 629 630 void setGContext(void) __asm__ (GOSYM_PREFIX "runtime.setGContext"); 631 632 // setGContext sets up a new goroutine context for the current g. 633 void 634 setGContext(void) 635 { 636 int val; 637 G *gp; 638 639 initcontext(); 640 gp = g; 641 gp->entry = nil; 642 gp->param = nil; 643 #ifdef USING_SPLIT_STACK 644 __splitstack_getcontext((void*)(&gp->stackcontext[0])); 645 val = 0; 646 __splitstack_block_signals(&val, nil); 647 #else 648 gp->gcinitialsp = &val; 649 gp->gcstack = 0; 650 gp->gcstacksize = 0; 651 gp->gcnextsp = (uintptr)(&val); 652 gp->gcinitialsp2 = secondary_stack_pointer(); 653 gp->gcnextsp2 = (uintptr)(gp->gcinitialsp2); 654 #endif 655 __go_getcontext(ucontext_arg(&gp->context[0])); 656 657 if(gp->entry != nil) { 658 // Got here from mcall. 659 FuncVal *fv = gp->entry; 660 void (*pfn)(G*) = (void (*)(G*))fv->fn; 661 G* gp1 = (G*)gp->param; 662 gp->entry = nil; 663 gp->param = nil; 664 __builtin_call_with_static_chain(pfn(gp1), fv); 665 abort(); 666 } 667 } 668 669 void makeGContext(G*, byte*, uintptr) 670 __asm__(GOSYM_PREFIX "runtime.makeGContext"); 671 672 // makeGContext makes a new context for a g. 673 void 674 makeGContext(G* gp, byte* sp, uintptr spsize) { 675 __go_context_t *uc; 676 677 uc = ucontext_arg(&gp->context[0]); 678 __go_getcontext(uc); 679 __go_makecontext(uc, kickoff, sp, (size_t)spsize); 680 } 681 682 // The goroutine g is about to enter a system call. 683 // Record that it's not using the cpu anymore. 684 // This is called only from the go syscall library and cgocall, 685 // not from the low-level system calls used by the runtime. 686 // 687 // Entersyscall cannot split the stack: the runtime_gosave must 688 // make g->sched refer to the caller's stack segment, because 689 // entersyscall is going to return immediately after. 690 691 void runtime_entersyscall() __attribute__ ((no_split_stack)); 692 static void doentersyscall(uintptr, uintptr) 693 __attribute__ ((no_split_stack, noinline)); 694 695 void 696 runtime_entersyscall() 697 { 698 // Save the registers in the g structure so that any pointers 699 // held in registers will be seen by the garbage collector. 700 if (!runtime_usestackmaps) 701 __go_getcontext(ucontext_arg(&g->gcregs[0])); 702 703 // Note that if this function does save any registers itself, 704 // we might store the wrong value in the call to getcontext. 705 // FIXME: This assumes that we do not need to save any 706 // callee-saved registers to access the TLS variable g. We 707 // don't want to put the ucontext_t on the stack because it is 708 // large and we can not split the stack here. 709 doentersyscall((uintptr)runtime_getcallerpc(), 710 (uintptr)runtime_getcallersp()); 711 } 712 713 static void 714 doentersyscall(uintptr pc, uintptr sp) 715 { 716 // Leave SP around for GC and traceback. 717 #ifdef USING_SPLIT_STACK 718 { 719 size_t gcstacksize; 720 g->gcstack = (uintptr)(__splitstack_find(nil, nil, &gcstacksize, 721 (void**)(&g->gcnextsegment), 722 (void**)(&g->gcnextsp), 723 &g->gcinitialsp)); 724 g->gcstacksize = (uintptr)gcstacksize; 725 } 726 #else 727 { 728 void *v; 729 730 g->gcnextsp = (uintptr)(&v); 731 g->gcnextsp2 = (uintptr)(secondary_stack_pointer()); 732 } 733 #endif 734 735 reentersyscall(pc, sp); 736 } 737 738 static void doentersyscallblock(uintptr, uintptr) 739 __attribute__ ((no_split_stack, noinline)); 740 741 // The same as runtime_entersyscall(), but with a hint that the syscall is blocking. 742 void 743 runtime_entersyscallblock() 744 { 745 // Save the registers in the g structure so that any pointers 746 // held in registers will be seen by the garbage collector. 747 if (!runtime_usestackmaps) 748 __go_getcontext(ucontext_arg(&g->gcregs[0])); 749 750 // See comment in runtime_entersyscall. 751 doentersyscallblock((uintptr)runtime_getcallerpc(), 752 (uintptr)runtime_getcallersp()); 753 } 754 755 static void 756 doentersyscallblock(uintptr pc, uintptr sp) 757 { 758 // Leave SP around for GC and traceback. 759 #ifdef USING_SPLIT_STACK 760 { 761 size_t gcstacksize; 762 g->gcstack = (uintptr)(__splitstack_find(nil, nil, &gcstacksize, 763 (void**)(&g->gcnextsegment), 764 (void**)(&g->gcnextsp), 765 &g->gcinitialsp)); 766 g->gcstacksize = (uintptr)gcstacksize; 767 } 768 #else 769 { 770 void *v; 771 772 g->gcnextsp = (uintptr)(&v); 773 g->gcnextsp2 = (uintptr)(secondary_stack_pointer()); 774 } 775 #endif 776 777 reentersyscallblock(pc, sp); 778 } 779 780 // Allocate a new g, with a stack big enough for stacksize bytes. 781 G* 782 runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* ret_stacksize) 783 { 784 uintptr stacksize; 785 G *newg; 786 byte* unused_stack; 787 uintptr unused_stacksize; 788 #ifdef USING_SPLIT_STACK 789 int dont_block_signals = 0; 790 size_t ss_stacksize; 791 #endif 792 793 if (ret_stack == nil) { 794 ret_stack = &unused_stack; 795 } 796 if (ret_stacksize == nil) { 797 ret_stacksize = &unused_stacksize; 798 } 799 newg = allocg(); 800 if(allocatestack) { 801 stacksize = StackMin; 802 if(signalstack) { 803 stacksize = 32 * 1024; // OS X wants >= 8K, GNU/Linux >= 2K 804 #ifdef SIGSTKSZ 805 if(stacksize < (uintptr)(SIGSTKSZ)) 806 stacksize = (uintptr)(SIGSTKSZ); 807 #endif 808 } 809 810 #ifdef USING_SPLIT_STACK 811 *ret_stack = __splitstack_makecontext(stacksize, 812 (void*)(&newg->stackcontext[0]), 813 &ss_stacksize); 814 *ret_stacksize = (uintptr)ss_stacksize; 815 __splitstack_block_signals_context((void*)(&newg->stackcontext[0]), 816 &dont_block_signals, nil); 817 #else 818 // In 64-bit mode, the maximum Go allocation space is 819 // 128G. Our stack size is 4M, which only permits 32K 820 // goroutines. In order to not limit ourselves, 821 // allocate the stacks out of separate memory. In 822 // 32-bit mode, the Go allocation space is all of 823 // memory anyhow. 824 if(sizeof(void*) == 8) { 825 void *p = runtime_sysAlloc(stacksize, &getMemstats()->stacks_sys); 826 if(p == nil) 827 runtime_throw("runtime: cannot allocate memory for goroutine stack"); 828 *ret_stack = (byte*)p; 829 } else { 830 *ret_stack = runtime_mallocgc(stacksize, nil, false); 831 runtime_xadd(&runtime_stacks_sys, stacksize); 832 } 833 *ret_stacksize = (uintptr)stacksize; 834 newg->gcinitialsp = *ret_stack; 835 newg->gcstacksize = (uintptr)stacksize; 836 newg->gcinitialsp2 = initial_secondary_stack_pointer(*ret_stack); 837 #endif 838 } 839 return newg; 840 } 841 842 void stackfree(G*) 843 __asm__(GOSYM_PREFIX "runtime.stackfree"); 844 845 // stackfree frees the stack of a g. 846 void 847 stackfree(G* gp) 848 { 849 #ifdef USING_SPLIT_STACK 850 __splitstack_releasecontext((void*)(&gp->stackcontext[0])); 851 #else 852 // If gcstacksize is 0, the stack is allocated by libc and will be 853 // released when the thread exits. Otherwise, in 64-bit mode it was 854 // allocated using sysAlloc and in 32-bit mode it was allocated 855 // using garbage collected memory. 856 if (gp->gcstacksize != 0) { 857 if (sizeof(void*) == 8) { 858 runtime_sysFree(gp->gcinitialsp, gp->gcstacksize, &getMemstats()->stacks_sys); 859 } 860 gp->gcinitialsp = nil; 861 gp->gcstacksize = 0; 862 } 863 #endif 864 } 865 866 void resetNewG(G*, void **, uintptr*) 867 __asm__(GOSYM_PREFIX "runtime.resetNewG"); 868 869 // Reset stack information for g pulled out of the cache to start a 870 // new goroutine. 871 void 872 resetNewG(G *newg, void **sp, uintptr *spsize) 873 { 874 #ifdef USING_SPLIT_STACK 875 int dont_block_signals = 0; 876 size_t ss_spsize; 877 878 *sp = __splitstack_resetcontext((void*)(&newg->stackcontext[0]), &ss_spsize); 879 *spsize = ss_spsize; 880 __splitstack_block_signals_context((void*)(&newg->stackcontext[0]), 881 &dont_block_signals, nil); 882 #else 883 *sp = newg->gcinitialsp; 884 *spsize = newg->gcstacksize; 885 if(*spsize == 0) 886 runtime_throw("bad spsize in resetNewG"); 887 newg->gcnextsp = (uintptr)(*sp); 888 newg->gcnextsp2 = (uintptr)(newg->gcinitialsp2); 889 #endif 890 }