]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use cgo runtime functions to call windows syscalls
authorAlex Brainman <alex.brainman@gmail.com>
Sat, 27 Aug 2011 13:17:00 +0000 (23:17 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Sat, 27 Aug 2011 13:17:00 +0000 (23:17 +1000)
R=rsc
CC=golang-dev, jp, vcc.163
https://golang.org/cl/4926042

src/pkg/runtime/cgocall.c
src/pkg/runtime/mkasmh.sh
src/pkg/runtime/runtime.h
src/pkg/runtime/windows/386/sys.s
src/pkg/runtime/windows/amd64/sys.s
src/pkg/runtime/windows/os.h
src/pkg/runtime/windows/thread.c

index c2f8620a657607018ffb06a8c0428bc6cd075622..4fdb912fa9c2400a3485b9c8715018c0572d5947 100644 (file)
@@ -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)
index 328e2d5ba491327d7a54ddfe9c01aa93a843b063..920e79a0245b926df259ade61b778c37c37fda30 100755 (executable)
@@ -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;
index 84bab5877227aa8246b7f242909aeaeb5929b701..6feedcbc821be590ffcb9ff96fa77d0a3d8c99ec 100644 (file)
@@ -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
index 703f77d55be748413140985c8f42c3e200b4c73a..111e3d94c3591be534fbbdcf2a81129a05706927 100644 (file)
@@ -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
-
-       // 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)
+// void runtime·asmstdcall(void *c);
+TEXT runtime·asmstdcall(SB),7,$0
+       MOVL    c+0(FP), DX
+
+       // 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
 
index 891e0d50f957c5f2c61fc0f7cd0ecd45b4788aa7..ddb2f5df438da4c387e7fa972cf932e8b64f61c4 100644 (file)
@@ -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
-
-       // 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)
-       
-       SUBQ    $0x60, SP
-       
-       // Copy args to new stack.
+#define maxargs 12
+
+// 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
+
+       // SetLastError(0).
+       MOVQ    0x30(GS), DI
+       MOVL    $0, 0x68(DI)
+
+       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)
index bc96787334f9e5e005f8290c63e754f223d81584..a8cc299b8c914e0670f9723e4241661af4e23f0a 100644 (file)
@@ -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);
 
index e08d1b6f0e077d2a73b935b183a252484668922c..fbcbf871e6b0ba1c4af51c39b4f0301e605ef682 100644 (file)
@@ -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;
-
-       /*
-        * 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();
+       WinCall c;
 
-       m->lockedg = oldlock;
-       if(oldlock == nil)
-               g->lockedm = nil;
-
-       return ret;
+       c.fn = fn;
+       c.n = nargs;
+       c.args = args;
+       runtime·cgocall(runtime·asmstdcall, &c);
+       if(err)
+               *err = c.err;
+       return c.r;
 }
 
 uint32