summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/windows/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/windows/thread.c')
-rw-r--r--src/pkg/runtime/windows/thread.c180
1 files changed, 149 insertions, 31 deletions
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;
}