diff options
Diffstat (limited to 'src/pkg/runtime/windows/thread.c')
-rw-r--r-- | src/pkg/runtime/windows/thread.c | 180 |
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; } |