blob: 9a6f121aba9d9fe78d263378976aeb0518e77114 [file] [log] [blame]
// 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 "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
void *runtime·CloseHandle;
void *runtime·ExitProcess;
void *runtime·GetStdHandle;
void *runtime·SetEvent;
void *runtime·WriteFile;
void *runtime·LoadLibraryEx;
void *runtime·GetProcAddress;
void *runtime·GetLastError;
void *runtime·SetLastError;
#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
#pragma dynimport runtime·CreateThread CreateThread "kernel32.dll"
#pragma dynimport runtime·GetModuleHandle GetModuleHandleA "kernel32.dll"
#pragma dynimport runtime·WaitForSingleObject WaitForSingleObject "kernel32.dll"
void *runtime·CreateEvent;
void *runtime·CreateThread;
void *runtime·GetModuleHandle;
void *runtime·WaitForSingleObject;
void
runtime·osinit(void)
{
}
#pragma dynimport runtime·GetCommandLine GetCommandLineW "kernel32.dll"
#pragma dynimport runtime·CommandLineToArgv CommandLineToArgvW "shell32.dll"
#pragma dynimport runtime·GetEnvironmentStrings GetEnvironmentStringsW "kernel32.dll"
#pragma dynimport runtime·FreeEnvironmentStrings FreeEnvironmentStringsW "kernel32.dll"
#pragma dynimport runtime·LocalFree LocalFree "kernel32.dll"
void *runtime·GetCommandLine;
void *runtime·CommandLineToArgv;
void *runtime·GetEnvironmentStrings;
void *runtime·FreeEnvironmentStrings;
void *runtime·LocalFree;
void
runtime·windows_goargs(void)
{
extern Slice os·Args;
extern Slice os·Envs;
uint16 *cmd, *env, **argv;
String *gargv;
String *genvv;
int32 i, argc, envc;
uint16 *envp;
cmd = runtime·stdcall(runtime·GetCommandLine, 0);
env = runtime·stdcall(runtime·GetEnvironmentStrings, 0);
argv = runtime·stdcall(runtime·CommandLineToArgv, 2, cmd, &argc);
envc = 0;
for(envp=env; *envp; envc++)
envp += runtime·findnullw(envp)+1;
gargv = runtime·malloc(argc*sizeof gargv[0]);
genvv = runtime·malloc(envc*sizeof genvv[0]);
for(i=0; i<argc; i++)
gargv[i] = runtime·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] = runtime·gostringw(envp);
envp += runtime·findnullw(envp)+1;
}
os·Envs.array = (byte*)genvv;
os·Envs.len = envc;
os·Envs.cap = envc;
runtime·stdcall(runtime·LocalFree, 1, argv);
runtime·stdcall(runtime·FreeEnvironmentStrings, 1, env);
}
void
runtime·exit(int32 code)
{
runtime·stdcall(runtime·ExitProcess, 1, code);
}
int32
runtime·write(int32 fd, void *buf, int32 n)
{
void *handle;
uint32 written;
written = 0;
switch(fd) {
case 1:
handle = runtime·stdcall(runtime·GetStdHandle, 1, -11);
break;
case 2:
handle = runtime·stdcall(runtime·GetStdHandle, 1, -12);
break;
default:
return -1;
}
runtime·stdcall(runtime·WriteFile, 5, handle, buf, n, &written, 0);
return written;
}
// Thread-safe allocation of an event.
static void
initevent(void **pevent)
{
void *event;
event = runtime·stdcall(runtime·CreateEvent, 4, 0, 0, 0, 0);
if(!runtime·casp(pevent, 0, event)) {
// Someone else filled it in. Use theirs.
runtime·stdcall(runtime·CloseHandle, 1, event);
}
}
static void
eventlock(Lock *l)
{
// Allocate event if needed.
if(l->event == 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();
}