diff options
Diffstat (limited to 'src/pkg/runtime/cgo/gcc_linux_arm.c')
-rw-r--r-- | src/pkg/runtime/cgo/gcc_linux_arm.c | 55 |
1 files changed, 5 insertions, 50 deletions
diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/pkg/runtime/cgo/gcc_linux_arm.c index 46a1126ad..9a6e58594 100644 --- a/src/pkg/runtime/cgo/gcc_linux_arm.c +++ b/src/pkg/runtime/cgo/gcc_linux_arm.c @@ -8,60 +8,15 @@ static void *threadentry(void*); -// We have to resort to TLS variable to save g(R10) and -// m(R9). One reason is that external code might trigger -// SIGSEGV, and our runtime.sigtramp don't even know we -// are in external code, and will continue to use R10/R9, -// this might as well result in another SIGSEGV. -// Note: all three functions will clobber R0, and the last -// two can be called from 5c ABI code. -void __aeabi_read_tp(void) __attribute__((naked)); -void x_cgo_save_gm(void) __attribute__((naked)); -void x_cgo_load_gm(void) __attribute__((naked)); +static void (*setmg_gcc)(void*, void*); void -__aeabi_read_tp(void) -{ - // b __kuser_get_tls @ 0xffff0fe0 - __asm__ __volatile__ ( - "mvn r0, #0xf000\n\t" - "sub pc, r0, #31\n\t" - "nop\n\tnop\n\t" - ); -} - -// g (R10) at 8(TP), m (R9) at 12(TP) -void -x_cgo_load_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "ldr r10, [r0, #8]\n\t" - "ldr r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} - -void -x_cgo_save_gm(void) -{ - __asm__ __volatile__ ( - "push {lr}\n\t" - "bl __aeabi_read_tp\n\t" - "str r10, [r0, #8]\n\t" - "str r9, [r0, #12]\n\t" - "pop {pc}\n\t" - ); -} - -void -x_cgo_init(G *g) +x_cgo_init(G *g, void (*setmg)(void*, void*)) { pthread_attr_t attr; size_t size; - x_cgo_save_gm(); // save g and m for the initial thread + setmg_gcc = setmg; pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); g->stackguard = (uintptr)&attr - size + 4096; @@ -92,7 +47,7 @@ _cgo_sys_thread_start(ThreadStart *ts) } } -extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +extern void crosscall_arm2(void (*fn)(void), void (*setmg_gcc)(void*, void*), void*, void*); static void* threadentry(void *v) { @@ -109,6 +64,6 @@ threadentry(void *v) */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; - crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + crosscall_arm2(ts.fn, setmg_gcc, (void*)ts.m, (void*)ts.g); return nil; } |