diff --git a/src/pkg/runtime/mem_windows.c b/src/pkg/runtime/mem_windows.c index 77ec6e9262..5eb43b2a93 100644 --- a/src/pkg/runtime/mem_windows.c +++ b/src/pkg/runtime/mem_windows.c @@ -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"); } diff --git a/src/pkg/runtime/netpoll_windows.c b/src/pkg/runtime/netpoll_windows.c index 4528292125..64da41ad90 100644 --- a/src/pkg/runtime/netpoll_windows.c +++ b/src/pkg/runtime/netpoll_windows.c @@ -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) diff --git a/src/pkg/runtime/os_windows.c b/src/pkg/runtime/os_windows.c index aadc30a076..43026d6457 100644 --- a/src/pkg/runtime/os_windows.c +++ b/src/pkg/runtime/os_windows.c @@ -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); } diff --git a/src/pkg/runtime/os_windows.go b/src/pkg/runtime/os_windows.go index 188ca3219e..a1b9594318 100644 --- a/src/pkg/runtime/os_windows.go +++ b/src/pkg/runtime/os_windows.go @@ -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) diff --git a/src/pkg/runtime/os_windows.h b/src/pkg/runtime/os_windows.h index b64fa88736..e1e3cb0e23 100644 --- a/src/pkg/runtime/os_windows.h +++ b/src/pkg/runtime/os_windows.h @@ -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);