mirror of
https://github.com/golang/go
synced 2024-11-17 06:04:47 -07:00
runtime: update and tidy cgo callback description
The documentation on how cgo callbacks (C -> Go calls) works internally has gotten somewhat stale. This CL refreshes it. Change-Id: I1ab66225c9da52d698d97ebeb4f3c7b9b5ee97db Reviewed-on: https://go-review.googlesource.com/c/go/+/258937 Trust: Austin Clements <austin@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
21eb3dcf93
commit
f89d05eb7b
@ -35,44 +35,48 @@
|
||||
// cgo writes a gcc-compiled function named GoF (not p.GoF, since gcc doesn't
|
||||
// know about packages). The gcc-compiled C function f calls GoF.
|
||||
//
|
||||
// GoF calls crosscall2(_cgoexp_GoF, frame, framesize). Crosscall2
|
||||
// (in cgo/gcc_$GOARCH.S, a gcc-compiled assembly file) is a two-argument
|
||||
// adapter from the gcc function call ABI to the 6c function call ABI.
|
||||
// It is called from gcc to call 6c functions. In this case it calls
|
||||
// _cgoexp_GoF(frame, framesize), still running on m->g0's stack
|
||||
// GoF calls crosscall2(_cgoexp_GoF, frame, framesize, ctxt).
|
||||
// Crosscall2 (in cgo/asm_$GOARCH.s) is a four-argument adapter from
|
||||
// the gcc function call ABI to the gc function call ABI.
|
||||
// It is called from gcc to call gc functions. In this case it calls
|
||||
// _cgoexp_GoF(frame, framesize), still running on m.g0's stack
|
||||
// and outside the $GOMAXPROCS limit. Thus, this code cannot yet
|
||||
// call arbitrary Go code directly and must be careful not to allocate
|
||||
// memory or use up m->g0's stack.
|
||||
// memory or use up m.g0's stack.
|
||||
//
|
||||
// _cgoexp_GoF calls runtime.cgocallback(p.GoF, frame, framesize, ctxt).
|
||||
// _cgoexp_GoF (generated by cmd/cgo) calls
|
||||
// runtime.cgocallback(funcPC(p.GoF), frame, framesize, ctxt).
|
||||
// (The reason for having _cgoexp_GoF instead of writing a crosscall3
|
||||
// to make this call directly is that _cgoexp_GoF, because it is compiled
|
||||
// with 6c instead of gcc, can refer to dotted names like
|
||||
// with gc instead of gcc, can refer to dotted names like
|
||||
// runtime.cgocallback and p.GoF.)
|
||||
//
|
||||
// runtime.cgocallback (in asm_$GOARCH.s) switches from m->g0's
|
||||
// stack to the original g (m->curg)'s stack, on which it calls
|
||||
// runtime.cgocallback (in asm_$GOARCH.s) turns the raw PC of p.GoF
|
||||
// into a Go function value and calls runtime.cgocallback_gofunc.
|
||||
//
|
||||
// runtime.cgocallback_gofunc (in asm_$GOARCH.s) switches from m.g0's
|
||||
// stack to the original g (m.curg)'s stack, on which it calls
|
||||
// runtime.cgocallbackg(p.GoF, frame, framesize).
|
||||
// As part of the stack switch, runtime.cgocallback saves the current
|
||||
// SP as m->g0->sched.sp, so that any use of m->g0's stack during the
|
||||
// SP as m.g0.sched.sp, so that any use of m.g0's stack during the
|
||||
// execution of the callback will be done below the existing stack frames.
|
||||
// Before overwriting m->g0->sched.sp, it pushes the old value on the
|
||||
// m->g0 stack, so that it can be restored later.
|
||||
// Before overwriting m.g0.sched.sp, it pushes the old value on the
|
||||
// m.g0 stack, so that it can be restored later.
|
||||
//
|
||||
// runtime.cgocallbackg (below) is now running on a real goroutine
|
||||
// stack (not an m->g0 stack). First it calls runtime.exitsyscall, which will
|
||||
// stack (not an m.g0 stack). First it calls runtime.exitsyscall, which will
|
||||
// block until the $GOMAXPROCS limit allows running this goroutine.
|
||||
// Once exitsyscall has returned, it is safe to do things like call the memory
|
||||
// allocator or invoke the Go callback function p.GoF. runtime.cgocallbackg
|
||||
// first defers a function to unwind m->g0.sched.sp, so that if p.GoF
|
||||
// panics, m->g0.sched.sp will be restored to its old value: the m->g0 stack
|
||||
// and the m->curg stack will be unwound in lock step.
|
||||
// first defers a function to unwind m.g0.sched.sp, so that if p.GoF
|
||||
// panics, m.g0.sched.sp will be restored to its old value: the m.g0 stack
|
||||
// and the m.curg stack will be unwound in lock step.
|
||||
// Then it calls p.GoF. Finally it pops but does not execute the deferred
|
||||
// function, calls runtime.entersyscall, and returns to runtime.cgocallback.
|
||||
//
|
||||
// After it regains control, runtime.cgocallback switches back to
|
||||
// m->g0's stack (the pointer is still in m->g0.sched.sp), restores the old
|
||||
// m->g0.sched.sp value from the stack, and returns to _cgoexp_GoF.
|
||||
// m.g0's stack (the pointer is still in m.g0.sched.sp), restores the old
|
||||
// m.g0.sched.sp value from the stack, and returns to _cgoexp_GoF.
|
||||
//
|
||||
// _cgoexp_GoF immediately returns to crosscall2, which restores the
|
||||
// callee-save registers for gcc and returns to GoF, which returns to f.
|
||||
|
Loading…
Reference in New Issue
Block a user