newproc1三个g分别代表什么意思?有何作用?

来源:1-4 Go 程序是怎么跑起来的

非晓为骁

2021-06-24 22:52:37

http://img.mukewang.com/climg/60d49bbf094a752d13611517.jpg

go func(){

}()

这个调的是newproc,newproc调newproc1会传进去一个g。但是newproc1里面有3个g,分别是图里面的1,2,3,最后调度的是2,这是为什么呢?为什么不是就是在对3进行初始化操作?

4是不是全都是在初始化g?

写回答

1回答

Xargin

2021-06-25

newproc1 是从 newproc 进来的

func newproc(siz int32, fn *funcval) {
   argp := add(unsafe.Pointer(&fn), sys.PtrSize)
   gp := getg()
   pc := getcallerpc()
   systemstack(func() {
      newproc1(fn, argp, siz, gp, pc)
   })
}

要注意到这里有个 systemstack 的动作,这个是从用户 g 切换到 g0 栈来执行函数的,

所以在 newproc1 中 getg 得到的 _g_ 是 g0,这个可以在 delve 里验证:

(dlv) l
> runtime.newproc1() /usr/local/go/src/runtime/proc.go:3451 (PC: 0x10334da)
Warning: debugging optimized function
  3446:	// at argp. callerpc is the address of the go statement that created
  3447:	// this. The new g is put on the queue of g's waiting to run.
  3448:	func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerpc uintptr) {
  3449:		_g_ := getg()
  3450:
=>3451:		if fn == nil {
  3452:			_g_.m.throwing = -1 // do not dump full stacks
  3453:			throw("go of nil func value")
  3454:		}
  3455:		acquirem() // disable preemption because it can be holding p in a local var
  3456:		siz := narg
(dlv) p _g_ == _g_.m.g0
true


callergp 指的是创建这个 goroutine 的原始的那个用户 g,


你图上的 2 才是 newproc1 真正创建出来的新 g,

只不过 g 结构体本身有复用,要用 gfget 去找缓存


中间的代码确实是初始化代码。

0

Go高级工程师实战营

慕课网与 GoCN 社区官方联手打造,定义行业Go高级人才培养标准,4个月,快速晋升为P6+/D7级高级人才。

458 学习 · 266 问题

查看课程