Go线程调度器-启用或停止M

启用或停止M

相关函数

stopm(): 停止当前M的执行,直到因有新的G变得可运行而被唤醒

gcstopm(): 为串行运行时任务的执行让路,停止当前M的执行。串行运行时任务执行完毕后会被唤醒

stoplockedm(): 停止已与某个G锁定的当前M的执行,直到因这个G变得可运行的而被唤醒

startlockedm(gp *g): 唤醒与gp锁定的那个M,并让该M去执行gp

startm(_p_ *p, spinning bool): 唤醒或创建一个M去关联_p_并开始执行

调度器图例

在这里插入图片描述

启用或停止M图例

在这里插入图片描述

步骤

(1)

调度器在执行调度流程的时候,会先检查当前M是否与某个G锁定,如果锁定存在,调度器就会调用stoplockedm函数停止当前M

stoplockedm函数先解除当前M与本地P之间的关联,并通过调用一个名为handoffp的函数把这个P转手给其他M,在这个转手P的过程中会简介调用startmh函数

一旦这个P被转手,stoplockedm函数就会停止当前M的执行,并等待唤醒

(2)

另一方面,如果调度程序为当前M找到了一个可运行的G,却发现该G已与某个M锁定了,那么就会调用startlockedm函数并把这个G作为参数传入

startlockedm函数会通过参数gp的lockedm字段找到与之锁定的那个M(已锁的M),并把当前M的本地P转手给它

这里的转手P的过程要比(1)中的简单很多,startlockedm函数会先解除当前M与本地P之间的关联,然后把这个P赋给已锁M的nextp字段

(3)

startlockedm函数的执行会使与其参数gp锁定的那个M(已锁M)被唤醒

通过gp的lockedm字段可以找到已锁M。一旦已锁M被唤醒,就会与和它预联的P产生正式的关联,并去执行与之关联的G

(4)

startlockedm函数在最后会调用stopm函数。stopm函数会先把当前M放入调度器的空闲M列表,然后停止当前M。这里被停止的M,可能会在之后因有P需要转手,或有G需要执行而被唤醒

从另一个角度看,一旦M要停止就会把它的本地P转手给别的M。一旦M被唤醒,就会先找到一个P与之关联,即找到它的新的本地P

并且,这个P一定是在该M被唤醒之前由别的M预联给它的。因此,P总是会被高效利用

如果handoffp函数无法把作为其参数的P转给一个M,那么就会把这个P放入调度器的空闲P列表。该列表中的P会在需要时(比如有G需要执行)被取用

(5)

调度器在执行调度器流程的时候,也会检查是否有串行运行时任务正在等待执行

如果有,调度器就会调用gcstopm函数停止当前M

gcstopm函数会通过当前M的spinning字段检查它的自旋状态,如果其值为true,就把false赋给它,然后把调度器中用于记录自旋M数量的nmspinning字段的值减1

如此一来就完全重置了当前M的自旋状态标识,一个将要停止的M理应脱离自旋状态。在这之后,gcstopm函数会释放本地P,并将其状态设置为Pgcstop

然后再去自减并检查调度器的stopwait字段,并在发现stopwait字段的值为0时,通过stopnote字段唤醒等待执行的串行运行时任务

(6)

gcstopm函数在最后会调用stopm函数。同时,当前M会被放入调度器的空闲列表并停止

只要有串行运行时任务准备执行,"Stop the world"就会开始,所有在调度过程中的M就会执行步骤(5)和(6)

其中的步骤(5)更是决定了串行运行时任务是否能够被尽早地执行

(7)

调度总有不成功的时候。如果经过完整的一轮调度之后,仍找不到一个可运行的G给当前M执行,那么调度器程序就会通过调用stopm函数停止当前的M

一旦停掉的M被唤醒,stopm函数就会负载关联它和已与它预联的P,这也是在为M的执行做最后的准备

还有一种情况,如果stopm函数被发现当前M是因有可并发执行的GC任务而被唤醒的,那么就在执行完该任务之后再次停止当前M

(8)

所有经由调用stopm函数停止的M,都可以通过调用startm函数。与步骤(7)对应,一个M被唤醒的原因总是有新工作要做

比如,有了新的自由的P,或者有了新的可运行的G。有时候,传入startm函数的参数_p_为nil,这就说明在唤醒一个M的同时,需要从调度器的空闲P列表获取一个P作为M运行G的上下文环境

如果这个列表已经空了,那么startm函数也就无能为力了(没有上下文环境有了M也没有用),这时startm函数会直接返回

一旦有了一个P,startm函数就会再从调度器的空闲M列表获取一个M。如果该列表已空就创建一个新的M

无论如何,startm函数都会把拿到的P和这个M预联,然后让该M做好执行准备

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值