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