我们提供安全,免费的手游软件下载!
在前文《Go runtime调度器精讲(七):案例分析》中,我们介绍了一个抢占的案例。本文将继续深入源码层面,探讨Go runtime调度器是如何实现抢占逻辑的。
在之前的文章中我们提到了sysmon线程,它是运行在系统栈上的监控线程,负责监控goroutine的状态并做相应处理。本文将重点介绍sysmon线程的抢占处理。
sysmon
的创建在
src/runtime/proc.go:sysmon
中:
// The main goroutine.
func main() {
...
if GOARCH != "wasm" { // no threads on wasm yet, so no sysmon
systemstack(func() {
newm(sysmon, nil, -1)
})
}
...
}
sysmon
不需要和P绑定,作为监控线程运行在系统栈。进入
sysmon
后,根据goroutine的状态进行相应处理,包括抢占处理。
当sysmon线程发现运行时间过长的goroutine时,会将goroutine的
stackguard0
更新为一个比任何栈都大的
stackPreempt
值。当线程进行函数调用时,会比较栈顶
rsp
和
g.stackguard0
,检查goroutine栈的栈空间。因为更新了goroutine栈的
stackguard0
,线程会走到扩展逻辑,进入根据
preempt
标志位,执行对应的抢占调度。
本文介绍了sysmon线程和抢占运行时间过长的goroutine的实现方式。下一篇文章将继续深入介绍sysmon线程和抢占系统调用时间过长的goroutine。
热门资讯