]> Cypherpunks repositories - gostls13.git/commitdiff
runtime(windows): make sure scheduler runs on os stack and new stdcall implementation
authorAlex Brainman <alex.brainman@gmail.com>
Sun, 12 Sep 2010 01:45:16 +0000 (11:45 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Sun, 12 Sep 2010 01:45:16 +0000 (11:45 +1000)
R=rsc
CC=golang-dev
https://golang.org/cl/2009045

src/pkg/runtime/proc.c
src/pkg/runtime/runtime.h
src/pkg/runtime/windows/386/sys.s
src/pkg/runtime/windows/os.h
src/pkg/runtime/windows/syscall.goc
src/pkg/runtime/windows/thread.c

index 3dbc48fd9bcd0eee91bae869b7fd0b2038630b93..1d1b05969c6ee73fc67a013361c58f6e6c334623 100644 (file)
@@ -434,7 +434,11 @@ matchmg(void)
                                ts.fn = mstart;
                                runcgo(libcgo_thread_start, &ts);
                        } else {
-                               m->g0 = malg(8192);
+                               if(Windows)
+                                       // windows will layout sched stack on os stack
+                                       m->g0 = malg(-1);
+                               else
+                                       m->g0 = malg(8192);
                                newosproc(m, m->g0, m->g0->stackbase, mstart);
                        }
                }
index 6e8a79624a7cee83cdec4b71691aa36440719197..ca76729ec20d6a0acde853767e7a5708948d3040 100644 (file)
@@ -232,9 +232,7 @@ struct      M
        G*      lockedg;
        uint64 freg[8]; // Floating point register storage used by ARM software fp routines
 #ifdef __WINDOWS__
-       void*   return_address; // saved return address and stack
-       void*   stack_pointer;  // pointer for Windows stdcall
-       void*   os_stack_pointer;
+       void*   gostack;        // bookmark to keep track of go stack during stdcall
 #endif
 };
 struct Stktop
@@ -289,6 +287,16 @@ struct     Func
        int32   locals; // number of 32-bit locals
 };
 
