summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/windows
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-02-14 13:23:51 +0100
committerOndřej Surý <ondrej@sury.org>2011-02-14 13:23:51 +0100
commit758ff64c69e34965f8af5b2d6ffd65e8d7ab2150 (patch)
tree6d6b34f8c678862fe9b56c945a7b63f68502c245 /src/pkg/runtime/windows
parent3e45412327a2654a77944249962b3652e6142299 (diff)
downloadgolang-upstream/2011-02-01.1.tar.gz
Imported Upstream version 2011-02-01.1upstream/2011-02-01.1
Diffstat (limited to 'src/pkg/runtime/windows')
-rw-r--r--src/pkg/runtime/windows/386/defs.h61
-rw-r--r--src/pkg/runtime/windows/386/rt0.s8
-rw-r--r--src/pkg/runtime/windows/386/signal.c79
-rw-r--r--src/pkg/runtime/windows/386/sys.s145
-rw-r--r--src/pkg/runtime/windows/defs.c18
-rw-r--r--src/pkg/runtime/windows/mem.c35
-rw-r--r--src/pkg/runtime/windows/os.h32
-rw-r--r--src/pkg/runtime/windows/runtime_defs.go22
-rw-r--r--src/pkg/runtime/windows/syscall.goc128
-rw-r--r--src/pkg/runtime/windows/thread.c180
10 files changed, 499 insertions, 209 deletions
diff --git a/src/pkg/runtime/windows/386/defs.h b/src/pkg/runtime/windows/386/defs.h
index f5a16367e..a2a882103 100644
--- a/src/pkg/runtime/windows/386/defs.h
+++ b/src/pkg/runtime/windows/386/defs.h
@@ -10,8 +10,69 @@ enum {
PROT_EXEC = 0x4,
MAP_ANON = 0x1,
MAP_PRIVATE = 0x2,
+ EXCEPTION_ACCESS_VIOLATION = 0xc0000005,
+ EXCEPTION_BREAKPOINT = 0x80000003,
+ EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d,
+ EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e,
+ EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f,
+ EXCEPTION_FLT_OVERFLOW = 0xc0000091,
+ EXCEPTION_FLT_UNDERFLOW = 0xc0000093,
+ EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094,
+ EXCEPTION_INT_OVERFLOW = 0xc0000095,
};
// Types
#pragma pack on
+
+typedef struct ExceptionRecord ExceptionRecord;
+struct ExceptionRecord {
+ uint32 ExceptionCode;
+ uint32 ExceptionFlags;
+ ExceptionRecord *ExceptionRecord;
+ void *ExceptionAddress;
+ uint32 NumberParameters;
+ uint32 ExceptionInformation[15];
+};
+
+typedef struct FloatingSaveArea FloatingSaveArea;
+struct FloatingSaveArea {
+ uint32 ControlWord;
+ uint32 StatusWord;
+ uint32 TagWord;
+ uint32 ErrorOffset;
+ uint32 ErrorSelector;
+ uint32 DataOffset;
+ uint32 DataSelector;
+ uint8 RegisterArea[80];
+ uint32 Cr0NpxState;
+};
+
+typedef struct Context Context;
+struct Context {
+ uint32 ContextFlags;
+ uint32 Dr0;
+ uint32 Dr1;
+ uint32 Dr2;
+ uint32 Dr3;
+ uint32 Dr6;
+ uint32 Dr7;
+ FloatingSaveArea FloatSave;
+ uint32 SegGs;
+ uint32 SegFs;
+ uint32 SegEs;
+ uint32 SegDs;
+ uint32 Edi;
+ uint32 Esi;
+ uint32 Ebx;
+ uint32 Edx;
+ uint32 Ecx;
+ uint32 Eax;
+ uint32 Ebp;
+ uint32 Eip;
+ uint32 SegCs;
+ uint32 EFlags;
+ uint32 Esp;
+ uint32 SegSs;
+ uint8 ExtendedRegisters[512];
+};
#pragma pack off
diff --git a/src/pkg/runtime/windows/386/rt0.s b/src/pkg/runtime/windows/386/rt0.s
index e379830fb..3b023de2f 100644
--- a/src/pkg/runtime/windows/386/rt0.s
+++ b/src/pkg/runtime/windows/386/rt0.s
@@ -3,4 +3,12 @@
// license that can be found in the LICENSE file.
TEXT _rt0_386_windows(SB),7,$0
+ // Set up SEH frame for bootstrap m
+ PUSHL $runtime·sigtramp(SB)
+ PUSHL 0(FS)
+ MOVL SP, 0(FS)
+
JMP _rt0_386(SB)
+
+DATA runtime·iswindows(SB)/4, $1
+GLOBL runtime·iswindows(SB), $4
diff --git a/src/pkg/runtime/windows/386/signal.c b/src/pkg/runtime/windows/386/signal.c
index 2ae79e5b5..69178cdd0 100644
--- a/src/pkg/runtime/windows/386/signal.c
+++ b/src/pkg/runtime/windows/386/signal.c
@@ -3,6 +3,26 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "defs.h"
+#include "os.h"
+
+void
+runtime·dumpregs(Context *r)
+{
+ runtime·printf("eax %x\n", r->Eax);
+ runtime·printf("ebx %x\n", r->Ebx);
+ runtime·printf("ecx %x\n", r->Ecx);
+ runtime·printf("edx %x\n", r->Edx);
+ runtime·printf("edi %x\n", r->Edi);
+ runtime·printf("esi %x\n", r->Esi);
+ runtime·printf("ebp %x\n", r->Ebp);
+ runtime·printf("esp %x\n", r->Esp);
+ runtime·printf("eip %x\n", r->Eip);
+ runtime·printf("eflags %x\n", r->EFlags);
+ runtime·printf("cs %x\n", r->SegCs);
+ runtime·printf("fs %x\n", r->SegFs);
+ runtime·printf("gs %x\n", r->SegGs);
+}
void
runtime·initsig(int32)
@@ -15,3 +35,62 @@ runtime·signame(int32)
return runtime·emptystring;
}
+uint32
+runtime·sighandler(ExceptionRecord *info, void *frame, Context *r)
+{
+ uintptr *sp;
+ G *gp;
+
+ USED(frame);
+
+ switch(info->ExceptionCode) {
+ case EXCEPTION_BREAKPOINT:
+ r->Eip--; // because 8l generates 2 bytes for INT3
+ return 1;
+ }
+
+ if((gp = m->curg) != nil && runtime·issigpanic(info->ExceptionCode)) {
+ // Make it look like a call to the signal func.
+ // Have to pass arguments out of band since
+ // augmenting the stack frame would break
+ // the unwinding code.
+ gp->sig = info->ExceptionCode;
+ gp->sigcode0 = info->ExceptionInformation[0];
+ gp->sigcode1 = info->ExceptionInformation[1];
+ gp->sigpc = r->Eip;
+
+ // Only push runtime·sigpanic if r->eip != 0.
+ // If r->eip == 0, probably panicked because of a
+ // call to a nil func. Not pushing that onto sp will
+ // make the trace look like a call to runtime·sigpanic instead.
+ // (Otherwise the trace will end at runtime·sigpanic and we
+ // won't get to see who faulted.)
+ if(r->Eip != 0) {
+ sp = (uintptr*)r->Esp;
+ *--sp = r->Eip;
+ r->Esp = (uintptr)sp;
+ }
+ r->Eip = (uintptr)runtime·sigpanic;
+ return 0;
+ }
+
+ if(runtime·panicking) // traceback already printed
+ runtime·exit(2);
+ runtime·panicking = 1;
+
+ runtime·printf("Exception %x %p %p\n", info->ExceptionCode,
+ info->ExceptionInformation[0], info->ExceptionInformation[1]);
+
+ runtime·printf("PC=%x\n", r->Eip);
+ runtime·printf("\n");
+
+ if(runtime·gotraceback()){
+ runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, m->curg);
+ runtime·tracebackothers(m->curg);
+ runtime·dumpregs(r);
+ }
+
+ runtime·breakpoint();
+ runtime·exit(2);
+ return 0;
+}
diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s
index 7f99b34de..d1a8a49a9 100644
--- a/src/pkg/runtime/windows/386/sys.s
+++ b/src/pkg/runtime/windows/386/sys.s
@@ -5,7 +5,7 @@
#include "386/asm.h"
// void *stdcall_raw(void *fn, int32 count, uintptr *args)
-TEXT runtime·stdcall_raw(SB),7,$4
+TEXT runtime·stdcall_raw(SB),7,$0
// Copy arguments from stack.
MOVL fn+0(FP), AX
MOVL count+4(FP), CX // words
@@ -14,17 +14,18 @@ TEXT runtime·stdcall_raw(SB),7,$4
// 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 0(FS), SI
+ MOVL SI, m_sehframe(DX)
MOVL m_g0(DX), SI
CMPL g(DI), SI
- JEQ 3(PC)
+ MOVL SP, BX
+ JEQ 2(PC)
MOVL (m_sched+gobuf_sp)(DX), SP
+ PUSHL BX
+ PUSHL g(DI)
MOVL SI, g(DI)
// Copy args to new stack.
- SUBL $(10*4), SP // padding
MOVL CX, BX
SALL $2, BX
SUBL BX, SP // room for args
@@ -38,28 +39,122 @@ TEXT runtime·stdcall_raw(SB),7,$4
// Restore original SP, g.
get_tls(DI)
- MOVL m(DI), DX
- MOVL m_gostack(DX), SP // restore SP
- MOVL 0(SP), SI // restore g
- MOVL SI, g(DI)
+ POPL g(DI)
+ POPL SP
// Someday the convention will be D is always cleared.
CLD
- RET
+ RET
+
+// faster get/set last error
+TEXT runtime·getlasterror(SB),7,$0
+ MOVL 0x34(FS), AX
+ RET
+
+TEXT runtime·setlasterror(SB),7,$0
+ MOVL err+0(FP), AX
+ MOVL AX, 0x34(FS)
+ RET
+
+TEXT runtime·sigtramp(SB),7,$0
+ PUSHL BP // cdecl
+ PUSHL 0(FS)
+ CALL runtime·sigtramp1(SB)
+ POPL 0(FS)
+ POPL BP
+ RET
+
+TEXT runtime·sigtramp1(SB),0,$16-28
+ // unwinding?
+ MOVL info+12(FP), BX
+ MOVL 4(BX), CX // exception flags
+ ANDL $6, CX
+ MOVL $1, AX
+ JNZ sigdone
+
+ // place ourselves at the top of the SEH chain to
+ // ensure SEH frames lie within thread stack bounds
+ MOVL frame+16(FP), CX // our SEH frame
+ MOVL CX, 0(FS)
+
+ // copy arguments for call to sighandler
+ MOVL BX, 0(SP)
+ MOVL CX, 4(SP)
+ MOVL context+20(FP), BX
+ MOVL BX, 8(SP)
+ MOVL dispatcher+24(FP), BX
+ MOVL BX, 12(SP)
+
+ CALL runtime·sighandler(SB)
+ TESTL AX, AX
+ JZ sigdone
+
+ // call windows default handler early
+ MOVL 4(SP), BX // our SEH frame
+ MOVL 0(BX), BX // SEH frame of default handler
+ MOVL BX, 4(SP) // set establisher frame
+ CALL 4(BX)
+
+sigdone:
+ RET
+
+// Called from dynamic function created by ../thread.c compilecallback,
+// running on Windows stack (not Go stack).
+// BX, BP, SI, DI registers and DF flag are preserved
+// as required by windows callback convention.
+// AX = address of go func we need to call
+// DX = total size of arguments
+//
+TEXT runtime·callbackasm+0(SB),7,$0
+ LEAL 8(SP), CX
+
+ // save registers as required for windows callback
+ PUSHL 0(FS)
+ PUSHL DI
+ PUSHL SI
+ PUSHL BP
+ PUSHL BX
+ PUSHL DX
+ PUSHL CX
+ PUSHL AX
+
+ // reinstall our SEH handler
+ get_tls(CX)
+ MOVL m(CX), CX
+ MOVL m_sehframe(CX), CX
+ MOVL CX, 0(FS)
+ CLD
+
+ CALL runtime·cgocallback(SB)
+
+ // restore registers as required for windows callback
+ POPL CX
+ POPL CX
+ POPL DX
+ POPL BX
+ POPL BP
+ POPL SI
+ POPL DI
+ POPL 0(FS)
+ CLD
+
+ RET
// void tstart(M *newm);
TEXT runtime·tstart(SB),7,$0
MOVL newm+4(SP), CX // m
MOVL m_g0(CX), DX // g
- MOVL SP, DI // remember stack
+ // Set up SEH frame
+ PUSHL $runtime·sigtramp(SB)
+ PUSHL 0(FS)
+ MOVL SP, 0(FS)
// 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
+ SUBL $(64*1024), AX // stack size
MOVL AX, g_stackguard(DX)
// Set up tls.
@@ -68,20 +163,17 @@ TEXT runtime·tstart(SB),7,$0
MOVL CX, m(SI)
MOVL DX, g(SI)
- // Use scheduler stack now.
- MOVL g_stackbase(DX), SP
-
// Someday the convention will be D is always cleared.
CLD
- PUSHL DI // original stack
-
- CALL runtime·stackcheck(SB) // clobbers AX,CX
+ CALL runtime·stackcheck(SB) // clobbers AX,CX
CALL runtime·mstart(SB)
- POPL DI // original stack
- MOVL DI, SP
+ // Pop SEH frame
+ MOVL 0(FS), SP
+ POPL 0(FS)
+ POPL CX
RET
@@ -107,12 +199,3 @@ TEXT runtime·setldt(SB),7,$0
MOVL address+4(FP), CX
MOVL CX, 0x2c(FS)
RET
-
-// for now, return 0,0. only used for internal performance monitoring.
-TEXT runtime·gettime(SB),7,$0
- MOVL sec+0(FP), DI
- MOVL $0, (DI)
- MOVL $0, 4(DI) // zero extend 32 -> 64 bits
- MOVL usec+4(FP), DI
- MOVL $0, (DI)
- RET
diff --git a/src/pkg/runtime/windows/defs.c b/src/pkg/runtime/windows/defs.c
index db5f1400e..5aac03c81 100644
--- a/src/pkg/runtime/windows/defs.c
+++ b/src/pkg/runtime/windows/defs.c
@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <stdarg.h>
+#include <windef.h>
+#include <winbase.h>
+
enum {
$PROT_NONE = 0,
$PROT_READ = 1,
@@ -10,4 +14,18 @@ enum {
$MAP_ANON = 1,
$MAP_PRIVATE = 2,
+
+ $EXCEPTION_ACCESS_VIOLATION = STATUS_ACCESS_VIOLATION,
+ $EXCEPTION_BREAKPOINT = STATUS_BREAKPOINT,
+ $EXCEPTION_FLT_DENORMAL_OPERAND = STATUS_FLOAT_DENORMAL_OPERAND,
+ $EXCEPTION_FLT_DIVIDE_BY_ZERO = STATUS_FLOAT_DIVIDE_BY_ZERO,
+ $EXCEPTION_FLT_INEXACT_RESULT = STATUS_FLOAT_INEXACT_RESULT,
+ $EXCEPTION_FLT_OVERFLOW = STATUS_FLOAT_OVERFLOW,
+ $EXCEPTION_FLT_UNDERFLOW = STATUS_FLOAT_UNDERFLOW,
+ $EXCEPTION_INT_DIVIDE_BY_ZERO = STATUS_INTEGER_DIVIDE_BY_ZERO,
+ $EXCEPTION_INT_OVERFLOW = STATUS_INTEGER_OVERFLOW,
};
+
+typedef EXCEPTION_RECORD $ExceptionRecord;
+typedef FLOATING_SAVE_AREA $FloatingSaveArea;
+typedef CONTEXT $Context;
diff --git a/src/pkg/runtime/windows/mem.c b/src/pkg/runtime/windows/mem.c
index ba89887ea..19d11ce8d 100644
--- a/src/pkg/runtime/windows/mem.c
+++ b/src/pkg/runtime/windows/mem.c
@@ -15,16 +15,6 @@ enum {
PAGE_EXECUTE_READWRITE = 0x40,
};
-static void
-abort(int8 *name)
-{
- uintptr errno;
-
- errno = (uintptr)runtime·stdcall(runtime·GetLastError, 0);
- runtime·printf("%s failed with errno=%d\n", name, errno);
- runtime·throw(name);
-}
-
#pragma dynimport runtime·VirtualAlloc VirtualAlloc "kernel32.dll"
#pragma dynimport runtime·VirtualFree VirtualFree "kernel32.dll"
extern void *runtime·VirtualAlloc;
@@ -33,12 +23,8 @@ extern void *runtime·VirtualFree;
void*
runtime·SysAlloc(uintptr n)
{
- void *v;
-
- v = runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if(v == 0)
- abort("VirtualAlloc");
- return v;
+ mstats.sys += n;
+ return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
void
@@ -53,12 +39,25 @@ runtime·SysFree(void *v, uintptr n)
{
uintptr r;
+ mstats.sys -= n;
r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, 0, MEM_RELEASE);
if(r == 0)
- abort("VirtualFree");
+ runtime·throw("runtime: failed to release pages");
+}
+
+void*
+runtime·SysReserve(void *v, uintptr n)
+{
+ return runtime·stdcall(runtime·VirtualAlloc, 4, v, n, MEM_RESERVE, 0);
}
void
-runtime·SysMemInit(void)
+runtime·SysMap(void *v, uintptr n)
{
+ void *p;
+
+ mstats.sys += n;
+ p = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if(p != v)
+ runtime·throw("runtime: cannot map pages in arena address space");
}
diff --git a/src/pkg/runtime/windows/os.h b/src/pkg/runtime/windows/os.h
index 77d0d32a0..391eace5a 100644
--- a/src/pkg/runtime/windows/os.h
+++ b/src/pkg/runtime/windows/os.h
@@ -4,33 +4,23 @@
extern void *runtime·LoadLibraryEx;
extern void *runtime·GetProcAddress;
-extern void *runtime·GetLastError;
-
-// Get start address of symbol data in memory.
-void *runtime·get_symdat_addr(void);
// Call a Windows function with stdcall conventions,
// and switch to os stack during the call.
-void *runtime·stdcall_raw(void *fn, int32 count, uintptr *args);
+void *runtime·stdcall_raw(void *fn, uintptr nargs, void *args);
void *runtime·stdcall(void *fn, int32 count, ...);
+uintptr runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err);
+
+uintptr runtime·getlasterror(void);
+void runtime·setlasterror(uintptr err);
-// Function to be called by windows CreateTread
+// Function to be called by windows CreateThread
// to start new os thread.
uint32 runtime·tstart_stdcall(M *newm);
-// Call stdcall Windows function StdcallParams.fn
-// with params StdcallParams.args,
-// followed immediately by GetLastError call.
-// Both return values are returned in StdcallParams.r and
-// StdcallParams.err. Will use os stack during the call.
-typedef struct StdcallParams StdcallParams;
-struct StdcallParams
-{
- void *fn;
- uintptr args[12];
- int32 n;
- uintptr r;
- uintptr err;
-};
+uint32 runtime·issigpanic(uint32);
+void runtime·sigpanic(void);
-void runtime·syscall(StdcallParams *p);
+// Windows dll function to go callback entry.
+byte *runtime·compilecallback(Eface fn, bool cleanstack);
+void *runtime·callbackasm(void);
diff --git a/src/pkg/runtime/windows/runtime_defs.go b/src/pkg/runtime/windows/runtime_defs.go
deleted file mode 100644
index 34a9b3259..000000000
--- a/src/pkg/runtime/windows/runtime_defs.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Go definitions of internal structures. Master is runtime.h
-
-package runtime
-
-import "unsafe"
-
-const (
- Windows = 1
-)
-
-// const ( Structrnd = sizeof(uintptr) )
-
-type lock struct {
- key uint32
- event unsafe.Pointer
-}
-
-type note lock
diff --git a/src/pkg/runtime/windows/syscall.goc b/src/pkg/runtime/windows/syscall.goc
index d3057c540..85071e051 100644
--- a/src/pkg/runtime/windows/syscall.goc
+++ b/src/pkg/runtime/windows/syscall.goc
@@ -6,106 +6,62 @@ package syscall
#include "runtime.h"
#include "os.h"
-func loadlibraryex(filename uintptr) (handle uint32) {
- StdcallParams p;
- p.fn = (void*)runtime·LoadLibraryEx;
- p.args[0] = filename;
- p.args[1] = 0;
- p.args[2] = 0;
- p.n = 3;
- runtime·syscall(&p);
- handle = p.r;
+func loadlibraryex(filename uintptr) (handle uintptr) {
+ uintptr args[3] = { filename };
+ handle = runtime·syscall(runtime·LoadLibraryEx, 3, args, nil);
}
-func getprocaddress(handle uint32, procname uintptr) (proc uintptr) {
- StdcallParams p;
- p.fn = (void*)runtime·GetProcAddress;
- p.args[0] = handle;
- p.args[1] = procname;
- p.n = 2;
- runtime·syscall(&p);
- proc = p.r;
+func getprocaddress(handle uintptr, procname uintptr) (proc uintptr) {
+ USED(procname);
+ proc = runtime·syscall(runtime·GetProcAddress, 2, &handle, nil);
}
-func Syscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- StdcallParams p;
- p.fn = (void*)trap;
- p.args[0] = a1;
- p.args[1] = a2;
- p.args[2] = a3;
- p.n = 3;
- runtime·syscall(&p);
- r1 = p.r;
- r2 = 0;
- err = p.err;
+func NewCallback(fn Eface) (code uintptr) {
+ code = (uintptr)runtime·compilecallback(fn, true);
}
-func Syscall6(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- StdcallParams p;
- p.fn = (void*)trap;
- p.args[0] = a1;
- p.args[1] = a2;
- p.args[2] = a3;
- p.args[3] = a4;
- p.args[4] = a5;
- p.args[5] = a6;
- p.n = 6;
- runtime·syscall(&p);
- r1 = p.r;
+func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+ USED(a2);
+ USED(a3);
+ r1 = runtime·syscall((void*)fn, nargs, &a1, &err);
r2 = 0;
- err = p.err;
}
-func Syscall9(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, lasterr uintptr) {
- StdcallParams p;
- p.fn = (void*)trap;
- p.args[0] = a1;
- p.args[1] = a2;
- p.args[2] = a3;
- p.args[3] = a4;
- p.args[4] = a5;
- p.args[5] = a6;
- p.args[6] = a7;
- p.args[7] = a8;
- p.args[8] = a9;
- p.n = 9;
- runtime·syscall(&p);
- r1 = p.r;
+func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+ USED(a2);
+ USED(a3);
+ USED(a4);
+ USED(a5);
+ USED(a6);
+ r1 = runtime·syscall((void*)fn, nargs, &a1, &err);
r2 = 0;
- lasterr = p.err;
}
-func Syscall12(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, lasterr uintptr) {
- StdcallParams p;
- p.fn = (void*)trap;
- p.args[0] = a1;
- p.args[1] = a2;
- p.args[2] = a3;
- p.args[3] = a4;
- p.args[4] = a5;
- p.args[5] = a6;
- p.args[6] = a7;
- p.args[7] = a8;
- p.args[8] = a9;
- p.args[9] = a10;
- p.args[10] = a11;
- p.args[11] = a12;
- p.n = 12;
- runtime·syscall(&p);
- r1 = p.r;
+func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+ USED(a2);
+ USED(a3);
+ USED(a4);
+ USED(a5);
+ USED(a6);
+ USED(a7);
+ USED(a8);
+ USED(a9);
+ r1 = runtime·syscall((void*)fn, nargs, &a1, &err);
r2 = 0;
- lasterr = p.err;
}
-func RawSyscall(trap uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
- StdcallParams p;
- p.fn = (void*)trap;
- p.args[0] = a1;
- p.args[1] = a2;
- p.args[2] = a3;
- p.n = 3;
- runtime·syscall(&p);
- r1 = p.r;
+func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
+ USED(a2);
+ USED(a3);
+ USED(a4);
+ USED(a5);
+ USED(a6);
+ USED(a7);
+ USED(a8);
+ USED(a9);
+ USED(a10);
+ USED(a11);
+ USED(a12);
+ r1 = runtime·syscall((void*)fn, nargs, &a1, &err);
r2 = 0;
- err = p.err;
}
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c
index 9b5181337..278a5da69 100644
--- a/src/pkg/runtime/windows/thread.c
+++ b/src/pkg/runtime/windows/thread.c
@@ -3,48 +3,48 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "type.h"
+#include "defs.h"
#include "os.h"
-#pragma dynimport runtime·LoadLibraryEx LoadLibraryExA "kernel32.dll"
-#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
+#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
+#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
#pragma dynimport runtime·ExitProcess ExitProcess "kernel32.dll"
+#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
+#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
+#pragma dynimport runtime·GetProcAddress GetProcAddress "kernel32.dll"
#pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll"
+#pragma dynimport runtime·LoadLibraryEx LoadLibraryExA "kernel32.dll"
+#pragma dynimport runtime·QueryPerformanceCounter QueryPerformanceCounter "kernel32.dll"
+#pragma dynimport runtime·QueryPerformanceFrequency QueryPerformanceFrequency "kernel32.dll"
#pragma dynimport runtime·SetEvent SetEvent "kernel32.dll"
+#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
#pragma dynimport runtime·WriteFile WriteFile "kernel32.dll"
-#pragma dynimport runtime·GetLastError GetLastError "kernel32.dll"
-#pragma dynimport runtime·SetLastError SetLastError "kernel32.dll"
-// Also referenced by external packages
extern void *runtime·CloseHandle;
+extern void *runtime·CreateEvent;
+extern void *runtime·CreateThread;
extern void *runtime·ExitProcess;
+extern void *runtime·FreeEnvironmentStringsW;
+extern void *runtime·GetEnvironmentStringsW;
+extern void *runtime·GetProcAddress;
extern void *runtime·GetStdHandle;
+extern void *runtime·LoadLibraryEx;
+extern void *runtime·QueryPerformanceCounter;
+extern void *runtime·QueryPerformanceFrequency;
extern void *runtime·SetEvent;
+extern void *runtime·WaitForSingleObject;
extern void *runtime·WriteFile;
-extern void *runtime·LoadLibraryEx;
-extern void *runtime·GetProcAddress;
-extern void *runtime·GetLastError;
-extern void *runtime·SetLastError;
-
-#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
-#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
-#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
-extern void *runtime·CreateEvent;
-extern void *runtime·CreateThread;
-extern void *runtime·WaitForSingleObject;
+static int64 timerfreq;
void
runtime·osinit(void)
{
+ runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq);
}
-#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll"
-#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll"
-
-extern void *runtime·GetEnvironmentStringsW;
-extern void *runtime·FreeEnvironmentStringsW;
-
void
runtime·goenvs(void)
{
@@ -193,6 +193,17 @@ runtime·minit(void)
{
}
+void
+runtime·gettime(int64 *sec, int32 *usec)
+{
+ int64 count;
+
+ runtime·stdcall(runtime·QueryPerformanceCounter, 1, &count);
+ *sec = count / timerfreq;
+ count %= timerfreq;
+ *usec = count*1000000 / timerfreq;
+}
+
// Calling stdcall on os stack.
#pragma textflag 7
void *
@@ -201,17 +212,124 @@ runtime·stdcall(void *fn, int32 count, ...)
return runtime·stdcall_raw(fn, count, (uintptr*)(&count + 1));
}
-void
-runtime·syscall(StdcallParams *p)
+uintptr
+runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err)
{
- uintptr a;
+ 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();
- // TODO(brainman): Move calls to SetLastError and GetLastError
- // to stdcall_raw to speed up syscall.
- a = 0;
- runtime·stdcall_raw(runtime·SetLastError, 1, &a);
- p->r = (uintptr)runtime·stdcall_raw((void*)p->fn, p->n, p->args);
- p->err = (uintptr)runtime·stdcall_raw(runtime·GetLastError, 0, &a);
+ runtime·setlasterror(0);
+ ret = (uintptr)runtime·stdcall_raw(fn, nargs, args);
+ if(err)
+ *err = runtime·getlasterror();
runtime·exitsyscall();
+
+ m->lockedg = oldlock;
+ if(oldlock == nil)
+ g->lockedm = nil;
+
+ return ret;
+}
+
+uint32
+runtime·issigpanic(uint32 code)
+{
+ switch(code) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ case EXCEPTION_INT_OVERFLOW:
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_UNDERFLOW:
+ return 1;
+ }
+ return 0;
+}
+
+void
+runtime·sigpanic(void)
+{
+ switch(g->sig) {
+ case EXCEPTION_ACCESS_VIOLATION:
+ if(g->sigcode1 < 0x1000)
+ runtime·panicstring("invalid memory address or nil pointer dereference");
+ runtime·printf("unexpected fault address %p\n", g->sigcode1);
+ runtime·throw("fault");
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ runtime·panicstring("integer divide by zero");
+ case EXCEPTION_INT_OVERFLOW:
+ runtime·panicstring("integer overflow");
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ case EXCEPTION_FLT_OVERFLOW:
+ case EXCEPTION_FLT_UNDERFLOW:
+ runtime·panicstring("floating point error");
+ }
+ runtime·throw("fault");
+}
+
+// Call back from windows dll into go.
+byte *
+runtime·compilecallback(Eface fn, bool cleanstack)
+{
+ Func *f;
+ int32 argsize, n;
+ byte *ret, *p;
+
+ if(fn.type->kind != KindFunc)
+ runtime·panicstring("not a function");
+ if((f = runtime·findfunc((uintptr)fn.data)) == nil)
+ runtime·throw("cannot find function");
+ argsize = (f->args-2) * 4;
+
+ // compute size of new fn.
+ // must match code laid out below.
+ n = 1+4; // MOVL fn, AX
+ n += 1+4; // MOVL argsize, DX
+ n += 1+4; // MOVL callbackasm, CX
+ n += 2; // CALL CX
+ n += 1; // RET
+ if(cleanstack)
+ n += 2; // ... argsize
+
+ ret = p = runtime·mal(n);
+
+ // MOVL fn, AX
+ *p++ = 0xb8;
+ *(uint32*)p = (uint32)fn.data;
+ p += 4;
+
+ // MOVL argsize, DX
+ *p++ = 0xba;
+ *(uint32*)p = argsize;
+ p += 4;
+
+ // MOVL callbackasm, CX
+ *p++ = 0xb9;
+ *(uint32*)p = (uint32)runtime·callbackasm;
+ p += 4;
+
+ // CALL CX
+ *p++ = 0xff;
+ *p++ = 0xd1;
+
+ // RET argsize?
+ if(cleanstack) {
+ *p++ = 0xc2;
+ *(uint16*)p = argsize;
+ } else
+ *p = 0xc3;
+
+ return ret;
}