diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-01-17 12:40:45 +0100 |
commit | 3e45412327a2654a77944249962b3652e6142299 (patch) | |
tree | bc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/runtime/windows/thread.c | |
parent | c533680039762cacbc37db8dc7eed074c3e497be (diff) | |
download | golang-upstream/2011.01.12.tar.gz |
Imported Upstream version 2011.01.12upstream/2011.01.12
Diffstat (limited to 'src/pkg/runtime/windows/thread.c')
-rw-r--r-- | src/pkg/runtime/windows/thread.c | 268 |
1 files changed, 97 insertions, 171 deletions
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c index c65f665b1..9b5181337 100644 --- a/src/pkg/runtime/windows/thread.c +++ b/src/pkg/runtime/windows/thread.c @@ -5,130 +5,84 @@ #include "runtime.h" #include "os.h" -extern void *get_kernel_module(void); +#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 -void *CloseHandle; -void *ExitProcess; -void *GetStdHandle; -void *SetEvent; -void *WriteFile; -void *VirtualAlloc; -void *LoadLibraryEx; -void *GetProcAddress; -void *GetLastError; - -static void *CreateEvent; -static void *CreateThread; -static void *GetModuleHandle; -static void *WaitForSingleObject; - -static void* -get_proc_addr2(byte *base, byte *name) -{ - byte *pe_header, *exports; - uint32 entries, *addr, *names, i; - uint16 *ordinals; - - pe_header = base+*(uint32*)(base+0x3c); - exports = base+*(uint32*)(pe_header+0x78); - entries = *(uint32*)(exports+0x18); - addr = (uint32*)(base+*(uint32*)(exports+0x1c)); - names = (uint32*)(base+*(uint32*)(exports+0x20)); - ordinals = (uint16*)(base+*(uint32*)(exports+0x24)); - for(i=0; i<entries; i++) { - byte *s = base+names[i]; - if(!strcmp(name, s)) - break; - } - if(i == entries) - return 0; - return base+addr[ordinals[i]]; -} +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 -osinit(void) +runtime·osinit(void) { - void *base; - - base = get_kernel_module(); - GetProcAddress = get_proc_addr2(base, (byte*)"GetProcAddress"); - LoadLibraryEx = get_proc_addr2(base, (byte*)"LoadLibraryExA"); - CloseHandle = get_proc_addr("kernel32.dll", "CloseHandle"); - CreateEvent = get_proc_addr("kernel32.dll", "CreateEventA"); - CreateThread = get_proc_addr("kernel32.dll", "CreateThread"); - ExitProcess = get_proc_addr("kernel32.dll", "ExitProcess"); - GetModuleHandle = get_proc_addr("kernel32.dll", "GetModuleHandleA"); - GetStdHandle = get_proc_addr("kernel32.dll", "GetStdHandle"); - SetEvent = get_proc_addr("kernel32.dll", "SetEvent"); - VirtualAlloc = get_proc_addr("kernel32.dll", "VirtualAlloc"); - WaitForSingleObject = get_proc_addr("kernel32.dll", "WaitForSingleObject"); - WriteFile = get_proc_addr("kernel32.dll", "WriteFile"); - GetLastError = get_proc_addr("kernel32.dll", "GetLastError"); } -// The arguments are strings. -void* -get_proc_addr(void *library, void *name) -{ - void *base; +#pragma dynimport runtime·GetEnvironmentStringsW GetEnvironmentStringsW "kernel32.dll" +#pragma dynimport runtime·FreeEnvironmentStringsW FreeEnvironmentStringsW "kernel32.dll" - base = stdcall_raw(LoadLibraryEx, library, 0, 0); - return stdcall_raw(GetProcAddress, base, name); -} +extern void *runtime·GetEnvironmentStringsW; +extern void *runtime·FreeEnvironmentStringsW; void -windows_goargs(void) +runtime·goenvs(void) { - extern Slice os·Args; extern Slice os·Envs; - void *gcl, *clta, *ges; - uint16 *cmd, *env, **argv; - String *gargv; - String *genvv; - int32 i, argc, envc; - uint16 *envp; - - gcl = get_proc_addr("kernel32.dll", "GetCommandLineW"); - clta = get_proc_addr("shell32.dll", "CommandLineToArgvW"); - ges = get_proc_addr("kernel32.dll", "GetEnvironmentStringsW"); - - cmd = stdcall(gcl, 0); - env = stdcall(ges, 0); - argv = stdcall(clta, 2, cmd, &argc); - - envc = 0; - for(envp=env; *envp; envc++) - envp += findnullw(envp)+1; - - gargv = malloc(argc*sizeof gargv[0]); - genvv = malloc(envc*sizeof genvv[0]); - - for(i=0; i<argc; i++) - gargv[i] = gostringw(argv[i]); - os·Args.array = (byte*)gargv; - os·Args.len = argc; - os·Args.cap = argc; - - envp = env; - for(i=0; i<envc; i++) { - genvv[i] = gostringw(envp); - envp += findnullw(envp)+1; + 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; i<n; i++) { + s[i] = runtime·gostringw(p); + p += runtime·findnullw(p)+1; } - os·Envs.array = (byte*)genvv; - os·Envs.len = envc; - os·Envs.cap = envc; + os·Envs.array = (byte*)s; + os·Envs.len = n; + os·Envs.cap = n; + + runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env); } void -exit(int32 code) +runtime·exit(int32 code) { - stdcall(ExitProcess, 1, code); + runtime·stdcall(runtime·ExitProcess, 1, code); } int32 -write(int32 fd, void *buf, int32 n) +runtime·write(int32 fd, void *buf, int32 n) { void *handle; uint32 written; @@ -136,46 +90,28 @@ write(int32 fd, void *buf, int32 n) written = 0; switch(fd) { case 1: - handle = stdcall(GetStdHandle, 1, -11); + handle = runtime·stdcall(runtime·GetStdHandle, 1, -11); break; case 2: - handle = stdcall(GetStdHandle, 1, -12); + handle = runtime·stdcall(runtime·GetStdHandle, 1, -12); break; default: return -1; } - stdcall(WriteFile, 5, handle, buf, n, &written, 0); + runtime·stdcall(runtime·WriteFile, 5, handle, buf, n, &written, 0); return written; } -void* -get_symdat_addr(void) -{ - byte *mod, *p; - uint32 peh, add; - uint16 oph; - - mod = stdcall(GetModuleHandle, 1, 0); - peh = *(uint32*)(mod+0x3c); - p = mod+peh+4; - oph = *(uint16*)(p+0x10); - p += 0x14+oph; - while(strcmp(p, (byte*)".symdat")) - p += 40; - add = *(uint32*)(p+0x0c); - return mod+add; -} - // Thread-safe allocation of an event. static void initevent(void **pevent) { void *event; - event = stdcall(CreateEvent, 4, 0, 0, 0, 0); - if(!casp(pevent, 0, event)) { + event = runtime·stdcall(runtime·CreateEvent, 4, 0, 0, 0, 0); + if(!runtime·casp(pevent, 0, event)) { // Someone else filled it in. Use theirs. - stdcall(CloseHandle, 1, event); + runtime·stdcall(runtime·CloseHandle, 1, event); } } @@ -186,106 +122,96 @@ eventlock(Lock *l) if(l->event == 0) initevent(&l->event); - if(xadd(&l->key, 1) > 1) // someone else has it; wait - stdcall(WaitForSingleObject, 2, l->event, -1); + 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(xadd(&l->key, -1) > 0) // someone else is waiting - stdcall(SetEvent, 1, l->event); + if(runtime·xadd(&l->key, -1) > 0) // someone else is waiting + runtime·stdcall(runtime·SetEvent, 1, l->event); } void -lock(Lock *l) +runtime·lock(Lock *l) { if(m->locks < 0) - throw("lock count"); + runtime·throw("lock count"); m->locks++; eventlock(l); } void -unlock(Lock *l) +runtime·unlock(Lock *l) { m->locks--; if(m->locks < 0) - throw("lock count"); + runtime·throw("lock count"); eventunlock(l); } void -destroylock(Lock *l) +runtime·destroylock(Lock *l) { if(l->event != 0) - stdcall(CloseHandle, 1, l->event); + runtime·stdcall(runtime·CloseHandle, 1, l->event); } void -noteclear(Note *n) +runtime·noteclear(Note *n) { eventlock(&n->lock); } void -notewakeup(Note *n) +runtime·notewakeup(Note *n) { eventunlock(&n->lock); } void -notesleep(Note *n) +runtime·notesleep(Note *n) { eventlock(&n->lock); eventunlock(&n->lock); // Let other sleepers find out too. } void -newosproc(M *m, G *g, void *stk, void (*fn)(void)) +runtime·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, ¶m, 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 + + runtime·stdcall(runtime·CreateThread, 6, 0, 0, runtime·tstart_stdcall, m, 0, 0); } // Called to initialize a new m (including the bootstrap m). void -minit(void) +runtime·minit(void) { } // Calling stdcall on os stack. #pragma textflag 7 void * -stdcall(void *fn, int32 count, ...) +runtime·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 runtime·stdcall_raw(fn, count, (uintptr*)(&count + 1)); } void -call_syscall(void *args) -{ - StdcallParams *p = (StdcallParams*)args; - 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->err = (uintptr)stdcall_raw(GetLastError); - return; +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(); } |