Commit 73f5010d authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

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
parent 9f0b749b
......@@ -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)
......
This diff is collapsed.
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment