// Copyright 2009 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. #include "runtime.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·ExitProcess ExitProcess "kernel32.dll" #pragma dynimport runtime·GetStdHandle GetStdHandle "kernel32.dll" #pragma dynimport runtime·SetEvent SetEvent "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·ExitProcess; extern void *runtime·GetStdHandle; extern void *runtime·SetEvent; 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; void runtime·osinit(void) { } #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) { extern Slice os·Envs; uint16 *env; String *s; int32 i, n; uint16 *p; env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0); n = 0; for(p=env; *p; n++) p += runtime·findnullw(p)+1; s = runtime·malloc(n*sizeof s[0]); p = env; for(i=0; ievent == 0) initevent(&l->event); if(runtime·xadd(&l->key, 1) > 1) // someone else has it; wait runtime·stdcall(runtime·WaitForSingleObject, 2, l->event, -1); } static void eventunlock(Lock *l) { if(runtime·xadd(&l->key, -1) > 0) // someone else is waiting runtime·stdcall(runtime·SetEvent, 1, l->event); } void runtime·lock(Lock *l) { if(m->locks < 0) runtime·throw("lock count"); m->locks++; eventlock(l); } void runtime·unlock(Lock *l) { m->locks--; if(m->locks < 0) runtime·throw("lock count"); eventunlock(l); } void runtime·destroylock(Lock *l) { if(l->event != 0) runtime·stdcall(runtime·CloseHandle, 1, l->event); } void runtime·noteclear(Note *n) { eventlock(&n->lock); } void runtime·notewakeup(Note *n) { eventunlock(&n->lock); } void runtime·notesleep(Note *n) { eventlock(&n->lock); eventunlock(&n->lock); // Let other sleepers find out too. } void runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) { USED(stk); USED(g); // assuming g = m->g0 USED(fn); // assuming fn = mstart runtime·stdcall(runtime·CreateThread, 6, 0, 0, runtime·tstart_stdcall, m, 0, 0); } // Called to initialize a new m (including the bootstrap m). void runtime·minit(void) { } // Calling stdcall on os stack. #pragma textflag 7 void * runtime·stdcall(void *fn, int32 count, ...) { return runtime·stdcall_raw(fn, count, (uintptr*)(&count + 1)); } void runtime·syscall(StdcallParams *p) { uintptr a; 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·exitsyscall(); } 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"); }