Commit 2a808826 authored by Alex Brainman's avatar Alex Brainman

runtime: use cgo runtime functions to call windows syscalls

R=rsc
CC=golang-dev, jp, vcc.163
https://golang.org/cl/4926042
parent a88994f8
...@@ -94,7 +94,7 @@ runtime·cgocall(void (*fn)(void*), void *arg) ...@@ -94,7 +94,7 @@ runtime·cgocall(void (*fn)(void*), void *arg)
{ {
Defer d; Defer d;
if(!runtime·iscgo) if(!runtime·iscgo && !Windows)
runtime·throw("cgocall unavailable"); runtime·throw("cgocall unavailable");
if(fn == 0) if(fn == 0)
......
...@@ -96,6 +96,7 @@ awk ' ...@@ -96,6 +96,7 @@ awk '
/^aggr G$/ { aggr="g" } /^aggr G$/ { aggr="g" }
/^aggr M$/ { aggr = "m" } /^aggr M$/ { aggr = "m" }
/^aggr Gobuf$/ { aggr = "gobuf" } /^aggr Gobuf$/ { aggr = "gobuf" }
/^aggr WinCall$/ { aggr = "wincall" }
/^}/ { aggr = "" } /^}/ { aggr = "" }
# Gobuf 24 sched; # Gobuf 24 sched;
......
...@@ -70,6 +70,7 @@ typedef struct Hmap Hmap; ...@@ -70,6 +70,7 @@ typedef struct Hmap Hmap;
typedef struct Hchan Hchan; typedef struct Hchan Hchan;
typedef struct Complex64 Complex64; typedef struct Complex64 Complex64;
typedef struct Complex128 Complex128; typedef struct Complex128 Complex128;
typedef struct WinCall WinCall;
/* /*
* per-cpu declaration. * per-cpu declaration.
...@@ -250,11 +251,6 @@ struct M ...@@ -250,11 +251,6 @@ struct M
uint32 freglo[16]; // D[i] lsb and F[i] uint32 freglo[16]; // D[i] lsb and F[i]
uint32 freghi[16]; // D[i] msb and F[i+16] uint32 freghi[16]; // D[i] msb and F[i+16]
uint32 fflag; // floating point compare flags uint32 fflag; // floating point compare flags
#ifdef __WINDOWS__
#ifdef _64BIT
void* gostack;
#endif
#endif
}; };
struct Stktop struct Stktop
...@@ -306,6 +302,15 @@ struct Func ...@@ -306,6 +302,15 @@ struct Func
int32 locals; // number of 32-bit locals 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__ #ifdef __WINDOWS__
enum { enum {
Windows = 1 Windows = 1
......
...@@ -4,44 +4,34 @@ ...@@ -4,44 +4,34 @@
#include "386/asm.h" #include "386/asm.h"
// void *stdcall_raw(void *fn, int32 count, uintptr *args) // void runtime·asmstdcall(void *c);
TEXT runtime·stdcall_raw(SB),7,$0 TEXT runtime·asmstdcall(SB),7,$0
// Copy arguments from stack. MOVL c+0(FP), DX
MOVL fn+0(FP), AX
MOVL count+4(FP), CX // words // SetLastError(0).
MOVL args+8(FP), BP MOVL $0, 0x34(FS)
// 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)
// Copy args to new stack. // Copy args to the stack.
MOVL wincall_n(DX), CX // words
MOVL CX, BX MOVL CX, BX
SALL $2, BX SALL $2, BX
SUBL BX, SP // room for args SUBL BX, SP // room for args
MOVL SP, DI MOVL SP, DI
MOVL BP, SI MOVL wincall_args(DX), SI
CLD CLD
REP; MOVSL REP; MOVSL
// Call stdcall function. // Call stdcall function.
MOVL wincall_fn(DX), AX
CALL AX CALL AX
// Restore original SP, g. // Return result.
get_tls(DI) MOVL c+0(FP), DX
POPL g(DI) MOVL AX, wincall_r(DX)
POPL SP
// Someday the convention will be D is always cleared. // GetLastError().
CLD MOVL 0x34(FS), BX
MOVL BX, wincall_err(DX)
RET RET
......
...@@ -4,46 +4,57 @@ ...@@ -4,46 +4,57 @@
#include "amd64/asm.h" #include "amd64/asm.h"
// void *stdcall_raw(void *fn, uintptr nargs, void *args) #define maxargs 12
TEXT runtime·stdcall_raw(SB),7,$8
MOVQ fn+0(FP), AX // void runtime·asmstdcall(void *c);
MOVQ nargs+8(FP), CX TEXT runtime·asmstdcall(SB),7,$0
MOVQ args+16(FP), R11 // asmcgocall will put first argument into CX.
PUSHQ CX // save for later
// Switch to m->g0 if needed. MOVQ wincall_fn(CX), AX
get_tls(DI) MOVQ wincall_args(CX), SI
MOVQ m(DI), DX MOVQ wincall_n(CX), CX
MOVQ g(DI), SI
MOVQ SI, 0(SP) // save g // SetLastError(0).
MOVQ SP, m_gostack(DX) // save SP MOVQ 0x30(GS), DI
MOVQ m_g0(DX), SI MOVL $0, 0x68(DI)
CMPQ g(DI), SI
JEQ 3(PC) SUBQ $(maxargs*8), SP // room for args
MOVQ (g_sched+gobuf_sp)(SI), SP
ANDQ $~15, SP // Fast version, do not store args on the stack.
MOVQ SI, g(DI) CMPL CX, $4
JLE loadregs
SUBQ $0x60, SP
// Check we have enough room for args.
// Copy args to new stack. CMPL CX, $maxargs
JLE 2(PC)
INT $3 // not enough room -> crash
// Copy args to the stack.
MOVQ SP, DI MOVQ SP, DI
MOVQ R11, SI
CLD CLD
REP; MOVSQ REP; MOVSQ
MOVQ 0(R11), CX MOVQ SP, SI
MOVQ 8(R11), DX
MOVQ 16(R11), R8 loadregs:
MOVQ 24(R11), R9 // 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 stdcall function.
CALL AX CALL AX
// Restore original SP, g. ADDQ $(maxargs*8), SP
get_tls(DI)
MOVQ m(DI), DX // Return result.
MOVQ m_gostack(DX), SP // restore SP POPQ CX
MOVQ 0(SP), SI // restore g MOVQ AX, wincall_r(CX)
MOVQ SI, g(DI)
// GetLastError().
MOVQ 0x30(GS), DI
MOVL 0x68(DI), AX
MOVQ AX, wincall_err(CX)
RET RET
...@@ -70,7 +81,7 @@ TEXT runtime·ctrlhandler(SB),7,$0 ...@@ -70,7 +81,7 @@ TEXT runtime·ctrlhandler(SB),7,$0
MOVQ SP, BX MOVQ SP, BX
// setup dummy m, g // 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 LEAQ m_tls(SP), CX
MOVQ CX, 0x58(GS) MOVQ CX, 0x58(GS)
MOVQ SP, m(CX) MOVQ SP, m(CX)
......
...@@ -10,7 +10,7 @@ extern void *runtime·GetProcAddress; ...@@ -10,7 +10,7 @@ extern void *runtime·GetProcAddress;
#pragma varargck countpos runtime·stdcall 2 #pragma varargck countpos runtime·stdcall 2
#pragma varargck type runtime·stdcall void* #pragma varargck type runtime·stdcall void*
#pragma varargck type runtime·stdcall uintptr #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, ...); void *runtime·stdcall(void *fn, int32 count, ...);
uintptr runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err); uintptr runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err);
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "type.h" #include "type.h"
#include "defs.h" #include "defs.h"
#include "os.h" #include "os.h"
#include "cgocall.h"
#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll" #pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll" #pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
...@@ -221,34 +222,27 @@ runtime·gettime(int64 *sec, int32 *usec) ...@@ -221,34 +222,27 @@ runtime·gettime(int64 *sec, int32 *usec)
void * void *
runtime·stdcall(void *fn, int32 count, ...) 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 uintptr
runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err) runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err)
{ {
G *oldlock; WinCall c;
uintptr ret;
/*
* 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);
if(err)
*err = runtime·getlasterror();
runtime·exitsyscall();
m->lockedg = oldlock; c.fn = fn;
if(oldlock == nil) c.n = nargs;
g->lockedm = nil; c.args = args;
runtime·cgocall(runtime·asmstdcall, &c);
return ret; if(err)
*err = c.err;
return c.r;
} }
uint32 uint32
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment