github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/callback_windows.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  #include "zasm_GOOS_GOARCH.h"
    11  
    12  typedef	struct	Callbacks	Callbacks;
    13  struct	Callbacks {
    14  	Lock;
    15  	WinCallbackContext*	ctxt[cb_max];
    16  	int32			n;
    17  };
    18  
    19  static	Callbacks	cbs;
    20  
    21  WinCallbackContext** runtime·cbctxts; // to simplify access to cbs.ctxt in sys_windows_*.s
    22  
    23  // Call back from windows dll into go.
    24  byte *
    25  runtime·compilecallback(Eface fn, bool cleanstack)
    26  {
    27  	FuncType *ft;
    28  	Type *t;
    29  	int32 argsize, i, n;
    30  	WinCallbackContext *c;
    31  
    32  	if(fn.type == nil || fn.type->kind != KindFunc)
    33  		runtime·panicstring("compilecallback: not a function");
    34  	ft = (FuncType*)fn.type;
    35  	if(ft->out.len != 1)
    36  		runtime·panicstring("compilecallback: function must have one output parameter");
    37  	if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
    38  		runtime·panicstring("compilecallback: output parameter size is wrong");
    39  	argsize = 0;
    40  	for(i=0; i<ft->in.len; i++) {
    41  		t = ((Type**)ft->in.array)[i];
    42  		if(t->size > sizeof(uintptr))
    43  			runtime·panicstring("compilecallback: input parameter size is wrong");
    44  		argsize += sizeof(uintptr);
    45  	}
    46  
    47  	runtime·lock(&cbs);
    48  	if(runtime·cbctxts == nil)
    49  		runtime·cbctxts = &(cbs.ctxt[0]);
    50  	n = cbs.n;
    51  	for(i=0; i<n; i++) {
    52  		if(cbs.ctxt[i]->gobody == fn.data) {
    53  			runtime·unlock(&cbs);
    54  			// runtime·callbackasm is just a series of CALL instructions
    55  			// (each is 5 bytes long), and we want callback to arrive at
    56  			// correspondent call instruction instead of start of
    57  			// runtime·callbackasm.
    58  			return (byte*)runtime·callbackasm + i * 5;
    59  		}
    60  	}
    61  	if(n >= cb_max)
    62  		runtime·throw("too many callback functions");
    63  	c = runtime·mal(sizeof *c);
    64  	c->gobody = fn.data;
    65  	c->argsize = argsize;
    66  	if(cleanstack && argsize!=0)
    67  		c->restorestack = argsize;
    68  	else
    69  		c->restorestack = 0;
    70  	cbs.ctxt[n] = c;
    71  	cbs.n++;
    72  	runtime·unlock(&cbs);
    73  
    74  	// as before
    75  	return (byte*)runtime·callbackasm + n * 5;
    76  }