+#ifdef __WINDOWS__
+enum {
+   Windows = 1
+};
+#else
+enum {
+   Windows = 0
+};
+#endif
+
 /*
  * defined macros
  *    you need super-goru privilege
index e36ef53e0a8e29ecc354b5d987acc9c9a851dc77..8c43f9bdcf1875dd853def95d64c8abf40e4bec1 100644 (file)
@@ -12,87 +12,102 @@ TEXT get_kernel_module(SB),7,$0
        MOVL    0x08(AX), AX            // get base of module
        RET
 
-// void *stdcall_raw(void *fn, ...);
-// Call fn with stdcall calling convention.
-// fn parameters are on stack.
-TEXT stdcall_raw(SB),7,$0
-       get_tls(CX)
-       MOVL    m(CX), CX
-       POPL    m_return_address(CX)    // save return address
-       POPL    AX                      // first arg is function pointer
-       MOVL    SP, m_stack_pointer(CX) // save stack pointer
-       CALL    AX
-       get_tls(CX)
-       MOVL    m(CX), CX
-       MOVL    m_stack_pointer(CX), SP
-       PUSHL   AX
-       PUSHL   m_return_address(CX)
-       RET
+// void *stdcall_raw(void *fn, int32 count, uintptr *args)
+TEXT stdcall_raw(SB),7,$4
+       // Copy arguments from stack.
+       MOVL    fn+0(FP), AX
+       MOVL    count+4(FP), CX         // words
+       MOVL    args+8(FP), BP
 
-// void syscall(StdcallParams *p);
-// Call p.fn syscall + GetLastError on os stack.
-TEXT syscall(SB),7,$16
-       MOVL    p+0(FP), AX
-       MOVL    SP, CX
-
-       // Figure out if we need to switch to m->g0 stack.
+       // Switch to m->g0 if needed.
        get_tls(DI)
        MOVL    m(DI), DX
+       MOVL    g(DI), SI
+       MOVL    SI, 0(SP)               // save g
+       MOVL    SP, m_gostack(DX)       // save SP
        MOVL    m_g0(DX), SI
        CMPL    g(DI), SI
-       JEQ     2(PC)
+       JEQ 3(PC)
        MOVL    (m_sched+gobuf_sp)(DX), SP
-
-       // Now on a scheduling stack (an os stack).
-       MOVL    g(DI), BP
-       MOVL    BP, 8(SP)
        MOVL    SI, g(DI)
-       MOVL    CX, 4(SP)
-       MOVL    AX, 0(SP)
-       CALL    call_syscall(SB)
-       
-       // Back; switch to original g and stack, re-establish
-       // "DF is clear" invariant.
+
+       // Copy args to new stack.
+       SUBL    $(10*4), SP             // padding
+       MOVL    CX, BX
+       SALL    $2, BX
+       SUBL    BX, SP                  // room for args
+       MOVL    SP, DI
+       MOVL    BP, SI
        CLD
+       REP; MOVSL
+
+       // Call stdcall function.
+       CALL    AX
+
+       // Restore original SP, g.
        get_tls(DI)
-       MOVL    8(SP), SI
+       MOVL    m(DI), DX
+       MOVL    m_gostack(DX), SP       // restore SP
+       MOVL    0(SP), SI               // restore g
        MOVL    SI, g(DI)
-       MOVL    4(SP), SP
-       RET
 
-TEXT threadstart(SB),7,$0
-       MOVL    4(SP), AX               // threadstart param
-       MOVL    0(AX), BX               // newosproc arg stack
-       MOVL    0(BX), CX               // m
-       MOVL    4(BX), DX               // g
+       // Someday the convention will be D is always cleared.
+       CLD
+
+       RET 
+
+// void tstart(M *newm);
+TEXT tstart(SB),7,$0
+       MOVL    newm+4(SP), CX          // m
+       MOVL    m_g0(CX), DX            // g
 
-       // set up tls
+       MOVL    SP, DI                  // remember stack
+
+       // Layout new m scheduler stack on os stack.
+       MOVL    SP, AX
+       SUBL    $256, AX                // just some space for ourselves
+       MOVL    AX, g_stackbase(DX)
+       SUBL    $8192, AX               // stack size
+       MOVL    AX, g_stackguard(DX)
+
+       // Set up tls.
        LEAL    m_tls(CX), SI
        MOVL    SI, 0x2c(FS)
        MOVL    CX, m(SI)
        MOVL    DX, g(SI)
-       MOVL    SP, m_os_stack_pointer(CX)
 
-       PUSHL   8(BX)                   // stk
-       PUSHL   12(BX)                  // fn
-       PUSHL   4(AX)                   // event_handle
+       // Use scheduler stack now.
+       MOVL    g_stackbase(DX), SP
+
+       // Someday the convention will be D is always cleared.
+       CLD
 
-       // signal that we're done with thread args
-       MOVL    SetEvent(SB), BX
-       CALL    BX                      // SetEvent(event_handle)
-       POPL    BX                      // fn
-       POPL    SP                      // stk
+       PUSHL   DI                      // original stack
 
        CALL    stackcheck(SB)          // clobbers AX,CX
-       CALL    BX                      // fn()
-
-       // cleanup stack before returning as we are stdcall
-       get_tls(CX)
-       MOVL    m(CX), CX
-       MOVL    m_os_stack_pointer(CX), SP
-       POPL    AX                      // return address
-       MOVL    AX, (SP)
-       XORL    AX, AX
+
+       CALL    mstart(SB)
+
+       POPL    DI                      // original stack
+       MOVL    DI, SP
+
+       RET
+
+// uint32 tstart_stdcall(M *newm);
+TEXT tstart_stdcall(SB),7,$0
+       MOVL    newm+4(SP), BX
+
+       PUSHL   BX
+       CALL    tstart+0(SB)
+       POPL    BX
+
+       // Adjust stack for stdcall to return properly.
+       MOVL    (SP), AX                // save return address
+       ADDL    $4, SP                  // remove single parameter
+       MOVL    AX, (SP)                // restore return address
+
+       XORL    AX, AX                  // return 0 == success
+
        RET
 
 // setldt(int entry, int address, int limit)
index 68efaa036a7584a1ece7841e98eccf48de5864b3..343ddbccf96fc1182c5c6bfbad1caf9693850c15 100644 (file)
@@ -19,13 +19,15 @@ void windows_goargs(void);
 // Get start address of symbol data in memory.
 void *get_symdat_addr(void);
 
-// Call a Windows function with stdcall conventions.
-void *stdcall_raw(void *fn, ...);
-
 // Call a Windows function with stdcall conventions,
 // and switch to os stack during the call.
+void *stdcall_raw(void *fn, int32 count, uintptr *args);
 void *stdcall(void *fn, int32 count, ...);
 
+// Function to be called by windows CreateTread
+// to start new os thread.
+uint32 tstart_stdcall(M *newm);
+
 // Call stdcall Windows function StdcallParams.fn
 // with params StdcallParams.args,
 // followed immediately by GetLastError call.
@@ -36,8 +38,9 @@ struct StdcallParams
 {
        void    *fn;
        uintptr args[12];
+       int32   n;
        uintptr r;
        uintptr err;
 };
-void call_syscall(void *args);
+
 void syscall(StdcallParams *p);
index 8287e704146d2f574f22496825a200a591fe33cb..306b7152964262ab87105ec80edd9e68d3627bab 100644 (file)
@@ -12,9 +12,8 @@ func loadlibraryex(filename uintptr) (handle uint32) {
        p.args[0] = filename;
        p.args[1] = 0;
        p.args[2] = 0;
-       ·entersyscall();
+       p.n = 3;
        syscall(&p);
-       ·exitsyscall();
        handle = p.r;
 }
 
@@ -23,9 +22,8 @@ func getprocaddress(handle uint32, procname uintptr) (proc uintptr) {
        p.fn = (void*)GetProcAddress;
        p.args[0] = handle;
        p.args[1] = procname;
-       ·entersyscall();
+       p.n = 2;
        syscall(&p);
-       ·exitsyscall();
        proc = p.r;
 }
 
@@ -35,9 +33,8 @@ func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 u
        p.args[0] = a1;
        p.args[1] = a2;
        p.args[2] = a3;
-       ·entersyscall();
+       p.n = 3;
        syscall(&p);
-       ·exitsyscall();
        r1 = p.r;
        r2 = 0;
        err = p.err;
@@ -52,9 +49,8 @@ func Syscall6(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 u
        p.args[3] = a4;
        p.args[4] = a5;
        p.args[5] = a6;
-       ·entersyscall();
+       p.n = 6;
        syscall(&p);
-       ·exitsyscall();
        r1 = p.r;
        r2 = 0;
        err = p.err;
@@ -72,9 +68,8 @@ func Syscall9(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 u
        p.args[6] = a7;
        p.args[7] = a8;
        p.args[8] = a9;
-       ·entersyscall();
+       p.n = 9;
        syscall(&p);
-       ·exitsyscall();
        r1 = p.r;
        r2 = 0;
        lasterr = p.err;
@@ -95,9 +90,8 @@ func Syscall12(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5
        p.args[9] = a10;
        p.args[10] = a11;
        p.args[11] = a12;
-       ·entersyscall();
+       p.n = 12;
        syscall(&p);
-       ·exitsyscall();
        r1 = p.r;
        r2 = 0;
        lasterr = p.err;
@@ -109,6 +103,7 @@ func RawSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r
        p.args[0] = a1;
        p.args[1] = a2;
        p.args[2] = a3;
+       p.n = 3;
        syscall(&p);
        r1 = p.r;
        r2 = 0;
index a9062250dc7482e1cfcda61bc6316408463836b8..82d1fa84e5613d7e7011386744c446603c7acd46 100644 (file)
@@ -77,8 +77,8 @@ get_proc_addr(void *library, void *name)
 {
        void *base;
 
-       base = stdcall_raw(LoadLibraryEx, library, 0, 0);
-       return stdcall_raw(GetProcAddress, base, name);
+       base = stdcall(LoadLibraryEx, 3, library, 0, 0);
+       return stdcall(GetProcAddress, 2, base, name);
 }
 
 void
@@ -251,17 +251,11 @@ notesleep(Note *n)
 void
 newosproc(M *m, G *g, void *stk, void (*fn)(void))
 {
-       struct {
-               void *args;
-               void *event_handle;
-       } param = { &m };
-       extern uint32 threadstart(void *p);
-
-       USED(g, stk, fn);
-       param.event_handle = stdcall(CreateEvent, 4, 0, 0, 0, 0);
-       stdcall(CreateThread, 6, 0, 0, threadstart, &param, 0, 0);
-       stdcall(WaitForSingleObject, 2, param.event_handle, -1);
-       stdcall(CloseHandle, 1, param.event_handle);
+       USED(stk);
+       USED(g);        // assuming g = m->g0
+       USED(fn);       // assuming fn = mstart
+
+       stdcall(CreateThread, 6, 0, 0, tstart_stdcall, m, 0, 0);
 }
 
 // Called to initialize a new m (including the bootstrap m).
@@ -275,25 +269,20 @@ minit(void)
 void *
 stdcall(void *fn, int32 count, ...)
 {
-       uintptr *a;
-       StdcallParams p;
-
-       p.fn = fn;
-       a = (uintptr*)(&count + 1);
-       while(count > 0) {
-               count--;
-               p.args[count] = a[count];
-       }
-       syscall(&p);
-       return (void*)(p.r);
+       return stdcall_raw(fn, count, (uintptr*)(&count + 1));
 }
 
 void
-call_syscall(void *args)
+syscall(StdcallParams *p)
 {
-       StdcallParams *p = (StdcallParams*)args;
-       stdcall_raw(SetLastError, 0);
-       p->r = (uintptr)stdcall_raw((void*)p->fn, p->args[0], p->args[1], p->args[2], p->args[3], p->args[4], p->args[5], p->args[6], p->args[7], p->args[8], p->args[9], p->args[10], p->args[11]);
-       p->err = (uintptr)stdcall_raw(GetLastError);
-       return;
+       uintptr a;
+
+       ·entersyscall();
+       // TODO(brainman): Move calls to SetLastError and GetLastError
+       // to stdcall_raw to speed up syscall.
+       a = 0;
+       stdcall_raw(SetLastError, 1, &a);
+       p->r = (uintptr)stdcall_raw((void*)p->fn, p->n, p->args);
+       p->err = (uintptr)stdcall_raw(GetLastError, 0, &a);
+       ·exitsyscall();
 }