summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/windows/thread.c
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-01-17 12:40:45 +0100
committerOndřej Surý <ondrej@sury.org>2011-01-17 12:40:45 +0100
commit3e45412327a2654a77944249962b3652e6142299 (patch)
treebc3bf69452afa055423cbe0c5cfa8ca357df6ccf /src/pkg/runtime/windows/thread.c
parentc533680039762cacbc37db8dc7eed074c3e497be (diff)
downloadgolang-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.c268
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, &param, 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();
}