mirror of
https://github.com/golang/go
synced 2024-11-25 08:57:58 -07:00
runtime: use cgo runtime functions to call windows syscalls
R=rsc CC=golang-dev, jp, vcc.163 https://golang.org/cl/4926042
This commit is contained in:
parent
a88994f804
commit
2a80882601
@ -94,7 +94,7 @@ runtime·cgocall(void (*fn)(void*), void *arg)
|
||||
{
|
||||
Defer d;
|
||||
|
||||
if(!runtime·iscgo)
|
||||
if(!runtime·iscgo && !Windows)
|
||||
runtime·throw("cgocall unavailable");
|
||||
|
||||
if(fn == 0)
|
||||
|
@ -96,6 +96,7 @@ awk '
|
||||
/^aggr G$/ { aggr="g" }
|
||||
/^aggr M$/ { aggr = "m" }
|
||||
/^aggr Gobuf$/ { aggr = "gobuf" }
|
||||
/^aggr WinCall$/ { aggr = "wincall" }
|
||||
/^}/ { aggr = "" }
|
||||
|
||||
# Gobuf 24 sched;
|
||||
|
@ -70,6 +70,7 @@ typedef struct Hmap Hmap;
|
||||
typedef struct Hchan Hchan;
|
||||
typedef struct Complex64 Complex64;
|
||||
typedef struct Complex128 Complex128;
|
||||
typedef struct WinCall WinCall;
|
||||
|
||||
/*
|
||||
* per-cpu declaration.
|
||||
@ -250,11 +251,6 @@ struct M
|
||||
uint32 freglo[16]; // D[i] lsb and F[i]
|
||||
uint32 freghi[16]; // D[i] msb and F[i+16]
|
||||
uint32 fflag; // floating point compare flags
|
||||
#ifdef __WINDOWS__
|
||||
#ifdef _64BIT
|
||||
void* gostack;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Stktop
|
||||
@ -306,6 +302,15 @@ struct Func
|
||||
int32 locals; // number of 32-bit locals
|
||||
};
|
||||
|
||||
struct WinCall
|
||||
{
|
||||
void (*fn)(void*);
|
||||
uintptr n; // number of parameters
|
||||
void* args; // parameters
|
||||
uintptr r; // return value
|
||||
uintptr err; // error number
|
||||
};
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
enum {
|
||||
Windows = 1
|
||||
|
@ -4,44 +4,34 @@
|
||||
|
||||
#include "386/asm.h"
|
||||
|
||||
// void *stdcall_raw(void *fn, int32 count, uintptr *args)
|
||||
TEXT runtime·stdcall_raw(SB),7,$0
|
||||
// Copy arguments from stack.
|
||||
MOVL fn+0(FP), AX
|
||||
MOVL count+4(FP), CX // words
|
||||
MOVL args+8(FP), BP
|
||||
// void runtime·asmstdcall(void *c);
|
||||
TEXT runtime·asmstdcall(SB),7,$0
|
||||
MOVL c+0(FP), DX
|
||||
|
||||
// Switch to m->g0 if needed.
|
||||
get_tls(DI)
|
||||
MOVL m(DI), DX
|
||||
MOVL m_g0(DX), SI
|
||||
CMPL g(DI), SI
|
||||
MOVL SP, BX
|
||||
JEQ 2(PC)
|
||||
MOVL (g_sched+gobuf_sp)(SI), SP
|
||||
PUSHL BX
|
||||
PUSHL g(DI)
|
||||
MOVL SI, g(DI)
|
||||
// SetLastError(0).
|
||||
MOVL $0, 0x34(FS)
|
||||
|
||||
// Copy args to new stack.
|
||||
// Copy args to the stack.
|
||||
MOVL wincall_n(DX), CX // words
|
||||
MOVL CX, BX
|
||||
SALL $2, BX
|
||||
SUBL BX, SP // room for args
|
||||
MOVL SP, DI
|
||||
MOVL BP, SI
|
||||
MOVL wincall_args(DX), SI
|
||||
CLD
|
||||
REP; MOVSL
|
||||
|
||||
// Call stdcall function.
|
||||
MOVL wincall_fn(DX), AX
|
||||
CALL AX
|
||||
|
||||
// Restore original SP, g.
|
||||
get_tls(DI)
|
||||
POPL g(DI)
|
||||
POPL SP
|
||||
// Return result.
|
||||
MOVL c+0(FP), DX
|
||||
MOVL AX, wincall_r(DX)
|
||||
|
||||
// Someday the convention will be D is always cleared.
|
||||
CLD
|
||||
// GetLastError().
|
||||
MOVL 0x34(FS), BX
|
||||
MOVL BX, wincall_err(DX)
|
||||
|
||||
RET
|
||||
|
||||
|
@ -4,46 +4,57 @@
|
||||
|
||||
#include "amd64/asm.h"
|
||||
|
||||
// void *stdcall_raw(void *fn, uintptr nargs, void *args)
|
||||
TEXT runtime·stdcall_raw(SB),7,$8
|
||||
MOVQ fn+0(FP), AX
|
||||
MOVQ nargs+8(FP), CX
|
||||
MOVQ args+16(FP), R11
|
||||
#define maxargs 12
|
||||
|
||||
// Switch to m->g0 if needed.
|
||||
get_tls(DI)
|
||||
MOVQ m(DI), DX
|
||||
MOVQ g(DI), SI
|
||||
MOVQ SI, 0(SP) // save g
|
||||
MOVQ SP, m_gostack(DX) // save SP
|
||||
MOVQ m_g0(DX), SI
|
||||
CMPQ g(DI), SI
|
||||
JEQ 3(PC)
|
||||
MOVQ (g_sched+gobuf_sp)(SI), SP
|
||||
ANDQ $~15, SP
|
||||
MOVQ SI, g(DI)
|
||||
// void runtime·asmstdcall(void *c);
|
||||
TEXT runtime·asmstdcall(SB),7,$0
|
||||
// asmcgocall will put first argument into CX.
|
||||
PUSHQ CX // save for later
|
||||
MOVQ wincall_fn(CX), AX
|
||||
MOVQ wincall_args(CX), SI
|
||||
MOVQ wincall_n(CX), CX
|
||||
|
||||
SUBQ $0x60, SP
|
||||
// SetLastError(0).
|
||||
MOVQ 0x30(GS), DI
|
||||
MOVL $0, 0x68(DI)
|
||||
|
||||
// Copy args to new stack.
|
||||
SUBQ $(maxargs*8), SP // room for args
|
||||
|
||||
// Fast version, do not store args on the stack.
|
||||
CMPL CX, $4
|
||||
JLE loadregs
|
||||
|
||||
// Check we have enough room for args.
|
||||
CMPL CX, $maxargs
|
||||
JLE 2(PC)
|
||||
INT $3 // not enough room -> crash
|
||||
|
||||
// Copy args to the stack.
|
||||
MOVQ SP, DI
|
||||
MOVQ R11, SI
|
||||
CLD
|
||||
REP; MOVSQ
|
||||
MOVQ 0(R11), CX
|
||||
MOVQ 8(R11), DX
|
||||
MOVQ 16(R11), R8
|
||||
MOVQ 24(R11), R9
|
||||
MOVQ SP, SI
|
||||
|
||||
loadregs:
|
||||
// Load first 4 args into correspondent registers.
|
||||
MOVQ 0(SI), CX
|
||||
MOVQ 8(SI), DX
|
||||
MOVQ 16(SI), R8
|
||||
MOVQ 24(SI), R9
|
||||
|
||||
// Call stdcall function.
|
||||
CALL AX
|
||||
|
||||
// Restore original SP, g.
|
||||
get_tls(DI)
|
||||
MOVQ m(DI), DX
|
||||
MOVQ m_gostack(DX), SP // restore SP
|
||||
MOVQ 0(SP), SI // restore g
|
||||
MOVQ SI, g(DI)
|
||||
ADDQ $(maxargs*8), SP
|
||||
|
||||
// Return result.
|
||||
POPQ CX
|
||||
MOVQ AX, wincall_r(CX)
|
||||
|
||||
// GetLastError().
|
||||
MOVQ 0x30(GS), DI
|
||||
MOVL 0x68(DI), AX
|
||||
MOVQ AX, wincall_err(CX)
|
||||
|
||||
RET
|
||||
|
||||
@ -70,7 +81,7 @@ TEXT runtime·ctrlhandler(SB),7,$0
|
||||
MOVQ SP, BX
|
||||
|
||||
// setup dummy m, g
|
||||
SUBQ $(m_gostack+8), SP // at least space for m_gostack
|
||||
SUBQ $(m_fflag+4), SP // at least space for m_fflag
|
||||
LEAQ m_tls(SP), CX
|
||||
MOVQ CX, 0x58(GS)
|
||||
MOVQ SP, m(CX)
|
||||
|
@ -10,7 +10,7 @@ extern void *runtime·GetProcAddress;
|
||||
#pragma varargck countpos runtime·stdcall 2
|
||||
#pragma varargck type runtime·stdcall void*
|
||||
#pragma varargck type runtime·stdcall uintptr
|
||||
void *runtime·stdcall_raw(void *fn, uintptr nargs, void *args);
|
||||
void runtime·asmstdcall(void *c);
|
||||
void *runtime·stdcall(void *fn, int32 count, ...);
|
||||
uintptr runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "type.h"
|
||||
#include "defs.h"
|
||||
#include "os.h"
|
||||
#include "cgocall.h"
|
||||
|
||||
#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
|
||||
#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
|
||||
@ -221,34 +222,27 @@ runtime·gettime(int64 *sec, int32 *usec)
|
||||
void *
|
||||
runtime·stdcall(void *fn, int32 count, ...)
|
||||
{
|
||||
return runtime·stdcall_raw(fn, count, (uintptr*)&count + 1);
|
||||
WinCall c;
|
||||
|
||||
c.fn = fn;
|
||||
c.n = count;
|
||||
c.args = (uintptr*)&count + 1;
|
||||
runtime·asmcgocall(runtime·asmstdcall, &c);
|
||||
return (void*)c.r;
|
||||
}
|
||||
|
||||
uintptr
|
||||
runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err)
|
||||
{
|
||||
G *oldlock;
|
||||
uintptr ret;
|
||||
WinCall c;
|
||||
|
||||
/*
|
||||
* Lock g to m to ensure we stay on the same stack if we do a callback.
|
||||
*/
|
||||
oldlock = m->lockedg;
|
||||
m->lockedg = g;
|
||||
g->lockedm = m;
|
||||
|
||||
runtime·entersyscall();
|
||||
runtime·setlasterror(0);
|
||||
ret = (uintptr)runtime·stdcall_raw(fn, nargs, args);
|
||||
c.fn = fn;
|
||||
c.n = nargs;
|
||||
c.args = args;
|
||||
runtime·cgocall(runtime·asmstdcall, &c);
|
||||
if(err)
|
||||
*err = runtime·getlasterror();
|
||||
runtime·exitsyscall();
|
||||
|
||||
m->lockedg = oldlock;
|
||||
if(oldlock == nil)
|
||||
g->lockedm = nil;
|
||||
|
||||
return ret;
|
||||
*err = c.err;
|
||||
return c.r;
|
||||
}
|
||||
|
||||
uint32
|
||||
|
Loading…
Reference in New Issue
Block a user