golang 调度之wakep和M创建
说说wakep
和m的创建吧
wakep
调用时机和作用
- 作用:wakep的作用是添加一个P来执行goroutinue
- 时机:在有G变为runnable的时候 如:newproc ready
wakep中调用startm
来启动一个新的m
startm
- 首先如果传递过来P是nil,则需要获取一个idle P,如果获取不到,直接返回
- 调用
mget
获得一个已经睡眠m - 如果没有获得m,则调用
newm
创建一个新的m - 如果是创建的m则直接返回,后面再具体将newm的功能。如果是获取的m,则调用notewakeup来唤醒m(因为m在mput的时候已经睡眠了)
mget
mget
比较简单,就是从midle中取出一个通过mput放入的m,如果没有则返回nil
newm
func newm(fn func(), _p_ *p)
先看看注释:
// Create a new m. It will start off with a call to fn, or else the scheduler.
// fn needs to be static and not a heap allocated closure.
// May run with m.p==nil, so write barriers are not allowed.
创建一个m并执行fn或者是一次调度,所谓创建m就是启动一个系统线程。
- 调用allocm创建一个m并设置m.nextp为传进来的参数_p_,allocm还为m创建g0,并设置一个栈
- 这里有cgo的东西,暂时先不说,我也不懂,呵呵。
- 如果不是cgo,调用newosproc
newosproc
这个函数就有点系统相关了,这里看os_windows.go下的。
这个函数会调用一个系统调用来创建线程
这里创建的线程的启动函数为tstart_stdcall
所以我们先不纠结系统调用的问题,直接看线程启动之后会干嘛:
这个函数是用汇编写的(sys_windows_amd64.s)
在这个函数中,第一参数是存放在CX中。参数就是前面创建的m
- 获取g0
- 在这个函数中会重新设置栈给g0
- 这里把当前线程的栈顶给g的栈底,然后预留64K的空间给g0,并设置栈的stack_hi和stack_lo,以及stackguard0和stackguard1.
- 设置线程本地存储 将m的tls设置到0x28(GS),然后设置m给g0.m,设置g0给tls,以便g(tls)可以取到当前g。
- 调用runtime.stackcheck
- 调用runtime.mstart
stackcheck就是检查当前的SP是不是[stack_hi,stack_lo)区间
然后看mstart
mstart
这里lo != 0, ==0那一段代码得意思就是在这里设置设置栈
意思是说cgo的时候可能值设置了栈大小到stack.hi
所以这里先创建一个局部变量size保存stack.hi,因为size是局部变量,所以就把size的栈地址设置为stack.hi,然后根据size计算出stack.lo
调用mstart1
mstart1会进行一些初始化并保存g0的栈等,
如果这里是m0,还会初始化信号量等。
如果m有startfn这个函数,也就是之前调用newm的时候传递了函数过来的话,就先执行这个函数。sysmon就是通过这种方式执行的。
这里如果是helpgc,则直接停掉这个m,或者如果不是m0,会把m.nextp设置给m.p
然后调用schedule来调度任务。
schedule
这个函数主要是找到一个runnable的g 然后调用execute来启动g
这里有可能会只是trance或者gc的g,这部分还不太了解。
下面是先从全局队列里面取一次,因为如果不先取全局队列,那么有可能两个g互相继续而导致全局的g没有机会运行。
然后尝试从本地(P)的队列获取一个g
调用findrunnable,这个函数会阻塞知道找到一个可运行的g
如果找到一个g且为m为spinning,则清除状态
调用execute执行找到的g
findrunnable
- 如果gcwatting stopm
- fingwait没看懂
- 从本地P队列获取g
- 从全局队列获取g
- 如果没有人在进行netpoll,尝试netpoll发现g
- 如果当前所有的P都是idle状态, 跳过从别的P偷取工作流的流程,否则进行偷取
- 如果spinning的M大于busy的P,则直接让m睡眠
- 又是GC的worker
- 设置P为idle
- 暂时让nmspinning-1,然后再次检查所有P上的runq,发现有P上有多余的goroutinue,则让M重新得到一个P,然后再次进行上面的查找g的流程。
- 又是GC
- 如果没有人在netpool,让当前M永久阻塞在netpool睡眠。
- 如果有人在netpool了,则直接stopm,让m睡眠
execute
- 先把g的状态设置为running
- 设置栈为正常状态而不是preempt状态
- 调用gogo切换SP和PC等。
golang 调度之wakep和M创建相关推荐
- Golang调度器GPM原理与调度全分析
第一章 Golang调度器的由来 第二章 Goroutine调度器的GMP模型及设计思想 第三章 Goroutine调度场景过程全图文解析 一.Golang"调度器"的由来? (1 ...
- 开源分布式Job系统,调度与业务分离-如何创建一个计划HttpJob任务
项目介绍: Hangfire:是一个开源的job调度系统,支持分布式JOB!! Hangfire.HttpJob 是我针对Hangfire开发的一个组件,该组件和Hangfire本身是独立的.可以独立 ...
- 从Golang调度器的作者视角探究其设计之道!
导语 | Golang核心开发人员.goroutine调度的设计者Dmitry Vyukov,在2019年的一个talk里深入浅出地阐述了goroutine调度的设计思想以及一些优化的细节.本文是笔者 ...
- golang调度模型
https://tonybai.com/2017/06/2... 线程模型 内核级线程模型(KSE(Kernel Scheduling Entity)) 关键点: 完全靠操作系统调度 每一个用户线程绑 ...
- golang 初始化并赋值_Go语言创建、初始化数组的常见方式汇总
本文实例总结了Go语言创建.初始化数组的常见方式.分享给大家供大家参考.具体分析如下: Go语言的语法很灵活,以下展示了创建并初始化数组的多种方式: //数组初始化的各种方式 func arraySl ...
- golang对mongo数据库索引的创建,删除操作
package main import ( "fmt" "log" "time" "gopkg.in/mg ...
- 组件分享之后端组件——阿里妈妈前端团队出品的开源接口管理工具RAP第二代rap2-delos...
组件分享之后端组件--阿里妈妈前端团队出品的开源接口管理工具RAP第二代rap2-delos 背景 近期正在探索前端.后端.系统端各类常用组件与工具,对其一些常见的组件进行再次整理一下,形成标准化组件 ...
- golang源码分析:调度器chan调度
golang调度机制chan调度 golang的调度策略中,碰见阻塞chan就会将该chan放入到阻塞的g中,然后再等待该chan被唤醒,这是golang调度器策略的主动调度策略之一,其中还有其他的主 ...
- Golang知识点二、GMP调度模型
GMP调度模型 1. 调度器由来 调度器分为进程调度器和线程调度器. 1.1. 单进程时代 单进程系统存在一定问题:1. 单一执行流程.计算机只能一个任务一个任务处理 2. 进程阻塞所带来的C ...
最新文章
- 成功检测远距离目标,将点云与RGB图像结合,谷歌Waymo提出新算法:4D-Net
- python期末知识点总结_期末考试必备复习提纲丨9年级数学上册知识点总结归纳(人教版)...
- C# 笔记 .net与C#简单说明
- 信号分解:双正交、完备性、对偶向量
- [j2me]手机也可以玩播客(Podcast)! Geek开发说明[开源]
- CSS魔法堂:那个被我们忽略的outline 1
- GNU开发工具——Bochs模拟器
- ctf攻防渗透-加密-栅栏密码
- 数据库中常见mdf 、ndf 、ldf 、文件
- Shopee优选卖家真的重要吗?
- 腾讯回应“暴力裁员”
- 计算机路由器无线级联配置,两个无线路由器级联怎么设置?
- 安卓眼球追踪_一问易答:非三星手机如何实现眼球追踪
- 解救IP被封的服务器
- php 调用 C++
- 掘金 AMA:听闲鱼客户端架构师--邬吉风聊 Flutter 和移动端开发那些事
- NSPredicate模糊、精确、查询
- 通用权限管理设计篇_设计模式
- 将localhost换成自己电脑的ip的方法
- Ubuntu笔记本 在终端 听 收音机
热门文章
- 徐明星系列之徐明星创办的OK资本成为RnF金融有限公司的锚定投资者
- linux configure 的 --prefix 参数的作用
- underscore.js 报_is not defined解决方法
- vb实现webbrowser显示html,VB.NET 通过窗口句柄,获取webbrowser控件HTML内容
- 归并排序算法(C语言)
- 01背包总结+传授个人经验
- 安装docker和docker的开机启动及容器的开机自启
- Linux学习日记15——exec函数族、回收子进程
- [停更] 微信平台上的DRL [停更]
- linux下怎样安装openmpi