mirror of
https://github.com/golang/go
synced 2024-11-19 21:04:43 -07:00
runtime: allow to call stdcall from Go on windows
I've started with just one function with 8 arguments, but stdcall is called from nosplit functions and 8 args overflow nosplit area. LGTM=aram, alex.brainman R=golang-codereviews, aram, alex.brainman, dave CC=golang-codereviews, iant, khr, rsc https://golang.org/cl/135090043
This commit is contained in:
parent
9f0b749ba5
commit
73f5010dc6
@ -29,7 +29,7 @@ void*
|
||||
runtime·SysAlloc(uintptr n, uint64 *stat)
|
||||
{
|
||||
runtime·xadd64(stat, n);
|
||||
return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_READWRITE);
|
||||
return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -38,7 +38,7 @@ runtime·SysUnused(void *v, uintptr n)
|
||||
void *r;
|
||||
uintptr small;
|
||||
|
||||
r = runtime·stdcall(runtime·VirtualFree, 3, v, n, (uintptr)MEM_DECOMMIT);
|
||||
r = runtime·stdcall3(runtime·VirtualFree, (uintptr)v, n, MEM_DECOMMIT);
|
||||
if(r != nil)
|
||||
return;
|
||||
|
||||
@ -53,7 +53,7 @@ runtime·SysUnused(void *v, uintptr n)
|
||||
// in the worst case, but that's fast enough.
|
||||
while(n > 0) {
|
||||
small = n;
|
||||
while(small >= 4096 && runtime·stdcall(runtime·VirtualFree, 3, v, small, (uintptr)MEM_DECOMMIT) == nil)
|
||||
while(small >= 4096 && runtime·stdcall3(runtime·VirtualFree, (uintptr)v, small, MEM_DECOMMIT) == nil)
|
||||
small = (small / 2) & ~(4096-1);
|
||||
if(small < 4096)
|
||||
runtime·throw("runtime: failed to decommit pages");
|
||||
@ -67,7 +67,7 @@ runtime·SysUsed(void *v, uintptr n)
|
||||
{
|
||||
void *r;
|
||||
|
||||
r = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE);
|
||||
r = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
|
||||
if(r != v)
|
||||
runtime·throw("runtime: failed to commit pages");
|
||||
}
|
||||
@ -78,7 +78,7 @@ runtime·SysFree(void *v, uintptr n, uint64 *stat)
|
||||
uintptr r;
|
||||
|
||||
runtime·xadd64(stat, -(uint64)n);
|
||||
r = (uintptr)runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE);
|
||||
r = (uintptr)runtime·stdcall3(runtime·VirtualFree, (uintptr)v, 0, MEM_RELEASE);
|
||||
if(r == 0)
|
||||
runtime·throw("runtime: failed to release pages");
|
||||
}
|
||||
@ -96,12 +96,12 @@ runtime·SysReserve(void *v, uintptr n, bool *reserved)
|
||||
*reserved = true;
|
||||
// v is just a hint.
|
||||
// First try at v.
|
||||
v = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_READWRITE);
|
||||
v = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_RESERVE, PAGE_READWRITE);
|
||||
if(v != nil)
|
||||
return v;
|
||||
|
||||
// Next let the kernel choose the address.
|
||||
return runtime·stdcall(runtime·VirtualAlloc, 4, nil, n, (uintptr)MEM_RESERVE, (uintptr)PAGE_READWRITE);
|
||||
return runtime·stdcall4(runtime·VirtualAlloc, 0, n, MEM_RESERVE, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void
|
||||
@ -112,7 +112,7 @@ runtime·SysMap(void *v, uintptr n, bool reserved, uint64 *stat)
|
||||
USED(reserved);
|
||||
|
||||
runtime·xadd64(stat, n);
|
||||
p = runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)MEM_COMMIT, (uintptr)PAGE_READWRITE);
|
||||
p = runtime·stdcall4(runtime·VirtualAlloc, (uintptr)v, n, MEM_COMMIT, PAGE_READWRITE);
|
||||
if(p != v)
|
||||
runtime·throw("runtime: cannot map pages in arena address space");
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ static uintptr iocphandle = INVALID_HANDLE_VALUE; // completion port io handle
|
||||
void
|
||||
runtime·netpollinit(void)
|
||||
{
|
||||
iocphandle = (uintptr)runtime·stdcall(runtime·CreateIoCompletionPort, 4, INVALID_HANDLE_VALUE, (uintptr)0, (uintptr)0, (uintptr)DWORD_MAX);
|
||||
iocphandle = (uintptr)runtime·stdcall4(runtime·CreateIoCompletionPort, INVALID_HANDLE_VALUE, 0, 0, DWORD_MAX);
|
||||
if(iocphandle == 0) {
|
||||
runtime·printf("netpoll: failed to create iocp handle (errno=%d)\n", runtime·getlasterror());
|
||||
runtime·throw("netpoll: failed to create iocp handle");
|
||||
@ -59,7 +59,7 @@ int32
|
||||
runtime·netpollopen(uintptr fd, PollDesc *pd)
|
||||
{
|
||||
USED(pd);
|
||||
if(runtime·stdcall(runtime·CreateIoCompletionPort, 4, fd, iocphandle, (uintptr)0, (uintptr)0) == 0)
|
||||
if(runtime·stdcall4(runtime·CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0)
|
||||
return -runtime·getlasterror();
|
||||
return 0;
|
||||
}
|
||||
@ -103,7 +103,7 @@ retry:
|
||||
n = 8;
|
||||
if(block)
|
||||
g->m->blocked = true;
|
||||
if(runtime·stdcall(runtime·GetQueuedCompletionStatusEx, 6, iocphandle, entries, (uintptr)n, &n, (uintptr)wait, (uintptr)0) == 0) {
|
||||
if(runtime·stdcall6(runtime·GetQueuedCompletionStatusEx, iocphandle, (uintptr)entries, n, (uintptr)&n, wait, 0) == 0) {
|
||||
g->m->blocked = false;
|
||||
errno = runtime·getlasterror();
|
||||
if(!block && errno == WAIT_TIMEOUT)
|
||||
@ -116,7 +116,7 @@ retry:
|
||||
op = entries[i].op;
|
||||
errno = 0;
|
||||
qty = 0;
|
||||
if(runtime·stdcall(runtime·WSAGetOverlappedResult, 5, runtime·netpollfd(op->pd), op, &qty, (uintptr)0, (uintptr)&flags) == 0)
|
||||
if(runtime·stdcall5(runtime·WSAGetOverlappedResult, runtime·netpollfd(op->pd), (uintptr)op, (uintptr)&qty, 0, (uintptr)&flags) == 0)
|
||||
errno = runtime·getlasterror();
|
||||
handlecompletion(&gp, op, errno, qty);
|
||||
}
|
||||
@ -126,7 +126,7 @@ retry:
|
||||
qty = 0;
|
||||
if(block)
|
||||
g->m->blocked = true;
|
||||
if(runtime·stdcall(runtime·GetQueuedCompletionStatus, 5, iocphandle, &qty, &key, &op, (uintptr)wait) == 0) {
|
||||
if(runtime·stdcall5(runtime·GetQueuedCompletionStatus, iocphandle, (uintptr)&qty, (uintptr)&key, (uintptr)&op, wait) == 0) {
|
||||
g->m->blocked = false;
|
||||
errno = runtime·getlasterror();
|
||||
if(!block && errno == WAIT_TIMEOUT)
|
||||
|
@ -81,7 +81,7 @@ getproccount(void)
|
||||
{
|
||||
SystemInfo info;
|
||||
|
||||
runtime·stdcall(runtime·GetSystemInfo, 1, &info);
|
||||
runtime·stdcall1(runtime·GetSystemInfo, (uintptr)&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
@ -92,20 +92,20 @@ runtime·osinit(void)
|
||||
|
||||
runtime·externalthreadhandlerp = (uintptr)runtime·externalthreadhandler;
|
||||
|
||||
runtime·stdcall(runtime·AddVectoredExceptionHandler, 2, (uintptr)1, (uintptr)runtime·sigtramp);
|
||||
runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
|
||||
runtime·stdcall(runtime·timeBeginPeriod, 1, (uintptr)1);
|
||||
runtime·stdcall2(runtime·AddVectoredExceptionHandler, 1, (uintptr)runtime·sigtramp);
|
||||
runtime·stdcall2(runtime·SetConsoleCtrlHandler, (uintptr)runtime·ctrlhandler, 1);
|
||||
runtime·stdcall1(runtime·timeBeginPeriod, 1);
|
||||
runtime·ncpu = getproccount();
|
||||
|
||||
// Windows dynamic priority boosting assumes that a process has different types
|
||||
// of dedicated threads -- GUI, IO, computational, etc. Go processes use
|
||||
// equivalent threads that all do a mix of GUI, IO, computations, etc.
|
||||
// In such context dynamic priority boosting does nothing but harm, so we turn it off.
|
||||
runtime·stdcall(runtime·SetProcessPriorityBoost, 2, (uintptr)-1, (uintptr)1);
|
||||
runtime·stdcall2(runtime·SetProcessPriorityBoost, -1, 1);
|
||||
|
||||
kernel32 = runtime·stdcall(runtime·LoadLibraryA, 1, "kernel32.dll");
|
||||
kernel32 = runtime·stdcall1(runtime·LoadLibraryA, (uintptr)"kernel32.dll");
|
||||
if(kernel32 != nil) {
|
||||
runtime·GetQueuedCompletionStatusEx = runtime·stdcall(runtime·GetProcAddress, 2, kernel32, "GetQueuedCompletionStatusEx");
|
||||
runtime·GetQueuedCompletionStatusEx = runtime·stdcall2(runtime·GetProcAddress, (uintptr)kernel32, (uintptr)"GetQueuedCompletionStatusEx");
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,15 +115,15 @@ runtime·get_random_data(byte **rnd, int32 *rnd_len)
|
||||
uintptr handle;
|
||||
*rnd = nil;
|
||||
*rnd_len = 0;
|
||||
if(runtime·stdcall(runtime·CryptAcquireContextW, 5, &handle, nil, nil,
|
||||
(uintptr)1 /* PROV_RSA_FULL */,
|
||||
(uintptr)0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
|
||||
if(runtime·stdcall5(runtime·CryptAcquireContextW, (uintptr)&handle, (uintptr)nil, (uintptr)nil,
|
||||
1 /* PROV_RSA_FULL */,
|
||||
0xf0000000U /* CRYPT_VERIFYCONTEXT */) != 0) {
|
||||
static byte random_data[HashRandomBytes];
|
||||
if(runtime·stdcall(runtime·CryptGenRandom, 3, handle, (uintptr)HashRandomBytes, random_data)) {
|
||||
if(runtime·stdcall3(runtime·CryptGenRandom, handle, HashRandomBytes, (uintptr)&random_data[0])) {
|
||||
*rnd = random_data;
|
||||
*rnd_len = HashRandomBytes;
|
||||
}
|
||||
runtime·stdcall(runtime·CryptReleaseContext, 2, handle, (uintptr)0);
|
||||
runtime·stdcall2(runtime·CryptReleaseContext, handle, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ runtime·goenvs(void)
|
||||
int32 i, n;
|
||||
uint16 *p;
|
||||
|
||||
env = runtime·stdcall(runtime·GetEnvironmentStringsW, 0);
|
||||
env = runtime·stdcall0(runtime·GetEnvironmentStringsW);
|
||||
|
||||
n = 0;
|
||||
for(p=env; *p; n++)
|
||||
@ -154,13 +154,13 @@ runtime·goenvs(void)
|
||||
syscall·envs.len = n;
|
||||
syscall·envs.cap = n;
|
||||
|
||||
runtime·stdcall(runtime·FreeEnvironmentStringsW, 1, env);
|
||||
runtime·stdcall1(runtime·FreeEnvironmentStringsW, (uintptr)env);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·exit(int32 code)
|
||||
{
|
||||
runtime·stdcall(runtime·ExitProcess, 1, (uintptr)code);
|
||||
runtime·stdcall1(runtime·ExitProcess, code);
|
||||
}
|
||||
|
||||
int32
|
||||
@ -172,17 +172,17 @@ runtime·write(uintptr fd, void *buf, int32 n)
|
||||
written = 0;
|
||||
switch(fd) {
|
||||
case 1:
|
||||
handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-11);
|
||||
handle = runtime·stdcall1(runtime·GetStdHandle, -11);
|
||||
break;
|
||||
case 2:
|
||||
handle = runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12);
|
||||
handle = runtime·stdcall1(runtime·GetStdHandle, -12);
|
||||
break;
|
||||
default:
|
||||
// assume fd is real windows handle.
|
||||
handle = (void*)fd;
|
||||
break;
|
||||
}
|
||||
runtime·stdcall(runtime·WriteFile, 5, handle, buf, (uintptr)n, &written, (uintptr)0);
|
||||
runtime·stdcall5(runtime·WriteFile, (uintptr)handle, (uintptr)buf, n, (uintptr)&written, 0);
|
||||
return written;
|
||||
}
|
||||
|
||||
@ -200,7 +200,7 @@ runtime·semasleep(int64 ns)
|
||||
if(ns == 0)
|
||||
ns = 1;
|
||||
}
|
||||
if(runtime·stdcall(runtime·WaitForSingleObject, 2, g->m->waitsema, (uintptr)ns) != 0)
|
||||
if(runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)g->m->waitsema, ns) != 0)
|
||||
return -1; // timeout
|
||||
return 0;
|
||||
}
|
||||
@ -208,13 +208,13 @@ runtime·semasleep(int64 ns)
|
||||
void
|
||||
runtime·semawakeup(M *mp)
|
||||
{
|
||||
runtime·stdcall(runtime·SetEvent, 1, mp->waitsema);
|
||||
runtime·stdcall1(runtime·SetEvent, mp->waitsema);
|
||||
}
|
||||
|
||||
uintptr
|
||||
runtime·semacreate(void)
|
||||
{
|
||||
return (uintptr)runtime·stdcall(runtime·CreateEvent, 4, (uintptr)0, (uintptr)0, (uintptr)0, (uintptr)0);
|
||||
return (uintptr)runtime·stdcall4(runtime·CreateEvent, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define STACK_SIZE_PARAM_IS_A_RESERVATION ((uintptr)0x00010000)
|
||||
@ -226,9 +226,9 @@ runtime·newosproc(M *mp, void *stk)
|
||||
|
||||
USED(stk);
|
||||
|
||||
thandle = runtime·stdcall(runtime·CreateThread, 6,
|
||||
nil, (uintptr)0x20000, runtime·tstart_stdcall, mp,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, nil);
|
||||
thandle = runtime·stdcall6(runtime·CreateThread,
|
||||
(uintptr)nil, 0x20000, (uintptr)runtime·tstart_stdcall, (uintptr)mp,
|
||||
STACK_SIZE_PARAM_IS_A_RESERVATION, (uintptr)nil);
|
||||
if(thandle == nil) {
|
||||
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), runtime·getlasterror());
|
||||
runtime·throw("runtime.newosproc");
|
||||
@ -251,9 +251,7 @@ runtime·minit(void)
|
||||
void *thandle;
|
||||
|
||||
// -1 = current process, -2 = current thread
|
||||
runtime·stdcall(runtime·DuplicateHandle, 7,
|
||||
(uintptr)-1, (uintptr)-2, (uintptr)-1, &thandle,
|
||||
(uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS);
|
||||
runtime·stdcall7(runtime·DuplicateHandle, -1, -2, -1, (uintptr)&thandle, 0, 0, DUPLICATE_SAME_ACCESS);
|
||||
runtime·atomicstorep(&g->m->thread, thandle);
|
||||
}
|
||||
|
||||
@ -318,12 +316,10 @@ time·now(int64 sec, int32 usec)
|
||||
|
||||
// Calling stdcall on os stack.
|
||||
#pragma textflag NOSPLIT
|
||||
void *
|
||||
runtime·stdcall(void *fn, int32 count, ...)
|
||||
static void*
|
||||
stdcall(void *fn)
|
||||
{
|
||||
g->m->libcall.fn = fn;
|
||||
g->m->libcall.n = count;
|
||||
g->m->libcall.args = (uintptr*)&count + 1;
|
||||
if(g->m->profilehz != 0) {
|
||||
// leave pc/sp for cpu profiler
|
||||
g->m->libcallg = g;
|
||||
@ -337,6 +333,85 @@ runtime·stdcall(void *fn, int32 count, ...)
|
||||
return (void*)g->m->libcall.r1;
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall0(void *fn)
|
||||
{
|
||||
g->m->libcall.n = 0;
|
||||
g->m->libcall.args = &fn; // it's unused but must be non-nil, otherwise crashes
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall1(void *fn, uintptr a0)
|
||||
{
|
||||
USED(a0);
|
||||
g->m->libcall.n = 1;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall2(void *fn, uintptr a0, uintptr a1)
|
||||
{
|
||||
USED(a0, a1);
|
||||
g->m->libcall.n = 2;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2)
|
||||
{
|
||||
USED(a0, a1, a2);
|
||||
g->m->libcall.n = 3;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3)
|
||||
{
|
||||
USED(a0, a1, a2, a3);
|
||||
g->m->libcall.n = 4;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4)
|
||||
{
|
||||
USED(a0, a1, a2, a3, a4);
|
||||
g->m->libcall.n = 5;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5)
|
||||
{
|
||||
USED(a0, a1, a2, a3, a4, a5);
|
||||
g->m->libcall.n = 6;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
void*
|
||||
runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6)
|
||||
{
|
||||
USED(a0, a1, a2, a3, a4, a5, a6);
|
||||
g->m->libcall.n = 7;
|
||||
g->m->libcall.args = &a0;
|
||||
return stdcall(fn);
|
||||
}
|
||||
|
||||
extern void runtime·usleep1(uint32);
|
||||
|
||||
#pragma textflag NOSPLIT
|
||||
@ -451,7 +526,7 @@ profilem(M *mp)
|
||||
// align Context to 16 bytes
|
||||
r = (Context*)((uintptr)(&rbuf[15]) & ~15);
|
||||
r->ContextFlags = CONTEXT_CONTROL;
|
||||
runtime·stdcall(runtime·GetThreadContext, 2, mp->thread, r);
|
||||
runtime·stdcall2(runtime·GetThreadContext, (uintptr)mp->thread, (uintptr)r);
|
||||
runtime·dosigprof(r, gp, mp);
|
||||
}
|
||||
|
||||
@ -461,11 +536,10 @@ runtime·profileloop1(void)
|
||||
M *mp, *allm;
|
||||
void *thread;
|
||||
|
||||
runtime·stdcall(runtime·SetThreadPriority, 2,
|
||||
(uintptr)-2, (uintptr)THREAD_PRIORITY_HIGHEST);
|
||||
runtime·stdcall2(runtime·SetThreadPriority, -2, THREAD_PRIORITY_HIGHEST);
|
||||
|
||||
for(;;) {
|
||||
runtime·stdcall(runtime·WaitForSingleObject, 2, profiletimer, (uintptr)-1);
|
||||
runtime·stdcall2(runtime·WaitForSingleObject, (uintptr)profiletimer, -1);
|
||||
allm = runtime·atomicloadp(&runtime·allm);
|
||||
for(mp = allm; mp != nil; mp = mp->alllink) {
|
||||
thread = runtime·atomicloadp(&mp->thread);
|
||||
@ -474,10 +548,10 @@ runtime·profileloop1(void)
|
||||
// idle timer thread, idle heap scavenger, etc.
|
||||
if(thread == nil || mp->profilehz == 0 || mp->blocked)
|
||||
continue;
|
||||
runtime·stdcall(runtime·SuspendThread, 1, thread);
|
||||
runtime·stdcall1(runtime·SuspendThread, (uintptr)thread);
|
||||
if(mp->profilehz != 0 && !mp->blocked)
|
||||
profilem(mp);
|
||||
runtime·stdcall(runtime·ResumeThread, 1, thread);
|
||||
runtime·stdcall1(runtime·ResumeThread, (uintptr)thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -492,11 +566,11 @@ runtime·resetcpuprofiler(int32 hz)
|
||||
|
||||
runtime·lock(&lock);
|
||||
if(profiletimer == nil) {
|
||||
timer = runtime·stdcall(runtime·CreateWaitableTimer, 3, nil, nil, nil);
|
||||
timer = runtime·stdcall3(runtime·CreateWaitableTimer, (uintptr)nil, (uintptr)nil, (uintptr)nil);
|
||||
runtime·atomicstorep(&profiletimer, timer);
|
||||
thread = runtime·stdcall(runtime·CreateThread, 6,
|
||||
nil, nil, runtime·profileloop, nil, nil, nil);
|
||||
runtime·stdcall(runtime·CloseHandle, 1, thread);
|
||||
thread = runtime·stdcall6(runtime·CreateThread,
|
||||
(uintptr)nil, (uintptr)nil, (uintptr)runtime·profileloop, (uintptr)nil, (uintptr)nil, (uintptr)nil);
|
||||
runtime·stdcall1(runtime·CloseHandle, (uintptr)thread);
|
||||
}
|
||||
runtime·unlock(&lock);
|
||||
|
||||
@ -508,8 +582,8 @@ runtime·resetcpuprofiler(int32 hz)
|
||||
ms = 1;
|
||||
due = ms * -10000;
|
||||
}
|
||||
runtime·stdcall(runtime·SetWaitableTimer, 6,
|
||||
profiletimer, &due, (uintptr)ms, nil, nil, nil);
|
||||
runtime·stdcall6(runtime·SetWaitableTimer,
|
||||
(uintptr)profiletimer, (uintptr)&due, ms, (uintptr)nil, (uintptr)nil, (uintptr)nil);
|
||||
runtime·atomicstore((uint32*)&g->m->profilehz, hz);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,17 @@ package runtime
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type stdFunction *byte
|
||||
|
||||
func stdcall0(fn stdFunction) uintptr
|
||||
func stdcall1(fn stdFunction, a0 uintptr) uintptr
|
||||
func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr
|
||||
func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr
|
||||
func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr
|
||||
func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr
|
||||
func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr
|
||||
func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr
|
||||
|
||||
func asmstdcall(fn unsafe.Pointer)
|
||||
func getlasterror() uint32
|
||||
func setlasterror(err uint32)
|
||||
|
@ -8,11 +8,15 @@ extern void *runtime·GetQueuedCompletionStatusEx;
|
||||
|
||||
// Call a Windows function with stdcall conventions,
|
||||
// and switch to os stack during the call.
|
||||
#pragma varargck countpos runtime·stdcall 2
|
||||
#pragma varargck type runtime·stdcall void*
|
||||
#pragma varargck type runtime·stdcall uintptr
|
||||
void runtime·asmstdcall(void *c);
|
||||
void *runtime·stdcall(void *fn, int32 count, ...);
|
||||
void *runtime·stdcall0(void *fn);
|
||||
void *runtime·stdcall1(void *fn, uintptr a0);
|
||||
void *runtime·stdcall2(void *fn, uintptr a0, uintptr a1);
|
||||
void *runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2);
|
||||
void *runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3);
|
||||
void *runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
|
||||
void *runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
|
||||
void *runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
|
||||
|
||||
uint32 runtime·getlasterror(void);
|
||||
void runtime·setlasterror(uint32 err);
|
||||
|
Loading…
Reference in New Issue
Block a user