mirror of
https://github.com/golang/go
synced 2024-11-18 15:44:41 -07:00
Support cgo export on amd64.
R=rsc CC=golang-dev https://golang.org/cl/857045
This commit is contained in:
parent
bc2d977d67
commit
2d0ff3f1a6
@ -43,3 +43,39 @@ 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)
|
||||
|
||||
movq %rdi, %r12 /* fn */
|
||||
movq %rsi, 0(%rsp) /* arg */
|
||||
movq %rdx, 8(%rsp) /* argsize (includes padding) */
|
||||
|
||||
leaq 0x40(%rsp), %rdi
|
||||
call EXT(libcgo_get_scheduler)
|
||||
movq 0x40(%rsp), %r14 /* m */
|
||||
movq 0x48(%rsp), %r15 /* g */
|
||||
|
||||
call *%r12
|
||||
|
||||
movq 0x10(%rsp), %rbx
|
||||
movq 0x18(%rsp), %rbp
|
||||
movq 0x20(%rsp), %r12
|
||||
movq 0x28(%rsp), %r13
|
||||
movq 0x30(%rsp), %r14
|
||||
movq 0x38(%rsp), %r15
|
||||
addq $0x58, %rsp
|
||||
ret
|
||||
|
@ -7,9 +7,19 @@
|
||||
|
||||
static void* threadentry(void*);
|
||||
|
||||
static pthread_key_t km, kg;
|
||||
|
||||
void
|
||||
initcgo(void)
|
||||
{
|
||||
if(pthread_key_create(&km, nil) < 0) {
|
||||
fprintf(stderr, "libcgo: pthread_key_create failed\n");
|
||||
abort();
|
||||
}
|
||||
if(pthread_key_create(&kg, nil) < 0) {
|
||||
fprintf(stderr, "libcgo: pthread_key_create failed\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -44,3 +54,25 @@ threadentry(void *v)
|
||||
crosscall_amd64(ts.m, ts.g, ts.fn);
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
libcgo_set_scheduler(void *m, void *g)
|
||||
{
|
||||
pthread_setspecific(km, m);
|
||||
pthread_setspecific(kg, g);
|
||||
}
|
||||
|
||||
struct get_scheduler_args {
|
||||
void *m;
|
||||
void *g;
|
||||
};
|
||||
|
||||
void libcgo_get_scheduler(struct get_scheduler_args *)
|
||||
__attribute__ ((visibility("hidden")));
|
||||
|
||||
void
|
||||
libcgo_get_scheduler(struct get_scheduler_args *p)
|
||||
{
|
||||
p->m = pthread_getspecific(km);
|
||||
p->g = pthread_getspecific(kg);
|
||||
}
|
||||
|
@ -47,3 +47,28 @@ threadentry(void *v)
|
||||
crosscall_amd64(ts.m, ts.g, ts.fn);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static __thread void *libcgo_m;
|
||||
static __thread void *libcgo_g;
|
||||
|
||||
void
|
||||
libcgo_set_scheduler(void *m, void *g)
|
||||
{
|
||||
libcgo_m = m;
|
||||
libcgo_g = g;
|
||||
}
|
||||
|
||||
struct get_scheduler_args {
|
||||
void *m;
|
||||
void *g;
|
||||
};
|
||||
|
||||
void libcgo_get_scheduler(struct get_scheduler_args *)
|
||||
__attribute__ ((visibility("hidden")));
|
||||
|
||||
void
|
||||
libcgo_get_scheduler(struct get_scheduler_args *p)
|
||||
{
|
||||
p->m = libcgo_m;
|
||||
p->g = libcgo_g;
|
||||
}
|
||||
|
@ -44,3 +44,28 @@ threadentry(void *v)
|
||||
crosscall_amd64(ts.m, ts.g, ts.fn);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static __thread void *libcgo_m;
|
||||
static __thread void *libcgo_g;
|
||||
|
||||
void
|
||||
libcgo_set_scheduler(void *m, void *g)
|
||||
{
|
||||
libcgo_m = m;
|
||||
libcgo_g = g;
|
||||
}
|
||||
|
||||
struct get_scheduler_args {
|
||||
void *m;
|
||||
void *g;
|
||||
};
|
||||
|
||||
void libcgo_get_scheduler(struct get_scheduler_args *)
|
||||
__attribute__ ((visibility("hidden")));
|
||||
|
||||
void
|
||||
libcgo_get_scheduler(struct get_scheduler_args *p)
|
||||
{
|
||||
p->m = libcgo_m;
|
||||
p->g = libcgo_g;
|
||||
}
|
||||
|
@ -276,14 +276,13 @@ TEXT jmpdefer(SB), 7, $0
|
||||
// Save g and m across the call,
|
||||
// since the foreign code might reuse them.
|
||||
TEXT runcgo(SB),7,$32
|
||||
// Save old registers.
|
||||
MOVQ fn+0(FP),AX
|
||||
MOVQ arg+8(FP),DI // DI = first argument in AMD64 ABI
|
||||
MOVQ fn+0(FP), R12
|
||||
MOVQ arg+8(FP), R13
|
||||
MOVQ SP, CX
|
||||
|
||||
// Figure out if we need to switch to m->g0 stack.
|
||||
MOVQ m_g0(m), R8
|
||||
CMPQ R8, g
|
||||
MOVQ m_g0(m), SI
|
||||
CMPQ SI, g
|
||||
JEQ 2(PC)
|
||||
MOVQ (m_sched+gobuf_sp)(m), SP
|
||||
|
||||
@ -293,7 +292,17 @@ TEXT runcgo(SB),7,$32
|
||||
MOVQ g, 24(SP) // save old g, m, SP
|
||||
MOVQ m, 16(SP)
|
||||
MOVQ CX, 8(SP)
|
||||
CALL AX
|
||||
|
||||
// Save g and m values for a potential callback. The callback
|
||||
// will start running with on the g0 stack and as such should
|
||||
// have g set to m->g0.
|
||||
MOVQ m, DI // DI = first argument in AMD64 ABI
|
||||
// SI, second argument, set above
|
||||
MOVQ libcgo_set_scheduler(SB), BX
|
||||
CALL BX
|
||||
|
||||
MOVQ R13, DI // DI = first argument in AMD64 ABI
|
||||
CALL R12
|
||||
|
||||
// Restore registers, stack pointer.
|
||||
MOVQ 16(SP), m
|
||||
@ -301,6 +310,32 @@ TEXT runcgo(SB),7,$32
|
||||
MOVQ 8(SP), SP
|
||||
RET
|
||||
|
||||
// runcgocallback(G *g1, void* sp, void (*fn)(void))
|
||||
// Switch to g1 and sp, call fn, switch back. fn's arguments are on
|
||||
// the new stack.
|
||||
TEXT runcgocallback(SB),7,$48
|
||||
MOVQ g1+0(FP), DX
|
||||
MOVQ sp+8(FP), AX
|
||||
MOVQ fp+16(FP), BX
|
||||
|
||||
MOVQ DX, g
|
||||
|
||||
// We are running on m's scheduler stack. Save current SP
|
||||
// into m->sched.sp so that a recursive call to runcgo doesn't
|
||||
// clobber our stack, and also so that we can restore
|
||||
// the SP when the call finishes. Reusing m->sched.sp
|
||||
// for this purpose depends on the fact that there is only
|
||||
// one possible gosave of m->sched.
|
||||
MOVQ SP, (m_sched+gobuf_sp)(m)
|
||||
|
||||
// Set new SP, call fn
|
||||
MOVQ AX, SP
|
||||
CALL BX
|
||||
|
||||
// Restore old SP, return
|
||||
MOVQ (m_sched+gobuf_sp)(m), SP
|
||||
RET
|
||||
|
||||
// check that SP is in range [g->stackbase, g->stackguard)
|
||||
TEXT stackcheck(SB), 7, $0
|
||||
CMPQ g_stackbase(g), SP
|
||||
@ -337,3 +372,4 @@ TEXT getcallersp(SB),7,$0
|
||||
MOVQ sp+0(FP), AX
|
||||
RET
|
||||
|
||||
GLOBL libcgo_set_scheduler(SB), $8
|
||||
|
Loading…
Reference in New Issue
Block a user