diff options
Diffstat (limited to 'src/pkg/runtime/windows/thread.c')
-rw-r--r-- | src/pkg/runtime/windows/thread.c | 137 |
1 files changed, 16 insertions, 121 deletions
diff --git a/src/pkg/runtime/windows/thread.c b/src/pkg/runtime/windows/thread.c index e08d1b6f0..b76eaac59 100644 --- a/src/pkg/runtime/windows/thread.c +++ b/src/pkg/runtime/windows/thread.c @@ -6,6 +6,7 @@ #include "type.h" #include "defs.h" #include "os.h" +#include "cgocall.h" #pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll" #pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll" @@ -221,34 +222,27 @@ runtime·gettime(int64 *sec, int32 *usec) void * runtime·stdcall(void *fn, int32 count, ...) { - return runtime·stdcall_raw(fn, count, (uintptr*)&count + 1); + WinCall c; + + c.fn = fn; + c.n = count; + c.args = (uintptr*)&count + 1; + runtime·asmcgocall(runtime·asmstdcall, &c); + return (void*)c.r; } uintptr runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err) { - G *oldlock; - uintptr ret; - - /* - * 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(); - runtime·setlasterror(0); - ret = (uintptr)runtime·stdcall_raw(fn, nargs, args); - if(err) - *err = runtime·getlasterror(); - runtime·exitsyscall(); - - m->lockedg = oldlock; - if(oldlock == nil) - g->lockedm = nil; + WinCall c; - return ret; + c.fn = fn; + c.n = nargs; + c.args = args; + runtime·cgocall(runtime·asmstdcall, &c); + if(err) + *err = c.err; + return c.r; } uint32 @@ -326,105 +320,6 @@ runtime·ctrlhandler1(uint32 type) return 0; } -// Will keep all callbacks in a linked list, so they don't get garbage collected. -typedef struct Callback Callback; -struct Callback { - Callback* link; - void* gobody; - byte asmbody; -}; - -typedef struct Callbacks Callbacks; -struct Callbacks { - Lock; - Callback* link; - int32 n; -}; - -static Callbacks cbs; - -// Call back from windows dll into go. -byte * -runtime·compilecallback(Eface fn, bool cleanstack) -{ - FuncType *ft; - Type *t; - int32 argsize, i, n; - byte *p; - Callback *c; - - if(fn.type == nil || fn.type->kind != KindFunc) - runtime·panicstring("compilecallback: not a function"); - ft = (FuncType*)fn.type; - if(ft->out.len != 1) - runtime·panicstring("compilecallback: function must have one output parameter"); - if(((Type**)ft->out.array)[0]->size != sizeof(uintptr)) - runtime·panicstring("compilecallback: output parameter size is wrong"); - argsize = 0; - for(i=0; i<ft->in.len; i++) { - t = ((Type**)ft->in.array)[i]; - if(t->size != sizeof(uintptr)) - runtime·panicstring("compilecallback: input parameter size is wrong"); - argsize += t->size; - } - - // compute size of new fn. - // must match code laid out below. - n = 1+4; // MOVL fn, AX - n += 1+4; // MOVL argsize, DX - n += 1+4; // MOVL callbackasm, CX - n += 2; // CALL CX - n += 1; // RET - if(cleanstack) - n += 2; // ... argsize - - runtime·lock(&cbs); - for(c = cbs.link; c != nil; c = c->link) { - if(c->gobody == fn.data) { - runtime·unlock(&cbs); - return &c->asmbody; - } - } - if(cbs.n >= 2000) - runtime·throw("too many callback functions"); - c = runtime·mal(sizeof *c + n); - c->gobody = fn.data; - c->link = cbs.link; - cbs.link = c; - cbs.n++; - runtime·unlock(&cbs); - - p = &c->asmbody; - - // MOVL fn, AX - *p++ = 0xb8; - *(uint32*)p = (uint32)fn.data; - p += 4; - - // MOVL argsize, DX - *p++ = 0xba; - *(uint32*)p = argsize; - p += 4; - - // MOVL callbackasm, CX - *p++ = 0xb9; - *(uint32*)p = (uint32)runtime·callbackasm; - p += 4; - - // CALL CX - *p++ = 0xff; - *p++ = 0xd1; - - // RET argsize? - if(cleanstack) { - *p++ = 0xc2; - *(uint16*)p = argsize; - } else - *p = 0xc3; - - return &c->asmbody; -} - void os·sigpipe(void) { |