github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/callback_windows_386.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "runtime.h" 6 #include "type.h" 7 #include "typekind.h" 8 #include "defs_GOOS_GOARCH.h" 9 #include "os_GOOS.h" 10 11 // Will keep all callbacks in a linked list, so they don't get garbage collected. 12 typedef struct Callback Callback; 13 struct Callback { 14 Callback* link; 15 void* gobody; 16 byte asmbody; 17 }; 18 19 typedef struct Callbacks Callbacks; 20 struct Callbacks { 21 Lock; 22 Callback* link; 23 int32 n; 24 }; 25 26 static Callbacks cbs; 27 28 // Call back from windows dll into go. 29 byte * 30 runtime·compilecallback(Eface fn, bool cleanstack) 31 { 32 FuncType *ft; 33 Type *t; 34 int32 argsize, i, n; 35 byte *p; 36 Callback *c; 37 38 if(fn.type == nil || fn.type->kind != KindFunc) 39 runtime·panicstring("compilecallback: not a function"); 40 ft = (FuncType*)fn.type; 41 if(ft->out.len != 1) 42 runtime·panicstring("compilecallback: function must have one output parameter"); 43 if(((Type**)ft->out.array)[0]->size != sizeof(uintptr)) 44 runtime·panicstring("compilecallback: output parameter size is wrong"); 45 argsize = 0; 46 for(i=0; i<ft->in.len; i++) { 47 t = ((Type**)ft->in.array)[i]; 48 if(t->size > sizeof(uintptr)) 49 runtime·panicstring("compilecallback: input parameter size is wrong"); 50 argsize += sizeof(uintptr); 51 } 52 53 // compute size of new fn. 54 // must match code laid out below. 55 n = 1+4; // MOVL fn, AX 56 n += 1+4; // MOVL argsize, DX 57 n += 1+4; // MOVL callbackasm, CX 58 n += 2; // CALL CX 59 n += 1; // RET 60 if(cleanstack && argsize!=0) 61 n += 2; // ... argsize 62 63 runtime·lock(&cbs); 64 for(c = cbs.link; c != nil; c = c->link) { 65 if(c->gobody == fn.data) { 66 runtime·unlock(&cbs); 67 return &c->asmbody; 68 } 69 } 70 if(cbs.n >= 2000) 71 runtime·throw("too many callback functions"); 72 c = runtime·mal(sizeof *c + n); 73 c->gobody = fn.data; 74 c->link = cbs.link; 75 cbs.link = c; 76 cbs.n++; 77 runtime·unlock(&cbs); 78 79 p = &c->asmbody; 80 81 // MOVL fn, AX 82 *p++ = 0xb8; 83 *(uint32*)p = (uint32)(fn.data); 84 p += 4; 85 86 // MOVL argsize, DX 87 *p++ = 0xba; 88 *(uint32*)p = argsize; 89 p += 4; 90 91 // MOVL callbackasm, CX 92 *p++ = 0xb9; 93 *(uint32*)p = (uint32)runtime·callbackasm; 94 p += 4; 95 96 // CALL CX 97 *p++ = 0xff; 98 *p++ = 0xd1; 99 100 // RET argsize? 101 if(cleanstack && argsize!=0) { 102 *p++ = 0xc2; 103 *(uint16*)p = argsize; 104 } else 105 *p = 0xc3; 106 107 return &c->asmbody; 108 }