diff options
Diffstat (limited to 'src/pkg/runtime/cgo')
30 files changed, 1100 insertions, 147 deletions
diff --git a/src/pkg/runtime/cgo/asm_386.s b/src/pkg/runtime/cgo/asm_386.s new file mode 100644 index 000000000..7faaa4097 --- /dev/null +++ b/src/pkg/runtime/cgo/asm_386.s @@ -0,0 +1,29 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * void crosscall2(void (*fn)(void*, int32), void*, int32) + * Save registers and call fn with two arguments. + */ +TEXT crosscall2(SB),7,$0 + PUSHL BP + MOVL SP, BP + PUSHL BX + PUSHL SI + PUSHL DI + + SUBL $8, SP + MOVL 16(BP), AX + MOVL AX, 4(SP) + MOVL 12(BP), AX + MOVL AX, 0(SP) + MOVL 8(BP), AX + CALL AX + ADDL $8, SP + + POPL DI + POPL SI + POPL BX + POPL BP + RET diff --git a/src/pkg/runtime/cgo/asm_amd64.s b/src/pkg/runtime/cgo/asm_amd64.s new file mode 100644 index 000000000..53f7148a2 --- /dev/null +++ b/src/pkg/runtime/cgo/asm_amd64.s @@ -0,0 +1,45 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * void crosscall2(void (*fn)(void*, int32), void*, int32) + * Save registers and call fn with two arguments. + */ +TEXT crosscall2(SB),7,$0 + SUBQ $0x58, SP /* keeps stack pointer 32-byte aligned */ + MOVQ BX, 0x10(SP) + MOVQ BP, 0x18(SP) + MOVQ R12, 0x20(SP) + MOVQ R13, 0x28(SP) + MOVQ R14, 0x30(SP) + MOVQ R15, 0x38(SP) + +#ifdef GOOS_windows + // Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 + MOVQ DI, 0x40(SP) + MOVQ SI, 0x48(SP) + + MOVQ DX, 0(SP) /* arg */ + MOVQ R8, 8(SP) /* argsize (includes padding) */ + + CALL CX /* fn */ + + MOVQ 0x40(SP), DI + MOVQ 0x48(SP), SI +#else + MOVQ SI, 0(SP) /* arg */ + MOVQ DX, 8(SP) /* argsize (includes padding) */ + + CALL DI /* fn */ +#endif + + MOVQ 0x10(SP), BX + MOVQ 0x18(SP), BP + MOVQ 0x20(SP), R12 + MOVQ 0x28(SP), R13 + MOVQ 0x30(SP), R14 + MOVQ 0x38(SP), R15 + + ADDQ $0x58, SP + RET diff --git a/src/pkg/runtime/cgo/asm_arm.s b/src/pkg/runtime/cgo/asm_arm.s new file mode 100644 index 000000000..a6ea0dc07 --- /dev/null +++ b/src/pkg/runtime/cgo/asm_arm.s @@ -0,0 +1,23 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * void crosscall2(void (*fn)(void*, int32), void*, int32) + * Save registers and call fn with two arguments. + */ +TEXT crosscall2(SB),7,$-4 + /* + * We still need to save all callee save register as before, and then + * push 2 args for fn (R1 and R2). + * Also note that at procedure entry in 5c/5g world, 4(R13) will be the + * first arg, so we must push another dummy reg (R0) for 0(R13). + * Additionally, cgo_tls_set_gm will clobber R0, so we need to save R0 + * nevertheless. + */ + MOVM.WP [R0, R1, R2, R4, R5, R6, R7, R8, R9, R10, R11, R12, R14], (R13) + MOVW _cgo_load_gm(SB), R0 + BL (R0) + MOVW PC, R14 + MOVW 0(R13), PC + MOVM.IAW (R13), [R0, R1, R2, R4, R5, R6, R7, R8, R9, R10, R11, R12, PC] diff --git a/src/pkg/runtime/cgo/callbacks.c b/src/pkg/runtime/cgo/callbacks.c index f36fb3fd7..51bd529ec 100644 --- a/src/pkg/runtime/cgo/callbacks.c +++ b/src/pkg/runtime/cgo/callbacks.c @@ -33,7 +33,13 @@ static void _cgo_allocate_internal(uintptr len, byte *ret) { + CgoMal *c; + ret = runtime·mal(len); + c = runtime·mal(sizeof(*c)); + c->next = m->cgomal; + c->alloc = ret; + m->cgomal = c; FLUSH(&ret); } @@ -71,3 +77,19 @@ _cgo_panic(void *a, int32 n) { runtime·cgocallback((void(*)(void))_cgo_panic_internal, a, n); } + +#pragma cgo_import_static x_cgo_init +extern void x_cgo_init(G*); +void (*_cgo_init)(G*) = x_cgo_init; + +#pragma cgo_import_static x_cgo_malloc +extern void x_cgo_malloc(void*); +void (*_cgo_malloc)(void*) = x_cgo_malloc; + +#pragma cgo_import_static x_cgo_free +extern void x_cgo_free(void*); +void (*_cgo_free)(void*) = x_cgo_free; + +#pragma cgo_import_static x_cgo_thread_start +extern void x_cgo_thread_start(void*); +void (*_cgo_thread_start)(void*) = x_cgo_thread_start; diff --git a/src/pkg/runtime/cgo/cgo.go b/src/pkg/runtime/cgo/cgo.go index 414f3da36..e0d538668 100644 --- a/src/pkg/runtime/cgo/cgo.go +++ b/src/pkg/runtime/cgo/cgo.go @@ -18,6 +18,8 @@ package cgo #cgo openbsd LDFLAGS: -lpthread #cgo windows LDFLAGS: -lm -mthreads +#cgo CFLAGS: -Wall -Werror + */ import "C" diff --git a/src/pkg/runtime/cgo/cgo_arm.c b/src/pkg/runtime/cgo/cgo_arm.c new file mode 100644 index 000000000..d23f53e77 --- /dev/null +++ b/src/pkg/runtime/cgo/cgo_arm.c @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#pragma cgo_import_static x_cgo_load_gm +extern void x_cgo_load_gm(void); +void (*_cgo_load_gm)(void) = x_cgo_load_gm; + +#pragma cgo_import_static x_cgo_save_gm +extern void x_cgo_save_gm(void); +void (*_cgo_save_gm)(void) = x_cgo_save_gm; + diff --git a/src/pkg/runtime/cgo/gcc_386.S b/src/pkg/runtime/cgo/gcc_386.S index 9abab7ebd..94ba5842f 100644 --- a/src/pkg/runtime/cgo/gcc_386.S +++ b/src/pkg/runtime/cgo/gcc_386.S @@ -35,31 +35,6 @@ EXT(crosscall_386): popl %ebp ret -/* - * void crosscall2(void (*fn)(void*, int32), void*, int32) - * - * Save registers and call fn with two arguments. - */ -.globl EXT(crosscall2) -EXT(crosscall2): - pushl %ebp - movl %esp, %ebp - pushl %ebx - pushl %esi - pushl %edi - - pushl 16(%ebp) - pushl 12(%ebp) - mov 8(%ebp), %eax - call *%eax - addl $8,%esp - - popl %edi - popl %esi - popl %ebx - popl %ebp - ret - .globl EXT(__stack_chk_fail_local) EXT(__stack_chk_fail_local): 1: diff --git a/src/pkg/runtime/cgo/gcc_amd64.S b/src/pkg/runtime/cgo/gcc_amd64.S index 706ee6b58..81b270195 100644 --- a/src/pkg/runtime/cgo/gcc_amd64.S +++ b/src/pkg/runtime/cgo/gcc_amd64.S @@ -19,9 +19,6 @@ * are callee-save so they must be saved explicitly. * The standard x86-64 ABI passes the three arguments m, g, fn * in %rdi, %rsi, %rdx. - * - * Also need to set %r15 to g and %r14 to m (see ../pkg/runtime/mkasmh.sh) - * during the call. */ .globl EXT(crosscall_amd64) EXT(crosscall_amd64): @@ -45,48 +42,3 @@ EXT(crosscall_amd64): popq %rbp popq %rbx ret - -/* - * void crosscall2(void (*fn)(void*, int32), void *arg, int32 argsize) - * - * Save registers and call fn with two arguments. fn is a Go function - * which takes parameters on the stack rather than in registers. - */ -.globl EXT(crosscall2) -EXT(crosscall2): - subq $0x58, %rsp /* keeps stack pointer 32-byte aligned */ - movq %rbx, 0x10(%rsp) - movq %rbp, 0x18(%rsp) - movq %r12, 0x20(%rsp) - movq %r13, 0x28(%rsp) - movq %r14, 0x30(%rsp) - movq %r15, 0x38(%rsp) - -#if defined(_WIN64) - // Win64 save RBX, RBP, RDI, RSI, RSP, R12, R13, R14, and R15 - movq %rdi, 0x40(%rsp) - movq %rsi, 0x48(%rsp) - - movq %rdx, 0(%rsp) /* arg */ - movq %r8, 8(%rsp) /* argsize (includes padding) */ - - call *%rcx /* fn */ -#else - movq %rsi, 0(%rsp) /* arg */ - movq %rdx, 8(%rsp) /* argsize (includes padding) */ - - call *%rdi /* fn */ -#endif - - movq 0x10(%rsp), %rbx - movq 0x18(%rsp), %rbp - movq 0x20(%rsp), %r12 - movq 0x28(%rsp), %r13 - movq 0x30(%rsp), %r14 - movq 0x38(%rsp), %r15 -#if defined(__WIN64) - movq 0x40(%rsp), %rdi - movq 0x48(%rsp), %rsi -#endif - addq $0x58, %rsp - ret diff --git a/src/pkg/runtime/cgo/gcc_arm.S b/src/pkg/runtime/cgo/gcc_arm.S index 32d862984..809fcb9a0 100644 --- a/src/pkg/runtime/cgo/gcc_arm.S +++ b/src/pkg/runtime/cgo/gcc_arm.S @@ -1 +1,36 @@ -/* unimplemented */ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + * Apple still insists on underscore prefixes for C function names. + */ +#if defined(__APPLE__) +#define EXT(s) _##s +#else +#define EXT(s) s +#endif + +/* + * void crosscall_arm2(void (*fn)(void), void *g, void *m) + * + * Calling into the 5c tool chain, where all registers are caller save. + * Called from standard ARM EABI, where r4-r11 are callee-save, so they + * must be saved explicitly. + */ +.globl EXT(crosscall_arm2) +EXT(crosscall_arm2): + push {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr} + mov r10, r1 // g + mov r9, r2 // m + mov r3, r0 // save r0, cgo_tls_set_gm will clobber it + bl EXT(x_cgo_save_gm) // save current g and m into TLS variable + mov lr, pc + mov pc, r3 + pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, pc} + +.globl EXT(__stack_chk_fail_local) +EXT(__stack_chk_fail_local): +1: + b 1b + diff --git a/src/pkg/runtime/cgo/gcc_darwin_386.c b/src/pkg/runtime/cgo/gcc_darwin_386.c index 2c30c666f..ad9fb5abf 100644 --- a/src/pkg/runtime/cgo/gcc_darwin_386.c +++ b/src/pkg/runtime/cgo/gcc_darwin_386.c @@ -101,8 +101,8 @@ inittls(void) pthread_key_delete(tofree[i]); } -static void -xinitcgo(G *g) +void +x_cgo_init(G *g) { pthread_attr_t attr; size_t size; @@ -115,10 +115,9 @@ xinitcgo(G *g) inittls(); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { pthread_attr_t attr; sigset_t ign, oset; @@ -127,14 +126,14 @@ libcgo_sys_thread_start(ThreadStart *ts) int err; sigfillset(&ign); - sigprocmask(SIG_SETMASK, &ign, &oset); + pthread_sigmask(SIG_SETMASK, &ign, &oset); pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); ts->g->stackguard = size; err = pthread_create(&p, &attr, threadentry, ts); - sigprocmask(SIG_SETMASK, &oset, nil); + pthread_sigmask(SIG_SETMASK, &oset, nil); if (err != 0) { fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); @@ -153,7 +152,7 @@ threadentry(void *v) ts.g->stackbase = (uintptr)&ts; /* - * libcgo_sys_thread_start set stackguard to stack size; + * _cgo_sys_thread_start set stackguard to stack size; * change to actual guard pointer. */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; diff --git a/src/pkg/runtime/cgo/gcc_darwin_amd64.c b/src/pkg/runtime/cgo/gcc_darwin_amd64.c index 89dc7a4e8..65d381633 100644 --- a/src/pkg/runtime/cgo/gcc_darwin_amd64.c +++ b/src/pkg/runtime/cgo/gcc_darwin_amd64.c @@ -72,7 +72,7 @@ inittls(void) } void -xinitcgo(G *g) +x_cgo_init(G *g) { pthread_attr_t attr; size_t size; @@ -85,10 +85,9 @@ xinitcgo(G *g) inittls(); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { pthread_attr_t attr; sigset_t ign, oset; @@ -97,14 +96,14 @@ libcgo_sys_thread_start(ThreadStart *ts) int err; sigfillset(&ign); - sigprocmask(SIG_SETMASK, &ign, &oset); + pthread_sigmask(SIG_SETMASK, &ign, &oset); pthread_attr_init(&attr); pthread_attr_getstacksize(&attr, &size); ts->g->stackguard = size; err = pthread_create(&p, &attr, threadentry, ts); - sigprocmask(SIG_SETMASK, &oset, nil); + pthread_sigmask(SIG_SETMASK, &oset, nil); if (err != 0) { fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); @@ -123,7 +122,7 @@ threadentry(void *v) ts.g->stackbase = (uintptr)&ts; /* - * libcgo_sys_thread_start set stackguard to stack size; + * _cgo_sys_thread_start set stackguard to stack size; * change to actual guard pointer. */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; diff --git a/src/pkg/runtime/cgo/gcc_freebsd_386.c b/src/pkg/runtime/cgo/gcc_freebsd_386.c index 2c97e2a33..7c62a1bc4 100644 --- a/src/pkg/runtime/cgo/gcc_freebsd_386.c +++ b/src/pkg/runtime/cgo/gcc_freebsd_386.c @@ -6,12 +6,13 @@ #include <sys/signalvar.h> #include <pthread.h> #include <signal.h> +#include <string.h> #include "libcgo.h" static void* threadentry(void*); -static void -xinitcgo(G *g) +void +x_cgo_init(G *g) { pthread_attr_t attr; size_t size; @@ -22,10 +23,9 @@ xinitcgo(G *g) pthread_attr_destroy(&attr); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { pthread_attr_t attr; sigset_t ign, oset; @@ -60,7 +60,7 @@ threadentry(void *v) ts.g->stackbase = (uintptr)&ts; /* - * libcgo_sys_thread_start set stackguard to stack size; + * _cgo_sys_thread_start set stackguard to stack size; * change to actual guard pointer. */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; diff --git a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c index 3beb4d7bb..6be8bd251 100644 --- a/src/pkg/runtime/cgo/gcc_freebsd_amd64.c +++ b/src/pkg/runtime/cgo/gcc_freebsd_amd64.c @@ -6,12 +6,13 @@ #include <sys/signalvar.h> #include <pthread.h> #include <signal.h> +#include <string.h> #include "libcgo.h" static void* threadentry(void*); -static void -xinitcgo(G *g) +void +x_cgo_init(G *g) { pthread_attr_t attr; size_t size; @@ -22,10 +23,9 @@ xinitcgo(G *g) pthread_attr_destroy(&attr); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { pthread_attr_t attr; sigset_t ign, oset; @@ -61,7 +61,7 @@ threadentry(void *v) ts.g->stackbase = (uintptr)&ts; /* - * libcgo_sys_thread_start set stackguard to stack size; + * _cgo_sys_thread_start set stackguard to stack size; * change to actual guard pointer. */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; diff --git a/src/pkg/runtime/cgo/gcc_freebsd_arm.c b/src/pkg/runtime/cgo/gcc_freebsd_arm.c new file mode 100644 index 000000000..3bcb0b270 --- /dev/null +++ b/src/pkg/runtime/cgo/gcc_freebsd_arm.c @@ -0,0 +1,114 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <pthread.h> +#include <string.h> +#include "libcgo.h" + +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)); + +void +__aeabi_read_tp(void) +{ + // read @ 0xffff1000 + __asm__ __volatile__ ( + "ldr r0, =0xffff1000\n\t" + "ldr r0, [r0]\n\t" + "mov pc, lr\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) +{ + pthread_attr_t attr; + size_t size; + x_cgo_save_gm(); // save g and m for the initial thread + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); +} + + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + pthread_t p; + size_t size; + int err; + + // Not sure why the memset is necessary here, + // but without it, we get a bogus stack size + // out of pthread_attr_getstacksize. C'est la Linux. + memset(&attr, 0, sizeof attr); + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); + ts->g->stackguard = size; + err = pthread_create(&p, &attr, threadentry, ts); + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; + + crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + return nil; +} diff --git a/src/pkg/runtime/cgo/gcc_linux_386.c b/src/pkg/runtime/cgo/gcc_linux_386.c index 7d84acc11..9357a63f7 100644 --- a/src/pkg/runtime/cgo/gcc_linux_386.c +++ b/src/pkg/runtime/cgo/gcc_linux_386.c @@ -9,8 +9,8 @@ static void *threadentry(void*); -static void -xinitcgo(G *g) +void +x_cgo_init(G *g) { pthread_attr_t attr; size_t size; @@ -21,10 +21,9 @@ xinitcgo(G *g) pthread_attr_destroy(&attr); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { pthread_attr_t attr; sigset_t ign, oset; @@ -64,7 +63,7 @@ threadentry(void *v) ts.g->stackbase = (uintptr)&ts; /* - * libcgo_sys_thread_start set stackguard to stack size; + * _cgo_sys_thread_start set stackguard to stack size; * change to actual guard pointer. */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; diff --git a/src/pkg/runtime/cgo/gcc_linux_amd64.c b/src/pkg/runtime/cgo/gcc_linux_amd64.c index 28cbf78c5..bc76117d3 100644 --- a/src/pkg/runtime/cgo/gcc_linux_amd64.c +++ b/src/pkg/runtime/cgo/gcc_linux_amd64.c @@ -10,7 +10,7 @@ static void* threadentry(void*); void -xinitcgo(G* g) +x_cgo_init(G* g) { pthread_attr_t attr; size_t size; @@ -21,10 +21,9 @@ xinitcgo(G* g) pthread_attr_destroy(&attr); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { pthread_attr_t attr; sigset_t ign, oset; @@ -59,7 +58,7 @@ threadentry(void *v) ts.g->stackbase = (uintptr)&ts; /* - * libcgo_sys_thread_start set stackguard to stack size; + * _cgo_sys_thread_start set stackguard to stack size; * change to actual guard pointer. */ ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; diff --git a/src/pkg/runtime/cgo/gcc_linux_arm.c b/src/pkg/runtime/cgo/gcc_linux_arm.c index 8397c75bb..46a1126ad 100644 --- a/src/pkg/runtime/cgo/gcc_linux_arm.c +++ b/src/pkg/runtime/cgo/gcc_linux_arm.c @@ -2,19 +2,113 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include <pthread.h> +#include <string.h> #include "libcgo.h" -static void -xinitcgo(G *g) +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)); + +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) { - // unimplemented + pthread_attr_t attr; + size_t size; + x_cgo_save_gm(); // save g and m for the initial thread + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + pthread_t p; + size_t size; + int err; + + // Not sure why the memset is necessary here, + // but without it, we get a bogus stack size + // out of pthread_attr_getstacksize. C'est la Linux. + memset(&attr, 0, sizeof attr); + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); + ts->g->stackguard = size; + err = pthread_create(&p, &attr, threadentry, ts); + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +static void* +threadentry(void *v) { - // unimplemented - *(int*)0 = 0; + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; + + crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + return nil; } diff --git a/src/pkg/runtime/cgo/gcc_netbsd_386.c b/src/pkg/runtime/cgo/gcc_netbsd_386.c new file mode 100644 index 000000000..09b271df4 --- /dev/null +++ b/src/pkg/runtime/cgo/gcc_netbsd_386.c @@ -0,0 +1,80 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <sys/types.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> +#include "libcgo.h" + +static void* threadentry(void*); + +void +x_cgo_init(G *g) +{ + pthread_attr_t attr; + size_t size; + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); +} + + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + sigprocmask(SIG_SETMASK, &ign, &oset); + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + ts->g->stackguard = size; + err = pthread_create(&p, &attr, threadentry, ts); + + sigprocmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; + + /* + * Set specific keys. On NetBSD/ELF, the thread local storage + * is just before %gs:0. Our dynamic 8.out's reserve 8 bytes + * for the two words g and m at %gs:-8 and %gs:-4. + */ + asm volatile ( + "movl %0, %%gs:-8\n" // MOVL g, -8(GS) + "movl %1, %%gs:-4\n" // MOVL m, -4(GS) + :: "r"(ts.g), "r"(ts.m) + ); + + crosscall_386(ts.fn); + return nil; +} diff --git a/src/pkg/runtime/cgo/gcc_netbsd_amd64.c b/src/pkg/runtime/cgo/gcc_netbsd_amd64.c new file mode 100644 index 000000000..080c59ba4 --- /dev/null +++ b/src/pkg/runtime/cgo/gcc_netbsd_amd64.c @@ -0,0 +1,80 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <sys/types.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> +#include "libcgo.h" + +static void* threadentry(void*); + +void +x_cgo_init(G *g) +{ + pthread_attr_t attr; + size_t size; + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); +} + + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + sigprocmask(SIG_SETMASK, &ign, &oset); + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + + ts->g->stackguard = size; + err = pthread_create(&p, &attr, threadentry, ts); + + sigprocmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; + + /* + * Set specific keys. On NetBSD/ELF, the thread local storage + * is just before %fs:0. Our dynamic 6.out's reserve 16 bytes + * for the two words g and m at %fs:-16 and %fs:-8. + */ + asm volatile ( + "movq %0, %%fs:-16\n" // MOVL g, -16(FS) + "movq %1, %%fs:-8\n" // MOVL m, -8(FS) + :: "r"(ts.g), "r"(ts.m) + ); + crosscall_amd64(ts.fn); + return nil; +} diff --git a/src/pkg/runtime/cgo/gcc_netbsd_arm.c b/src/pkg/runtime/cgo/gcc_netbsd_arm.c new file mode 100644 index 000000000..d93b531e7 --- /dev/null +++ b/src/pkg/runtime/cgo/gcc_netbsd_arm.c @@ -0,0 +1,122 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <sys/types.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> +#include "libcgo.h" + +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)); + +void +__aeabi_read_tp(void) +{ + // this function is only allowed to clobber r0 + __asm__ __volatile__ ( + "mrc p15, 0, r0, c13, c0, 3\n\t" + "cmp r0, #0\n\t" + "movne pc, lr\n\t" + "push {r1,r2,r3,r12}\n\t" + "svc 0x00a0013c\n\t" // _lwp_getprivate + "pop {r1,r2,r3,r12}\n\t" + "mov pc, lr\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) +{ + pthread_attr_t attr; + size_t size; + x_cgo_save_gm(); // save g and m for the initial thread + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); +} + + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + sigprocmask(SIG_SETMASK, &ign, &oset); + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + ts->g->stackguard = size; + err = pthread_create(&p, &attr, threadentry, ts); + + sigprocmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +extern void crosscall_arm2(void (*fn)(void), void *g, void *m); +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096 * 2; + + crosscall_arm2(ts.fn, (void *)ts.g, (void *)ts.m); + return nil; +} diff --git a/src/pkg/runtime/cgo/gcc_openbsd_386.c b/src/pkg/runtime/cgo/gcc_openbsd_386.c new file mode 100644 index 000000000..86c1365ad --- /dev/null +++ b/src/pkg/runtime/cgo/gcc_openbsd_386.c @@ -0,0 +1,169 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <sys/types.h> +#include <dlfcn.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> +#include "libcgo.h" + +static void* threadentry(void*); + +// TCB_SIZE is sizeof(struct thread_control_block), +// as defined in /usr/src/lib/librthread/tcb.h +#define TCB_SIZE (4 * sizeof(void *)) +#define TLS_SIZE (2 * sizeof(void *)) + +void *__get_tcb(void); +void __set_tcb(void *); + +static int (*sys_pthread_create)(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg); + +struct thread_args { + void *(*func)(void *); + void *arg; +}; + +static void +tcb_fixup(int mainthread) +{ + void *newtcb, *oldtcb; + + // The OpenBSD ld.so(1) does not currently support PT_TLS. As a result, + // we need to allocate our own TLS space while preserving the existing + // TCB that has been setup via librthread. + + newtcb = malloc(TCB_SIZE + TLS_SIZE); + if(newtcb == NULL) + abort(); + + // The signal trampoline expects the TLS slots to be zeroed. + bzero(newtcb, TLS_SIZE); + + oldtcb = __get_tcb(); + bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE); + __set_tcb(newtcb + TLS_SIZE); + + // The main thread TCB is a static allocation - do not try to free it. + if(!mainthread) + free(oldtcb); +} + +static void * +thread_start_wrapper(void *arg) +{ + struct thread_args args = *(struct thread_args *)arg; + + free(arg); + tcb_fixup(0); + + return args.func(args.arg); +} + +int +pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + struct thread_args *p; + + p = malloc(sizeof(*p)); + if(p == NULL) { + errno = ENOMEM; + return -1; + } + p->func = start_routine; + p->arg = arg; + + return sys_pthread_create(thread, attr, thread_start_wrapper, p); +} + +void +x_cgo_init(G *g) +{ + pthread_attr_t attr; + size_t size; + void *handle; + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); + + // Locate symbol for the system pthread_create function. + handle = dlopen("libpthread.so", RTLD_LAZY); + if(handle == NULL) { + fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror()); + abort(); + } + sys_pthread_create = dlsym(handle, "pthread_create"); + if(sys_pthread_create == NULL) { + fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror()); + abort(); + } + dlclose(handle); + + tcb_fixup(1); +} + + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + sigprocmask(SIG_SETMASK, &ign, &oset); + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + ts->g->stackguard = size; + err = sys_pthread_create(&p, &attr, threadentry, ts); + + sigprocmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +static void* +threadentry(void *v) +{ + ThreadStart ts; + + tcb_fixup(0); + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; + + /* + * Set specific keys. On OpenBSD/ELF, the thread local storage + * is just before %gs:0. Our dynamic 8.out's reserve 8 bytes + * for the two words g and m at %gs:-8 and %gs:-4. + */ + asm volatile ( + "movl %0, %%gs:-8\n" // MOVL g, -8(GS) + "movl %1, %%gs:-4\n" // MOVL m, -4(GS) + :: "r"(ts.g), "r"(ts.m) + ); + + crosscall_386(ts.fn); + return nil; +} diff --git a/src/pkg/runtime/cgo/gcc_openbsd_amd64.c b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c new file mode 100644 index 000000000..d3a5e36b0 --- /dev/null +++ b/src/pkg/runtime/cgo/gcc_openbsd_amd64.c @@ -0,0 +1,169 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <sys/types.h> +#include <dlfcn.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> +#include "libcgo.h" + +static void* threadentry(void*); + +// TCB_SIZE is sizeof(struct thread_control_block), +// as defined in /usr/src/lib/librthread/tcb.h +#define TCB_SIZE (4 * sizeof(void *)) +#define TLS_SIZE (2 * sizeof(void *)) + +void *__get_tcb(void); +void __set_tcb(void *); + +static int (*sys_pthread_create)(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg); + +struct thread_args { + void *(*func)(void *); + void *arg; +}; + +static void +tcb_fixup(int mainthread) +{ + void *newtcb, *oldtcb; + + // The OpenBSD ld.so(1) does not currently support PT_TLS. As a result, + // we need to allocate our own TLS space while preserving the existing + // TCB that has been setup via librthread. + + newtcb = malloc(TCB_SIZE + TLS_SIZE); + if(newtcb == NULL) + abort(); + + // The signal trampoline expects the TLS slots to be zeroed. + bzero(newtcb, TLS_SIZE); + + oldtcb = __get_tcb(); + bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE); + __set_tcb(newtcb + TLS_SIZE); + + // The main thread TCB is a static allocation - do not try to free it. + if(!mainthread) + free(oldtcb); +} + +static void * +thread_start_wrapper(void *arg) +{ + struct thread_args args = *(struct thread_args *)arg; + + free(arg); + tcb_fixup(0); + + return args.func(args.arg); +} + +int +pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void *), void *arg) +{ + struct thread_args *p; + + p = malloc(sizeof(*p)); + if(p == NULL) { + errno = ENOMEM; + return -1; + } + p->func = start_routine; + p->arg = arg; + + return sys_pthread_create(thread, attr, thread_start_wrapper, p); +} + +void +x_cgo_init(G *g) +{ + pthread_attr_t attr; + size_t size; + void *handle; + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stackguard = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); + + // Locate symbol for the system pthread_create function. + handle = dlopen("libpthread.so", RTLD_LAZY); + if(handle == NULL) { + fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror()); + abort(); + } + sys_pthread_create = dlsym(handle, "pthread_create"); + if(sys_pthread_create == NULL) { + fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror()); + abort(); + } + dlclose(handle); + + tcb_fixup(1); +} + + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + sigprocmask(SIG_SETMASK, &ign, &oset); + + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + + ts->g->stackguard = size; + err = sys_pthread_create(&p, &attr, threadentry, ts); + + sigprocmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err)); + abort(); + } +} + +static void* +threadentry(void *v) +{ + ThreadStart ts; + + tcb_fixup(0); + + ts = *(ThreadStart*)v; + free(v); + + ts.g->stackbase = (uintptr)&ts; + + /* + * _cgo_sys_thread_start set stackguard to stack size; + * change to actual guard pointer. + */ + ts.g->stackguard = (uintptr)&ts - ts.g->stackguard + 4096; + + /* + * Set specific keys. On OpenBSD/ELF, the thread local storage + * is just before %fs:0. Our dynamic 6.out's reserve 16 bytes + * for the two words g and m at %fs:-16 and %fs:-8. + */ + asm volatile ( + "movq %0, %%fs:-16\n" // MOVL g, -16(FS) + "movq %1, %%fs:-8\n" // MOVL m, -8(FS) + :: "r"(ts.g), "r"(ts.m) + ); + crosscall_amd64(ts.fn); + return nil; +} diff --git a/src/pkg/runtime/cgo/gcc_setenv.c b/src/pkg/runtime/cgo/gcc_setenv.c index 7da4ad915..a0938166d 100644 --- a/src/pkg/runtime/cgo/gcc_setenv.c +++ b/src/pkg/runtime/cgo/gcc_setenv.c @@ -1,4 +1,4 @@ -// Copyright 20111 The Go Authors. All rights reserved. +// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -9,10 +9,8 @@ #include <stdlib.h> /* Stub for calling setenv */ -static void -xlibcgo_setenv(char **arg) +void +x_cgo_setenv(char **arg) { setenv(arg[0], arg[1], 1); } - -void (*libcgo_setenv)(char**) = xlibcgo_setenv; diff --git a/src/pkg/runtime/cgo/gcc_util.c b/src/pkg/runtime/cgo/gcc_util.c index e06b6f64d..20913d736 100644 --- a/src/pkg/runtime/cgo/gcc_util.c +++ b/src/pkg/runtime/cgo/gcc_util.c @@ -5,7 +5,7 @@ #include "libcgo.h" /* Stub for calling malloc from Go */ -static void +void x_cgo_malloc(void *p) { struct a { @@ -16,10 +16,8 @@ x_cgo_malloc(void *p) a->ret = malloc(a->n); } -void (*_cgo_malloc)(void*) = x_cgo_malloc; - /* Stub for calling free from Go */ -static void +void x_cgo_free(void *p) { struct a { @@ -29,11 +27,9 @@ x_cgo_free(void *p) free(a->arg); } -void (*_cgo_free)(void*) = x_cgo_free; - /* Stub for creating a new thread */ -static void -xlibcgo_thread_start(ThreadStart *arg) +void +x_cgo_thread_start(ThreadStart *arg) { ThreadStart *ts; @@ -45,7 +41,5 @@ xlibcgo_thread_start(ThreadStart *arg) } *ts = *arg; - libcgo_sys_thread_start(ts); /* OS-dependent half */ + _cgo_sys_thread_start(ts); /* OS-dependent half */ } - -void (*libcgo_thread_start)(ThreadStart*) = xlibcgo_thread_start; diff --git a/src/pkg/runtime/cgo/gcc_windows_386.c b/src/pkg/runtime/cgo/gcc_windows_386.c index 2b940d362..02eab12e5 100644 --- a/src/pkg/runtime/cgo/gcc_windows_386.c +++ b/src/pkg/runtime/cgo/gcc_windows_386.c @@ -4,31 +4,31 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> +#include <process.h> #include "libcgo.h" -static void *threadentry(void*); +static void threadentry(void*); /* 1MB is default stack size for 32-bit Windows. Allocation granularity on Windows is typically 64 KB. The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */ #define STACKSIZE (1*1024*1024) -static void -xinitcgo(G *g) +void +x_cgo_init(G *g) { int tmp; g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024; } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { _beginthread(threadentry, 0, ts); } -static void* +static void threadentry(void *v) { ThreadStart ts; @@ -55,5 +55,4 @@ threadentry(void *v) crosscall_386(ts.fn); LocalFree(tls0); - return nil; } diff --git a/src/pkg/runtime/cgo/gcc_windows_amd64.c b/src/pkg/runtime/cgo/gcc_windows_amd64.c index 0d2f5d233..f7695a1cc 100644 --- a/src/pkg/runtime/cgo/gcc_windows_amd64.c +++ b/src/pkg/runtime/cgo/gcc_windows_amd64.c @@ -4,31 +4,31 @@ #define WIN64_LEAN_AND_MEAN #include <windows.h> +#include <process.h> #include "libcgo.h" -static void *threadentry(void*); +static void threadentry(void*); /* 2MB is default stack size for 64-bit Windows. Allocation granularity on Windows is typically 64 KB. The constant is also hardcoded in cmd/ld/pe.c (keep synchronized). */ #define STACKSIZE (2*1024*1024) -static void -xinitcgo(G *g) +void +x_cgo_init(G *g) { int tmp; g->stackguard = (uintptr)&tmp - STACKSIZE + 8*1024; } -void (*initcgo)(G*) = xinitcgo; void -libcgo_sys_thread_start(ThreadStart *ts) +_cgo_sys_thread_start(ThreadStart *ts) { _beginthread(threadentry, 0, ts); } -static void* +static void threadentry(void *v) { ThreadStart ts; @@ -53,5 +53,4 @@ threadentry(void *v) ); crosscall_amd64(ts.fn); - return nil; } diff --git a/src/pkg/runtime/cgo/libcgo.h b/src/pkg/runtime/cgo/libcgo.h index c31d19d76..41a371c27 100644 --- a/src/pkg/runtime/cgo/libcgo.h +++ b/src/pkg/runtime/cgo/libcgo.h @@ -26,7 +26,7 @@ struct G }; /* - * Arguments to the libcgo_thread_start call. + * Arguments to the _cgo_thread_start call. * Also known to ../pkg/runtime/runtime.h. */ typedef struct ThreadStart ThreadStart; @@ -40,14 +40,14 @@ struct ThreadStart /* * Called by 5c/6c/8c world. * Makes a local copy of the ThreadStart and - * calls libcgo_sys_thread_start(ts). + * calls _cgo_sys_thread_start(ts). */ -extern void (*libcgo_thread_start)(ThreadStart *ts); +extern void (*_cgo_thread_start)(ThreadStart *ts); /* * Creates the new operating system thread (OS, arch dependent). */ -void libcgo_sys_thread_start(ThreadStart *ts); +void _cgo_sys_thread_start(ThreadStart *ts); /* * Call fn in the 6c world. diff --git a/src/pkg/runtime/cgo/netbsd.c b/src/pkg/runtime/cgo/netbsd.c new file mode 100644 index 000000000..b6403f686 --- /dev/null +++ b/src/pkg/runtime/cgo/netbsd.c @@ -0,0 +1,13 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Supply environ and __progname, because we don't +// link against the standard NetBSD crt0.o and the +// libc dynamic library needs them. + +char *environ[1]; +char *__progname; + +#pragma dynexport environ environ +#pragma dynexport __progname __progname diff --git a/src/pkg/runtime/cgo/openbsd.c b/src/pkg/runtime/cgo/openbsd.c new file mode 100644 index 000000000..84e9f9eff --- /dev/null +++ b/src/pkg/runtime/cgo/openbsd.c @@ -0,0 +1,21 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Supply environ, __progname and __guard_local, because +// we don't link against the standard OpenBSD crt0.o and +// the libc dynamic library needs them. + +char *environ[1]; +char *__progname; +long __guard_local; + +#pragma dynexport environ environ +#pragma dynexport __progname __progname + +// This is normally marked as hidden and placed in the +// .openbsd.randomdata section. +#pragma dynexport __guard_local __guard_local + +// We override pthread_create to support PT_TLS. +#pragma dynexport pthread_create pthread_create diff --git a/src/pkg/runtime/cgo/setenv.c b/src/pkg/runtime/cgo/setenv.c new file mode 100644 index 000000000..4c47cdb00 --- /dev/null +++ b/src/pkg/runtime/cgo/setenv.c @@ -0,0 +1,10 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin freebsd linux netbsd openbsd + +#pragma cgo_import_static x_cgo_setenv + +void x_cgo_setenv(char**); +void (*_cgo_setenv)(char**) = x_cgo_setenv; |