Run Format

Text file src/pkg/runtime/cgocall.c

     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

View as plain text