go抢占式调度
Posted 2021-05-25 13:13 +0800 by ZhangJie ‐ 1 min read
分享:
SIGURG,在信号处理函数runtime/signal_unix.go:sighandler(…)函数中又看到对sigPreempt的处理。
SIGURG实现抢占式调度: 对应这个函数doSigPreempt,检查当前g是不是wantAsyncPreempt,ok的话检查是不是isAsyncSafePoint,ok的话,sigctxt.pushCall(funcPC(asyncPreempt), newpc),这个函数调整PC并注入一个对asyncPreempt的调用。
TODO wantAsyncPreempt对应的判断参数是谁去设置的,什么时候设置的?
TODO isAsyncSafePoint,safepoint的含义?这个函数的注释以及代码中的if-else已经足够结实清楚什么是safepoint了,以及safepoint的意义了。
看下asyncPreempt的逻辑,该函数是在汇编中实现的,首先保存寄存器的值,然后调用asyncPreempt2执行其他处理。
g.preemptStop决定是挂起g还是重新调度g:
- 如果被抢占的g的g.preemptStop为true,则执行mcall(preemptPark)挂起该g,g的状态被改为preempted,后面什么时机会重新调度它吧。然后执行schedule调度其他goroutine执行;
- 如果g.preemptStop为false,则mcall(gopreempt_m)将g从running改为runnable重新调度一次。
大致的抢占式调度逻辑就是这样的。
ps: func mcall(fn func(*g)),mcall switches from the g to the g0 stack and invokes fn(g), where g is the goroutine that made the call.