2018-01-15 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / runtime / proc.c
blob556d86fb7d6c8ab5f218a3ba65f15e10ff52a862
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.
5 #include <errno.h>
6 #include <limits.h>
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <pthread.h>
10 #include <unistd.h>
12 #include "config.h"
14 #ifdef HAVE_DL_ITERATE_PHDR
15 #include <link.h>
16 #endif
18 #include "runtime.h"
19 #include "arch.h"
20 #include "defs.h"
21 #include "go-type.h"
23 #ifdef USING_SPLIT_STACK
25 /* FIXME: These are not declared anywhere. */
27 extern void __splitstack_getcontext(void *context[10]);
29 extern void __splitstack_setcontext(void *context[10]);
31 extern void *__splitstack_makecontext(size_t, void *context[10], size_t *);
33 extern void * __splitstack_resetcontext(void *context[10], size_t *);
35 extern void __splitstack_releasecontext(void *context[10]);
37 extern void *__splitstack_find(void *, void *, size_t *, void **, void **,
38 void **);
40 extern void __splitstack_block_signals (int *, int *);
42 extern void __splitstack_block_signals_context (void *context[10], int *,
43 int *);
45 #endif
47 #ifndef PTHREAD_STACK_MIN
48 # define PTHREAD_STACK_MIN 8192
49 #endif
51 #if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
52 # define StackMin PTHREAD_STACK_MIN
53 #else
54 # define StackMin ((sizeof(char *) < 8) ? 2 * 1024 * 1024 : 4 * 1024 * 1024)
55 #endif
57 uintptr runtime_stacks_sys;
59 void gtraceback(G*)
60 __asm__(GOSYM_PREFIX "runtime.gtraceback");
62 #ifdef __rtems__
63 #define __thread
64 #endif
66 static __thread G *g;
68 #ifndef SETCONTEXT_CLOBBERS_TLS
70 static inline void
71 initcontext(void)
75 static inline void
76 fixcontext(ucontext_t *c __attribute__ ((unused)))
80 #else
82 # if defined(__x86_64__) && defined(__sun__)
84 // x86_64 Solaris 10 and 11 have a bug: setcontext switches the %fs
85 // register to that of the thread which called getcontext. The effect
86 // is that the address of all __thread variables changes. This bug
87 // also affects pthread_self() and pthread_getspecific. We work
88 // around it by clobbering the context field directly to keep %fs the
89 // same.
91 static __thread greg_t fs;
93 static inline void
94 initcontext(void)
96 ucontext_t c;
98 getcontext(&c);
99 fs = c.uc_mcontext.gregs[REG_FSBASE];
102 static inline void
103 fixcontext(ucontext_t* c)
105 c->uc_mcontext.gregs[REG_FSBASE] = fs;
108 # elif defined(__NetBSD__)
110 // NetBSD has a bug: setcontext clobbers tlsbase, we need to save
111 // and restore it ourselves.
113 static __thread __greg_t tlsbase;
115 static inline void
116 initcontext(void)
118 ucontext_t c;
120 getcontext(&c);
121 tlsbase = c.uc_mcontext._mc_tlsbase;
124 static inline void
125 fixcontext(ucontext_t* c)
127 c->uc_mcontext._mc_tlsbase = tlsbase;
130 # elif defined(__sparc__)
132 static inline void
133 initcontext(void)
137 static inline void
138 fixcontext(ucontext_t *c)
140 /* ??? Using
141 register unsigned long thread __asm__("%g7");
142 c->uc_mcontext.gregs[REG_G7] = thread;
143 results in
144 error: variable ‘thread’ might be clobbered by \
145 ‘longjmp’ or ‘vfork’ [-Werror=clobbered]
146 which ought to be false, as %g7 is a fixed register. */
148 if (sizeof (c->uc_mcontext.gregs[REG_G7]) == 8)
149 asm ("stx %%g7, %0" : "=m"(c->uc_mcontext.gregs[REG_G7]));
150 else
151 asm ("st %%g7, %0" : "=m"(c->uc_mcontext.gregs[REG_G7]));
154 # elif defined(_AIX)
156 static inline void
157 initcontext(void)
161 static inline void
162 fixcontext(ucontext_t* c)
164 // Thread pointer is in r13, per 64-bit ABI.
165 if (sizeof (c->uc_mcontext.jmp_context.gpr[13]) == 8)
166 asm ("std 13, %0" : "=m"(c->uc_mcontext.jmp_context.gpr[13]));
169 # else
171 # error unknown case for SETCONTEXT_CLOBBERS_TLS
173 # endif
175 #endif
177 // ucontext_arg returns a properly aligned ucontext_t value. On some
178 // systems a ucontext_t value must be aligned to a 16-byte boundary.
179 // The g structure that has fields of type ucontext_t is defined in
180 // Go, and Go has no simple way to align a field to such a boundary.
181 // So we make the field larger in runtime2.go and pick an appropriate
182 // offset within the field here.
183 static ucontext_t*
184 ucontext_arg(uintptr_t* go_ucontext)
186 uintptr_t p = (uintptr_t)go_ucontext;
187 size_t align = __alignof__(ucontext_t);
188 if(align > 16) {
189 // We only ensured space for up to a 16 byte alignment
190 // in libgo/go/runtime/runtime2.go.
191 runtime_throw("required alignment of ucontext_t too large");
193 p = (p + align - 1) &~ (uintptr_t)(align - 1);
194 return (ucontext_t*)p;
197 // We can not always refer to the TLS variables directly. The
198 // compiler will call tls_get_addr to get the address of the variable,
199 // and it may hold it in a register across a call to schedule. When
200 // we get back from the call we may be running in a different thread,
201 // in which case the register now points to the TLS variable for a
202 // different thread. We use non-inlinable functions to avoid this
203 // when necessary.
205 G* runtime_g(void) __attribute__ ((noinline, no_split_stack));
208 runtime_g(void)
210 return g;
213 M* runtime_m(void) __attribute__ ((noinline, no_split_stack));
216 runtime_m(void)
218 if(g == nil)
219 return nil;
220 return g->m;
223 // Set g.
224 void
225 runtime_setg(G* gp)
227 g = gp;
230 void runtime_newosproc(M *)
231 __asm__(GOSYM_PREFIX "runtime.newosproc");
233 // Start a new thread.
234 void
235 runtime_newosproc(M *mp)
237 pthread_attr_t attr;
238 sigset_t clear, old;
239 pthread_t tid;
240 int tries;
241 int ret;
243 if(pthread_attr_init(&attr) != 0)
244 runtime_throw("pthread_attr_init");
245 if(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
246 runtime_throw("pthread_attr_setdetachstate");
248 // Block signals during pthread_create so that the new thread
249 // starts with signals disabled. It will enable them in minit.
250 sigfillset(&clear);
252 #ifdef SIGTRAP
253 // Blocking SIGTRAP reportedly breaks gdb on Alpha GNU/Linux.
254 sigdelset(&clear, SIGTRAP);
255 #endif
257 sigemptyset(&old);
258 pthread_sigmask(SIG_BLOCK, &clear, &old);
260 for (tries = 0; tries < 20; tries++) {
261 ret = pthread_create(&tid, &attr, runtime_mstart, mp);
262 if (ret != EAGAIN) {
263 break;
265 runtime_usleep((tries + 1) * 1000); // Milliseconds.
268 pthread_sigmask(SIG_SETMASK, &old, nil);
270 if (ret != 0) {
271 runtime_printf("pthread_create failed: %d\n", ret);
272 runtime_throw("pthread_create");
275 if(pthread_attr_destroy(&attr) != 0)
276 runtime_throw("pthread_attr_destroy");
279 // Switch context to a different goroutine. This is like longjmp.
280 void runtime_gogo(G*) __attribute__ ((noinline));
281 void
282 runtime_gogo(G* newg)
284 #ifdef USING_SPLIT_STACK
285 __splitstack_setcontext((void*)(&newg->stackcontext[0]));
286 #endif
287 g = newg;
288 newg->fromgogo = true;
289 fixcontext(ucontext_arg(&newg->context[0]));
290 setcontext(ucontext_arg(&newg->context[0]));
291 runtime_throw("gogo setcontext returned");
294 // Save context and call fn passing g as a parameter. This is like
295 // setjmp. Because getcontext always returns 0, unlike setjmp, we use
296 // g->fromgogo as a code. It will be true if we got here via
297 // setcontext. g == nil the first time this is called in a new m.
298 void runtime_mcall(FuncVal *) __attribute__ ((noinline));
299 void
300 runtime_mcall(FuncVal *fv)
302 M *mp;
303 G *gp;
304 #ifndef USING_SPLIT_STACK
305 void *afterregs;
306 #endif
308 // Ensure that all registers are on the stack for the garbage
309 // collector.
310 __builtin_unwind_init();
312 gp = g;
313 mp = gp->m;
314 if(gp == mp->g0)
315 runtime_throw("runtime: mcall called on m->g0 stack");
317 if(gp != nil) {
319 #ifdef USING_SPLIT_STACK
320 __splitstack_getcontext((void*)(&g->stackcontext[0]));
321 #else
322 // We have to point to an address on the stack that is
323 // below the saved registers.
324 gp->gcnextsp = (uintptr)(&afterregs);
325 #endif
326 gp->fromgogo = false;
327 getcontext(ucontext_arg(&gp->context[0]));
329 // When we return from getcontext, we may be running
330 // in a new thread. That means that g may have
331 // changed. It is a global variables so we will
332 // reload it, but the address of g may be cached in
333 // our local stack frame, and that address may be
334 // wrong. Call the function to reload the value for
335 // this thread.
336 gp = runtime_g();
337 mp = gp->m;
339 if(gp->traceback != nil)
340 gtraceback(gp);
342 if (gp == nil || !gp->fromgogo) {
343 #ifdef USING_SPLIT_STACK
344 __splitstack_setcontext((void*)(&mp->g0->stackcontext[0]));
345 #endif
346 mp->g0->entry = fv;
347 mp->g0->param = gp;
349 // It's OK to set g directly here because this case
350 // can not occur if we got here via a setcontext to
351 // the getcontext call just above.
352 g = mp->g0;
354 fixcontext(ucontext_arg(&mp->g0->context[0]));
355 setcontext(ucontext_arg(&mp->g0->context[0]));
356 runtime_throw("runtime: mcall function returned");
360 // Goroutine scheduler
361 // The scheduler's job is to distribute ready-to-run goroutines over worker threads.
363 // The main concepts are:
364 // G - goroutine.
365 // M - worker thread, or machine.
366 // P - processor, a resource that is required to execute Go code.
367 // M must have an associated P to execute Go code, however it can be
368 // blocked or in a syscall w/o an associated P.
370 // Design doc at http://golang.org/s/go11sched.
372 extern G* allocg(void)
373 __asm__ (GOSYM_PREFIX "runtime.allocg");
375 Sched* runtime_sched;
377 bool runtime_isarchive;
379 extern void kickoff(void)
380 __asm__(GOSYM_PREFIX "runtime.kickoff");
381 extern void minit(void)
382 __asm__(GOSYM_PREFIX "runtime.minit");
383 extern void mstart1(int32)
384 __asm__(GOSYM_PREFIX "runtime.mstart1");
385 extern void stopm(void)
386 __asm__(GOSYM_PREFIX "runtime.stopm");
387 extern void mexit(bool)
388 __asm__(GOSYM_PREFIX "runtime.mexit");
389 extern void handoffp(P*)
390 __asm__(GOSYM_PREFIX "runtime.handoffp");
391 extern void wakep(void)
392 __asm__(GOSYM_PREFIX "runtime.wakep");
393 extern void stoplockedm(void)
394 __asm__(GOSYM_PREFIX "runtime.stoplockedm");
395 extern void schedule(void)
396 __asm__(GOSYM_PREFIX "runtime.schedule");
397 extern void execute(G*, bool)
398 __asm__(GOSYM_PREFIX "runtime.execute");
399 extern void reentersyscall(uintptr, uintptr)
400 __asm__(GOSYM_PREFIX "runtime.reentersyscall");
401 extern void reentersyscallblock(uintptr, uintptr)
402 __asm__(GOSYM_PREFIX "runtime.reentersyscallblock");
403 extern G* gfget(P*)
404 __asm__(GOSYM_PREFIX "runtime.gfget");
405 extern void acquirep(P*)
406 __asm__(GOSYM_PREFIX "runtime.acquirep");
407 extern P* releasep(void)
408 __asm__(GOSYM_PREFIX "runtime.releasep");
409 extern void incidlelocked(int32)
410 __asm__(GOSYM_PREFIX "runtime.incidlelocked");
411 extern void globrunqput(G*)
412 __asm__(GOSYM_PREFIX "runtime.globrunqput");
413 extern P* pidleget(void)
414 __asm__(GOSYM_PREFIX "runtime.pidleget");
415 extern struct mstats* getMemstats(void)
416 __asm__(GOSYM_PREFIX "runtime.getMemstats");
418 bool runtime_isstarted;
420 // Used to determine the field alignment.
422 struct field_align
424 char c;
425 Hchan *p;
428 void getTraceback(G*, G*) __asm__(GOSYM_PREFIX "runtime.getTraceback");
430 // getTraceback stores a traceback of gp in the g's traceback field
431 // and then returns to me. We expect that gp's traceback is not nil.
432 // It works by saving me's current context, and checking gp's traceback field.
433 // If gp's traceback field is not nil, it starts running gp.
434 // In places where we call getcontext, we check the traceback field.
435 // If it is not nil, we collect a traceback, and then return to the
436 // goroutine stored in the traceback field, which is me.
437 void getTraceback(G* me, G* gp)
439 #ifdef USING_SPLIT_STACK
440 __splitstack_getcontext((void*)(&me->stackcontext[0]));
441 #endif
442 getcontext(ucontext_arg(&me->context[0]));
444 if (gp->traceback != nil) {
445 runtime_gogo(gp);
449 // Do a stack trace of gp, and then restore the context to
450 // gp->traceback->gp.
452 void
453 gtraceback(G* gp)
455 Traceback* traceback;
456 M* holdm;
458 traceback = gp->traceback;
459 gp->traceback = nil;
460 holdm = gp->m;
461 if(holdm != nil && holdm != g->m)
462 runtime_throw("gtraceback: m is not nil");
463 gp->m = traceback->gp->m;
464 traceback->c = runtime_callers(1, traceback->locbuf,
465 sizeof traceback->locbuf / sizeof traceback->locbuf[0], false);
466 gp->m = holdm;
467 runtime_gogo(traceback->gp);
470 // Called by pthread_create to start an M.
471 void*
472 runtime_mstart(void *arg)
474 M* mp;
475 G* gp;
477 mp = (M*)(arg);
478 gp = mp->g0;
479 gp->m = mp;
481 g = gp;
483 gp->entry = nil;
484 gp->param = nil;
486 // We have to call minit before we call getcontext,
487 // because getcontext will copy the signal mask.
488 minit();
490 initcontext();
492 // Record top of stack for use by mcall.
493 // Once we call schedule we're never coming back,
494 // so other calls can reuse this stack space.
495 #ifdef USING_SPLIT_STACK
496 __splitstack_getcontext((void*)(&gp->stackcontext[0]));
497 #else
498 gp->gcinitialsp = &arg;
499 // Setting gcstacksize to 0 is a marker meaning that gcinitialsp
500 // is the top of the stack, not the bottom.
501 gp->gcstacksize = 0;
502 gp->gcnextsp = (uintptr)(&arg);
503 #endif
505 // Save the currently active context. This will return
506 // multiple times via the setcontext call in mcall.
507 getcontext(ucontext_arg(&gp->context[0]));
509 if(gp->traceback != nil) {
510 // Got here from getTraceback.
511 // I'm not sure this ever actually happens--getTraceback
512 // may always go to the getcontext call in mcall.
513 gtraceback(gp);
516 if(gp->entry != nil) {
517 // Got here from mcall.
518 FuncVal *fv = gp->entry;
519 void (*pfn)(G*) = (void (*)(G*))fv->fn;
520 G* gp1 = (G*)gp->param;
521 gp->entry = nil;
522 gp->param = nil;
523 __builtin_call_with_static_chain(pfn(gp1), fv);
524 *(int*)0x21 = 0x21;
527 if(mp->exiting) {
528 mexit(true);
529 return nil;
532 // Initial call to getcontext--starting thread.
534 #ifdef USING_SPLIT_STACK
536 int dont_block_signals = 0;
537 __splitstack_block_signals(&dont_block_signals, nil);
539 #endif
541 mstart1(0);
543 // mstart1 does not return, but we need a return statement
544 // here to avoid a compiler warning.
545 return nil;
548 typedef struct CgoThreadStart CgoThreadStart;
549 struct CgoThreadStart
551 M *m;
552 G *g;
553 uintptr *tls;
554 void (*fn)(void);
557 void setGContext(void) __asm__ (GOSYM_PREFIX "runtime.setGContext");
559 // setGContext sets up a new goroutine context for the current g.
560 void
561 setGContext(void)
563 int val;
564 G *gp;
566 initcontext();
567 gp = g;
568 gp->entry = nil;
569 gp->param = nil;
570 #ifdef USING_SPLIT_STACK
571 __splitstack_getcontext((void*)(&gp->stackcontext[0]));
572 val = 0;
573 __splitstack_block_signals(&val, nil);
574 #else
575 gp->gcinitialsp = &val;
576 gp->gcstack = 0;
577 gp->gcstacksize = 0;
578 gp->gcnextsp = (uintptr)(&val);
579 #endif
580 getcontext(ucontext_arg(&gp->context[0]));
582 if(gp->entry != nil) {
583 // Got here from mcall.
584 FuncVal *fv = gp->entry;
585 void (*pfn)(G*) = (void (*)(G*))fv->fn;
586 G* gp1 = (G*)gp->param;
587 gp->entry = nil;
588 gp->param = nil;
589 __builtin_call_with_static_chain(pfn(gp1), fv);
590 *(int*)0x22 = 0x22;
594 void makeGContext(G*, byte*, uintptr)
595 __asm__(GOSYM_PREFIX "runtime.makeGContext");
597 // makeGContext makes a new context for a g.
598 void
599 makeGContext(G* gp, byte* sp, uintptr spsize) {
600 ucontext_t *uc;
602 uc = ucontext_arg(&gp->context[0]);
603 getcontext(uc);
604 uc->uc_stack.ss_sp = sp;
605 uc->uc_stack.ss_size = (size_t)spsize;
606 makecontext(uc, kickoff, 0);
609 // The goroutine g is about to enter a system call.
610 // Record that it's not using the cpu anymore.
611 // This is called only from the go syscall library and cgocall,
612 // not from the low-level system calls used by the runtime.
614 // Entersyscall cannot split the stack: the runtime_gosave must
615 // make g->sched refer to the caller's stack segment, because
616 // entersyscall is going to return immediately after.
618 void runtime_entersyscall(int32) __attribute__ ((no_split_stack));
619 static void doentersyscall(uintptr, uintptr)
620 __attribute__ ((no_split_stack, noinline));
622 void
623 runtime_entersyscall(int32 dummy __attribute__ ((unused)))
625 // Save the registers in the g structure so that any pointers
626 // held in registers will be seen by the garbage collector.
627 getcontext(ucontext_arg(&g->gcregs[0]));
629 // Note that if this function does save any registers itself,
630 // we might store the wrong value in the call to getcontext.
631 // FIXME: This assumes that we do not need to save any
632 // callee-saved registers to access the TLS variable g. We
633 // don't want to put the ucontext_t on the stack because it is
634 // large and we can not split the stack here.
635 doentersyscall((uintptr)runtime_getcallerpc(&dummy),
636 (uintptr)runtime_getcallersp(&dummy));
639 static void
640 doentersyscall(uintptr pc, uintptr sp)
642 // Leave SP around for GC and traceback.
643 #ifdef USING_SPLIT_STACK
645 size_t gcstacksize;
646 g->gcstack = (uintptr)(__splitstack_find(nil, nil, &gcstacksize,
647 (void**)(&g->gcnextsegment),
648 (void**)(&g->gcnextsp),
649 &g->gcinitialsp));
650 g->gcstacksize = (uintptr)gcstacksize;
652 #else
654 void *v;
656 g->gcnextsp = (uintptr)(&v);
658 #endif
660 reentersyscall(pc, sp);
663 static void doentersyscallblock(uintptr, uintptr)
664 __attribute__ ((no_split_stack, noinline));
666 // The same as runtime_entersyscall(), but with a hint that the syscall is blocking.
667 void
668 runtime_entersyscallblock(int32 dummy __attribute__ ((unused)))
670 // Save the registers in the g structure so that any pointers
671 // held in registers will be seen by the garbage collector.
672 getcontext(ucontext_arg(&g->gcregs[0]));
674 // See comment in runtime_entersyscall.
675 doentersyscallblock((uintptr)runtime_getcallerpc(&dummy),
676 (uintptr)runtime_getcallersp(&dummy));
679 static void
680 doentersyscallblock(uintptr pc, uintptr sp)
682 // Leave SP around for GC and traceback.
683 #ifdef USING_SPLIT_STACK
685 size_t gcstacksize;
686 g->gcstack = (uintptr)(__splitstack_find(nil, nil, &gcstacksize,
687 (void**)(&g->gcnextsegment),
688 (void**)(&g->gcnextsp),
689 &g->gcinitialsp));
690 g->gcstacksize = (uintptr)gcstacksize;
692 #else
694 void *v;
696 g->gcnextsp = (uintptr)(&v);
698 #endif
700 reentersyscallblock(pc, sp);
703 // Allocate a new g, with a stack big enough for stacksize bytes.
705 runtime_malg(bool allocatestack, bool signalstack, byte** ret_stack, uintptr* ret_stacksize)
707 uintptr stacksize;
708 G *newg;
709 byte* unused_stack;
710 uintptr unused_stacksize;
711 #if USING_SPLIT_STACK
712 int dont_block_signals = 0;
713 size_t ss_stacksize;
714 #endif
716 if (ret_stack == nil) {
717 ret_stack = &unused_stack;
719 if (ret_stacksize == nil) {
720 ret_stacksize = &unused_stacksize;
722 newg = allocg();
723 if(allocatestack) {
724 stacksize = StackMin;
725 if(signalstack) {
726 stacksize = 32 * 1024; // OS X wants >= 8K, GNU/Linux >= 2K
727 #ifdef SIGSTKSZ
728 if(stacksize < SIGSTKSZ)
729 stacksize = SIGSTKSZ;
730 #endif
733 #if USING_SPLIT_STACK
734 *ret_stack = __splitstack_makecontext(stacksize,
735 (void*)(&newg->stackcontext[0]),
736 &ss_stacksize);
737 *ret_stacksize = (uintptr)ss_stacksize;
738 __splitstack_block_signals_context((void*)(&newg->stackcontext[0]),
739 &dont_block_signals, nil);
740 #else
741 // In 64-bit mode, the maximum Go allocation space is
742 // 128G. Our stack size is 4M, which only permits 32K
743 // goroutines. In order to not limit ourselves,
744 // allocate the stacks out of separate memory. In
745 // 32-bit mode, the Go allocation space is all of
746 // memory anyhow.
747 if(sizeof(void*) == 8) {
748 void *p = runtime_sysAlloc(stacksize, &getMemstats()->stacks_sys);
749 if(p == nil)
750 runtime_throw("runtime: cannot allocate memory for goroutine stack");
751 *ret_stack = (byte*)p;
752 } else {
753 *ret_stack = runtime_mallocgc(stacksize, nil, false);
754 runtime_xadd(&runtime_stacks_sys, stacksize);
756 *ret_stacksize = (uintptr)stacksize;
757 newg->gcinitialsp = *ret_stack;
758 newg->gcstacksize = (uintptr)stacksize;
759 #endif
761 return newg;
764 void stackfree(G*)
765 __asm__(GOSYM_PREFIX "runtime.stackfree");
767 // stackfree frees the stack of a g.
768 void
769 stackfree(G* gp)
771 #if USING_SPLIT_STACK
772 __splitstack_releasecontext((void*)(&gp->stackcontext[0]));
773 #else
774 // If gcstacksize is 0, the stack is allocated by libc and will be
775 // released when the thread exits. Otherwise, in 64-bit mode it was
776 // allocated using sysAlloc and in 32-bit mode it was allocated
777 // using garbage collected memory.
778 if (gp->gcstacksize != 0) {
779 if (sizeof(void*) == 8) {
780 runtime_sysFree(gp->gcinitialsp, gp->gcstacksize, &getMemstats()->stacks_sys);
782 gp->gcinitialsp = nil;
783 gp->gcstacksize = 0;
785 #endif
788 void resetNewG(G*, void **, uintptr*)
789 __asm__(GOSYM_PREFIX "runtime.resetNewG");
791 // Reset stack information for g pulled out of the cache to start a
792 // new goroutine.
793 void
794 resetNewG(G *newg, void **sp, uintptr *spsize)
796 #ifdef USING_SPLIT_STACK
797 int dont_block_signals = 0;
798 size_t ss_spsize;
800 *sp = __splitstack_resetcontext((void*)(&newg->stackcontext[0]), &ss_spsize);
801 *spsize = ss_spsize;
802 __splitstack_block_signals_context((void*)(&newg->stackcontext[0]),
803 &dont_block_signals, nil);
804 #else
805 *sp = newg->gcinitialsp;
806 *spsize = newg->gcstacksize;
807 if(*spsize == 0)
808 runtime_throw("bad spsize in resetNewG");
809 newg->gcnextsp = (uintptr)(*sp);
810 #endif
813 // Return whether we are waiting for a GC. This gc toolchain uses
814 // preemption instead.
815 bool
816 runtime_gcwaiting(void)
818 return runtime_sched->gcwaiting;