github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/cgocall.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 "arch_GOARCH.h"
     7  #include "stack.h"
     8  #include "cgocall.h"
     9  #include "race.h"
    10  
    11  // Cgo call and callback support.
    12  //
    13  // To call into the C function f from Go, the cgo-generated code calls
    14  // runtime.cgocall(_cgo_Cfunc_f, frame), where _cgo_Cfunc_f is a
    15  // gcc-compiled function written by cgo.
    16  //
    17  // runtime.cgocall (below) locks g to m, calls entersyscall
    18  // so as not to block other goroutines or the garbage collector,
    19  // and then calls runtime.asmcgocall(_cgo_Cfunc_f, frame). 
    20  //
    21  // runtime.asmcgocall (in asm_$GOARCH.s) switches to the m->g0 stack
    22  // (assumed to be an operating system-allocated stack, so safe to run
    23  // gcc-compiled code on) and calls _cgo_Cfunc_f(frame).
    24  //
    25  // _cgo_Cfunc_f invokes the actual C function f with arguments
    26  // taken from the frame structure, records the results in the frame,
    27  // and returns to runtime.asmcgocall.
    28  //
    29  // After it regains control, runtime.asmcgocall switches back to the
    30  // original g (m->curg)'s stack and returns to runtime.cgocall.
    31  //
    32  // After it regains control, runtime.cgocall calls exitsyscall, which blocks
    33  // until this m can run Go code without violating the $GOMAXPROCS limit,
    34  // and then unlocks g from m.
    35  //
    36  // The above description skipped over the possibility of the gcc-compiled
    37  // function f calling back into Go.  If that happens, we continue down
    38  // the rabbit hole during the execution of f.
    39  //
    40  // To make it possible for gcc-compiled C code to call a Go function p.GoF,
    41  // cgo writes a gcc-compiled function named GoF (not p.GoF, since gcc doesn't
    42  // know about packages).  The gcc-compiled C function f calls GoF.
    43  //
    44  // GoF calls crosscall2(_cgoexp_GoF, frame, framesize).  Crosscall2
    45  // (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument
    46  // adapter from the gcc function call ABI to the 6c function call ABI.
    47  // It is called from gcc to call 6c functions.  In this case it calls
    48  // _cgoexp_GoF(frame, framesize), still running on m->g0's stack
    49  // and outside the $GOMAXPROCS limit.  Thus, this code cannot yet
    50  // call arbitrary Go code directly and must be careful not to allocate
    51  // memory or use up m->g0's stack.
    52  //
    53  // _cgoexp_GoF calls runtime.cgocallback(p.GoF, frame, framesize).
    54  // (The reason for having _cgoexp_GoF instead of writing a crosscall3
    55  // to make this call directly is that _cgoexp_GoF, because it is compiled
    56  // with 6c instead of gcc, can refer to dotted names like
    57  // runtime.cgocallback and p.GoF.)
    58  //
    59  // runtime.cgocallback (in asm_$GOARCH.s) switches from m->g0's
    60  // stack to the original g (m->curg)'s stack, on which it calls
    61  // runtime.cgocallbackg(p.GoF, frame, framesize).
    62  // As part of the stack switch, runtime.cgocallback saves the current
    63  // SP as m->g0->sched.sp, so that any use of m->g0's stack during the
    64  // execution of the callback will be done below the existing stack frames.
    65  // Before overwriting m->g0->sched.sp, it pushes the old value on the
    66  // m->g0 stack, so that it can be restored later.
    67  //
    68  // runtime.cgocallbackg (below) is now running on a real goroutine
    69  // stack (not an m->g0 stack).  First it calls runtime.exitsyscall, which will
    70  // block until the $GOMAXPROCS limit allows running this goroutine.
    71  // Once exitsyscall has returned, it is safe to do things like call the memory
    72  // allocator or invoke the Go callback function p.GoF.  runtime.cgocallbackg
    73  // first defers a function to unwind m->g0.sched.sp, so that if p.GoF
    74  // panics, m->g0.sched.sp will be restored to its old value: the m->g0 stack
    75  // and the m->curg stack will be unwound in lock step.
    76  // Then it calls p.GoF.  Finally it pops but does not execute the deferred
    77  // function, calls runtime.entersyscall, and returns to runtime.cgocallback.
    78  //
    79  // After it regains control, runtime.cgocallback switches back to
    80  // m->g0's stack (the pointer is still in m->g0.sched.sp), restores the old
    81  // m->g0.sched.sp value from the stack, and returns to _cgoexp_GoF.
    82  //
    83  // _cgoexp_GoF immediately returns to crosscall2, which restores the
    84  // callee-save registers for gcc and returns to GoF, which returns to f.
    85  
    86  void *_cgo_init;	/* filled in by dynamic linker when Cgo is available */
    87  static int64 cgosync;  /* represents possible synchronization in C code */
    88  
    89  // These two are only used by the architecture where TLS based storage isn't
    90  // the default for g and m (e.g., ARM)
    91  void *_cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
    92  void *_cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
    93  
    94  static void unwindm(void);
    95  
    96  // Call from Go to C.
    97  
    98  static void endcgo(void);
    99  static FuncVal endcgoV = { endcgo };
   100  
   101  // Gives a hint that the next syscall
   102  // executed by the current goroutine will block.
   103  // Currently used only on windows.
   104  void
   105  net·runtime_blockingSyscallHint(void)
   106  {
   107  	g->blockingsyscall = true;
   108  }
   109  
   110  void
   111  runtime·cgocall(void (*fn)(void*), void *arg)
   112  {
   113  	Defer d;
   114  
   115  	if(m->racecall) {
   116  		runtime·asmcgocall(fn, arg);
   117  		return;
   118  	}
   119  
   120  	if(!runtime·iscgo && !Windows)
   121  		runtime·throw("cgocall unavailable");
   122  
   123  	if(fn == 0)
   124  		runtime·throw("cgocall nil");
   125  
   126  	if(raceenabled)
   127  		runtime·racereleasemerge(&cgosync);
   128  
   129  	m->ncgocall++;
   130  
   131  	/*
   132  	 * Lock g to m to ensure we stay on the same stack if we do a
   133  	 * cgo callback. Add entry to defer stack in case of panic.
   134  	 */
   135  	runtime·lockOSThread();
   136  	d.fn = &endcgoV;
   137  	d.siz = 0;
   138  	d.link = g->defer;
   139  	d.argp = (void*)-1;  // unused because unlockm never recovers
   140  	d.special = true;
   141  	d.free = false;
   142  	g->defer = &d;
   143  
   144  	m->ncgo++;
   145  
   146  	/*
   147  	 * Announce we are entering a system call
   148  	 * so that the scheduler knows to create another
   149  	 * M to run goroutines while we are in the
   150  	 * foreign code.
   151  	 *
   152  	 * The call to asmcgocall is guaranteed not to
   153  	 * split the stack and does not allocate memory,
   154  	 * so it is safe to call while "in a system call", outside
   155  	 * the $GOMAXPROCS accounting.
   156  	 */
   157  	if(g->blockingsyscall) {
   158  		g->blockingsyscall = false;
   159  		runtime·entersyscallblock();
   160  	} else
   161  		runtime·entersyscall();
   162  	runtime·asmcgocall(fn, arg);
   163  	runtime·exitsyscall();
   164  
   165  	if(g->defer != &d || d.fn != &endcgoV)
   166  		runtime·throw("runtime: bad defer entry in cgocallback");
   167  	g->defer = d.link;
   168  	endcgo();
   169  }
   170  
   171  static void
   172  endcgo(void)
   173  {
   174  	runtime·unlockOSThread();
   175  	m->ncgo--;
   176  	if(m->ncgo == 0) {
   177  		// We are going back to Go and are not in a recursive
   178  		// call.  Let the GC collect any memory allocated via
   179  		// _cgo_allocate that is no longer referenced.
   180  		m->cgomal = nil;
   181  	}
   182  
   183  	if(raceenabled)
   184  		runtime·raceacquire(&cgosync);
   185  }
   186  
   187  void
   188  runtime·NumCgoCall(int64 ret)
   189  {
   190  	M *mp;
   191  
   192  	ret = 0;
   193  	for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
   194  		ret += mp->ncgocall;
   195  	FLUSH(&ret);
   196  }
   197  
   198  // Helper functions for cgo code.
   199  
   200  void (*_cgo_malloc)(void*);
   201  void (*_cgo_free)(void*);
   202  
   203  void*
   204  runtime·cmalloc(uintptr n)
   205  {
   206  	struct {
   207  		uint64 n;
   208  		void *ret;
   209  	} a;
   210  
   211  	a.n = n;
   212  	a.ret = nil;
   213  	runtime·cgocall(_cgo_malloc, &a);
   214  	return a.ret;
   215  }
   216  
   217  void
   218  runtime·cfree(void *p)
   219  {
   220  	runtime·cgocall(_cgo_free, p);
   221  }
   222  
   223  // Call from C back to Go.
   224  
   225  static FuncVal unwindmf = {unwindm};
   226  
   227  void
   228  runtime·cgocallbackg(FuncVal *fn, void *arg, uintptr argsize)
   229  {
   230  	Defer d;
   231  
   232  	if(m->racecall) {
   233  		reflect·call(fn, arg, argsize);
   234  		return;
   235  	}
   236  
   237  	if(g != m->curg)
   238  		runtime·throw("runtime: bad g in cgocallback");
   239  
   240  	runtime·exitsyscall();	// coming out of cgo call
   241  
   242  	if(m->needextram) {
   243  		m->needextram = 0;
   244  		runtime·newextram();
   245  	}
   246  
   247  	// Add entry to defer stack in case of panic.
   248  	d.fn = &unwindmf;
   249  	d.siz = 0;
   250  	d.link = g->defer;
   251  	d.argp = (void*)-1;  // unused because unwindm never recovers
   252  	d.special = true;
   253  	d.free = false;
   254  	g->defer = &d;
   255  
   256  	if(raceenabled)
   257  		runtime·raceacquire(&cgosync);
   258  
   259  	// Invoke callback.
   260  	reflect·call(fn, arg, argsize);
   261  
   262  	if(raceenabled)
   263  		runtime·racereleasemerge(&cgosync);
   264  
   265  	// Pop defer.
   266  	// Do not unwind m->g0->sched.sp.
   267  	// Our caller, cgocallback, will do that.
   268  	if(g->defer != &d || d.fn != &unwindmf)
   269  		runtime·throw("runtime: bad defer entry in cgocallback");
   270  	g->defer = d.link;
   271  
   272  	runtime·entersyscall();	// going back to cgo call
   273  }
   274  
   275  static void
   276  unwindm(void)
   277  {
   278  	// Restore sp saved by cgocallback during
   279  	// unwind of g's stack (see comment at top of file).
   280  	switch(thechar){
   281  	default:
   282  		runtime·throw("runtime: unwindm not implemented");
   283  	case '8':
   284  	case '6':
   285  	case '5':
   286  		m->g0->sched.sp = *(uintptr*)m->g0->sched.sp;
   287  		break;
   288  	}
   289  }
   290  
   291  void
   292  runtime·badcgocallback(void)	// called from assembly
   293  {
   294  	runtime·throw("runtime: misaligned stack in cgocallback");
   295  }
   296  
   297  void
   298  runtime·cgounimpl(void)	// called from (incomplete) assembly
   299  {
   300  	runtime·throw("runtime: cgo not implemented");
   301  }
   302  
   303  // For cgo-using programs with external linking,
   304  // export "main" (defined in assembly) so that libc can handle basic
   305  // C runtime startup and call the Go program as if it were
   306  // the C main function.
   307  #pragma cgo_export_static main