Index: src/pkg/runtime/windows/thread.c |
=================================================================== |
--- a/src/pkg/runtime/windows/thread.c |
+++ b/src/pkg/runtime/windows/thread.c |
@@ -168,8 +168,16 @@ |
void |
runtime·syscall(StdcallParams *p) |
{ |
+ G *oldlock; |
uintptr a; |
+ /* |
+ * Lock g to m to ensure we stay on the same stack if we do a callback. |
+ */ |
+ oldlock = m->lockedg; |
+ m->lockedg = g; |
+ g->lockedm = m; |
+ |
runtime·entersyscall(); |
// TODO(brainman): Move calls to SetLastError and GetLastError |
// to stdcall_raw to speed up syscall. |
@@ -178,4 +186,32 @@ |
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(); |
+ |
+ m->lockedg = oldlock; |
+ if(oldlock == nil) |
+ g->lockedm = nil; |
} |
+ |
+// Call back from windows dll into go. |
+void |
+runtime·setcallback(byte *code, void *fn, uint32 argsize) |
+{ |
+ byte *p = code; |
+ |
+ // PUSH argsize |
+ *p++ = 0x68; |
+ *(uint32*)p = argsize; |
+ p += 4; |
+ // PUSH fn |
+ *p++ = 0x68; |
+ *(uint32*)p = (uint32)fn; |
+ p += 4; |
+ // MOV callbackasm, AX |
+ void* (*x)(void) = runtime·callbackasm; |
+ *p++ = 0xb8; |
+ *(uint32*)p = (uint32)x; |
+ p += 4; |
+ // CALL AX |
+ *p++ = 0xff; |
+ *p++ = 0xd0; |
+} |