diff options
author | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-09-20 21:49:12 +0000 |
---|---|---|
committer | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-09-20 21:49:12 +0000 |
commit | c9c81ef3c667aaa14c498a5449ec6d134b4b66ff (patch) | |
tree | 0ac440db6513ee01deb5e5dc6142769d1e5b7b2d /libgo/runtime/proc.c | |
parent | 12cdcb9d74f55c165366ca1b1eeec013a0ce72ef (diff) | |
parent | 891196d7325e4c55d92d5ac5cfe7161c4f36c0ce (diff) | |
download | gcc-fortran-dev.tar.gz |
Merge from trunk (r239915 to r240230)fortran-dev
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/fortran-dev@240290 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime/proc.c')
-rw-r--r-- | libgo/runtime/proc.c | 65 |
1 files changed, 43 insertions, 22 deletions
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 1ac03a42372..6ac8857338b 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -156,6 +156,26 @@ fixcontext(ucontext_t *c) #endif +// ucontext_arg returns a properly aligned ucontext_t value. On some +// systems a ucontext_t value must be aligned to a 16-byte boundary. +// The g structure that has fields of type ucontext_t is defined in +// Go, and Go has no simple way to align a field to such a boundary. +// So we make the field larger in runtime2.go and pick an appropriate +// offset within the field here. +static ucontext_t* +ucontext_arg(void** go_ucontext) +{ + uintptr_t p = (uintptr_t)go_ucontext; + size_t align = __alignof__(ucontext_t); + if(align > 16) { + // We only ensured space for up to a 16 byte alignment + // in libgo/go/runtime/runtime2.go. + runtime_throw("required alignment of ucontext_t too large"); + } + p = (p + align - 1) &~ (uintptr_t)(align - 1); + return (ucontext_t*)p; +} + // We can not always refer to the TLS variables directly. The // compiler will call tls_get_addr to get the address of the variable, // and it may hold it in a register across a call to schedule. When @@ -245,8 +265,8 @@ runtime_gogo(G* newg) #endif g = newg; newg->fromgogo = true; - fixcontext((ucontext_t*)&newg->context[0]); - setcontext((ucontext_t*)&newg->context[0]); + fixcontext(ucontext_arg(&newg->context[0])); + setcontext(ucontext_arg(&newg->context[0])); runtime_throw("gogo setcontext returned"); } @@ -278,7 +298,7 @@ runtime_mcall(void (*pfn)(G*)) gp->gcnextsp = &pfn; #endif gp->fromgogo = false; - getcontext((ucontext_t*)&gp->context[0]); + getcontext(ucontext_arg(&gp->context[0])); // When we return from getcontext, we may be running // in a new thread. That means that g may have @@ -305,8 +325,8 @@ runtime_mcall(void (*pfn)(G*)) // the getcontext call just above. g = mp->g0; - fixcontext((ucontext_t*)&mp->g0->context[0]); - setcontext((ucontext_t*)&mp->g0->context[0]); + fixcontext(ucontext_arg(&mp->g0->context[0])); + setcontext(ucontext_arg(&mp->g0->context[0])); runtime_throw("runtime: mcall function returned"); } } @@ -709,7 +729,7 @@ runtime_tracebackothers(G * volatile me) #ifdef USING_SPLIT_STACK __splitstack_getcontext(&me->stackcontext[0]); #endif - getcontext((ucontext_t*)&me->context[0]); + getcontext(ucontext_arg(&me->context[0])); if(gp->traceback != nil) { runtime_gogo(gp); @@ -750,7 +770,7 @@ runtime_tracebackothers(G * volatile me) #ifdef USING_SPLIT_STACK __splitstack_getcontext(&me->stackcontext[0]); #endif - getcontext((ucontext_t*)&me->context[0]); + getcontext(ucontext_arg(&me->context[0])); if(gp->traceback != nil) { runtime_gogo(gp); @@ -1063,7 +1083,7 @@ runtime_mstart(void* mp) g->gcstacksize = 0; g->gcnextsp = ∓ #endif - getcontext((ucontext_t*)&g->context[0]); + getcontext(ucontext_arg(&g->context[0])); if(g->entry != nil) { // Got here from mcall. @@ -1251,7 +1271,7 @@ runtime_needm(void) g->gcstacksize = 0; g->gcnextsp = ∓ #endif - getcontext((ucontext_t*)&g->context[0]); + getcontext(ucontext_arg(&g->context[0])); if(g->entry != nil) { // Got here from mcall. @@ -1282,6 +1302,7 @@ runtime_newextram(void) G *gp; byte *g0_sp, *sp; uintptr g0_spsize, spsize; + ucontext_t *uc; // Create extra goroutine locked to extra m. // The goroutine is the context in which the cgo callback will run. @@ -1302,10 +1323,11 @@ runtime_newextram(void) // The context for gp will be set up in runtime_needm. But // here we need to set up the context for g0. - getcontext((ucontext_t*)&mp->g0->context[0]); - ((ucontext_t*)&mp->g0->context[0])->uc_stack.ss_sp = g0_sp; - ((ucontext_t*)&mp->g0->context[0])->uc_stack.ss_size = (size_t)g0_spsize; - makecontext((ucontext_t*)&mp->g0->context[0], kickoff, 0); + uc = ucontext_arg(&mp->g0->context[0]); + getcontext(uc); + uc->uc_stack.ss_sp = g0_sp; + uc->uc_stack.ss_size = (size_t)g0_spsize; + makecontext(uc, kickoff, 0); // Add m to the extra list. mnext = lockextra(true); @@ -2007,7 +2029,7 @@ runtime_entersyscall() { // Save the registers in the g structure so that any pointers // held in registers will be seen by the garbage collector. - getcontext((ucontext_t*)&g->gcregs[0]); + getcontext(ucontext_arg(&g->gcregs[0])); // Do the work in a separate function, so that this function // doesn't save any registers on its own stack. If this @@ -2086,7 +2108,7 @@ runtime_entersyscallblock(void) // Save the registers in the g structure so that any pointers // held in registers will be seen by the garbage collector. - getcontext((ucontext_t*)&g->gcregs[0]); + getcontext(ucontext_arg(&g->gcregs[0])); g->atomicstatus = _Gsyscall; @@ -2375,14 +2397,13 @@ __go_go(void (*fn)(void*), void* arg) byte * volatile vsp = sp; size_t volatile vspsize = spsize; G * volatile vnewg = newg; + ucontext_t * volatile uc; - getcontext((ucontext_t*)&vnewg->context[0]); - ((ucontext_t*)&vnewg->context[0])->uc_stack.ss_sp = vsp; -#ifdef MAKECONTEXT_STACK_TOP - ((ucontext_t*)&vnewg->context[0])->uc_stack.ss_sp += vspsize; -#endif - ((ucontext_t*)&vnewg->context[0])->uc_stack.ss_size = vspsize; - makecontext((ucontext_t*)&vnewg->context[0], kickoff, 0); + uc = ucontext_arg(&vnewg->context[0]); + getcontext(uc); + uc->uc_stack.ss_sp = vsp; + uc->uc_stack.ss_size = vspsize; + makecontext(uc, kickoff, 0); runqput(p, vnewg); |