brpc引入m:n的线程模型,固定的内核线程调度运行大量的bthread以避免内核线程上下文切换带来的开销。

bthread类似协程,即用户态线程,bthread的切换不会陷入内核,不会进行一系列内存同步等耗时操作,因此bthread的切换在100-200ns,相比内核线程的微秒级别有着数量级的提升。

为了实现协程需要协程栈,协程的初始化,以及协程间的切换,下面来逐一分析这几个过程。

首先看下协程栈的结构,如下,context指向协程栈顶,stacktype表示栈的类型(大小),storage为栈空间

栈分配时会通过mmap匿名映射一段空间,然后将高地址位赋值给bottom。

接着看下创建一个bthread的过程,函数入参分别为协程栈底,栈大小,以及这个bthread要执行的函数,返回值,即context为协程栈顶,具体看如下代码。

将rdi赋值给rax,rdi保存的是第一个参数,即stack的bottom

对rax进行 16字节对齐

将rax下移72字节

将rdx保存至rax + 56,rdx为第三个参数,即函数fn的地址

保存MXCSR寄存器(sse浮点数运算状态寄存器,32位)到rax所在位置

将 FPU 控制字的当前值存储到rax + 4

计算finish的绝对地址,保存到rcx中

将rcx保存到rax + 64

函数退出

rax保存的是栈顶,因此context现在指向协程栈的栈顶

这一过程如下图所示:上面为高地址,下面为低地址;左侧为调用此函数的bthread/pthread栈,右侧为执行完成后,新bthread栈空间结构,大框表示64位,小框表示32位,这里关于各个寄存器在栈中保存的位置是为了和协程切换函数里保持一致,具体下面会提到。

接下来看下协程的切换过程,首先看下代码,ofc为旧协程的栈顶,nfc为新协程的栈顶。

337-342行为将对应寄存器push到旧的协程栈中

将rsp下移8字节

比较rcx和0,因为rcx为0,所以zf为1

因为zf为1,所以跳转

将rsp保存至rdi中,rsp指向当前协程栈栈顶,rdi为第一个入参,即ofc

将rsi保存到rsp中,rsi为第二个参数,即nfc,此时栈顶指针rsp指向了新的协程栈

将rsp上移8字节

将协程栈中r12-rbp依次pop到对应寄存器

将rdx保存到rax,rdx为第三个参数,rax为返回值

将rdx保存到rdi,rdi为第一个入参,因此将作为新协程运行的入参

跳转到r8对应的寄存器运行。

在协程切换过程中有两种情况,第一种为新协程是通过bthread_make_fcontext函数刚刚创建的栈,另一种是已经运行过的栈,这两种过程分别如下图所示

上图表示切换到新协程的过程,因为pop到r8的是fn,所以接下来会运行创建协程时的函数fn,当协程运行结束后ret时会pop rip,此时便会执行finish。

上图表示切换到已经运行一段时间的协程的过程,因为右侧协程在上一次被切换的时候会将下一条指令地址push到栈中,然后在这次切换过程中被pop到r8,因此便会继续执行上次被切换后的代码。

brpc源码学习(二)-bthread的创建与切换相关推荐

  1. Golang源码学习(二)----Go源码学习基础

    ### 本文源码版本为 GO 1.17.8 Windows/amd64: ### 可能参与对比的版本:GO 1.16.2 Linux/amd64一.Golang的编译器究竟是如何工作的? (学习源码有 ...

  2. SocketServer源码学习(二)

    SocketServer 中非常重要的两个基类就是:BaseServer 和 BaseRequestHandler 在SocketServer 中也提供了对TCP以及UDP的高级封装,这次我们主要通过 ...

  3. 使用base标签后图片无法加载_Spring 源码学习(二)-默认标签解析

    `Spring` 解析默认标签~ 从上一篇笔记可以看出,在容器注册 bean 信息的时候,做了很多解析操作,而 xml 文件中包含了很多标签.属性,例如 bean . import 标签, meta ...

  4. ROS源码学习 二、线程池

    2021SC@SDUSC 目录 1.写在前面 2.ROS线程池概述 3.ROS线程池模型 4.ROS线程池源码详解 5.总结 1.写在前面 ROS作为一个操作系统,其职责是协调具有不同功能的node之 ...

  5. erlang底层c定时器设计-Erlang源码学习二

    Erlang底层的定时器实现位于源码的erts/emulator/beam/time.c文件,用时间轮的方式动态添加和删除定时器,结构体名为typedef struct ErtsTimerWheel_ ...

  6. brpc源码学习(一)-butex

    由于brpc中引入了bthread,如果在bthread中使用了mutex,那么将会挂起当前pthread,导致该bthread_worker无法执行其他bthread,因此类似pthread和fut ...

  7. Box2d源码学习二内存管理之SOA的实现

    本系列博客是由扭曲45原创,欢迎转载,转载时注明出处,http://blog.csdn.net/cg0206/article/details/8258166 SOA,全称small object al ...

  8. java集合类程序代码_java集合类源码学习二

    我们查看Collection接口的hierarchy时候,可以看到AbstractCollection这样一个抽象类,它实现了Collection接口的部分方法,Collection集合系列的各个集合 ...

  9. Thrift源码学习二——Server层

    Thrift 提供了如图五种模式:TSimpleServer.TNonblockingServer.THsHaServer.TThreadPoolServer.TThreadSelectorServe ...

  10. yara 源码学习(二) 规则编译部分

    yara规则的详细信息请参考: https://yara.readthedocs.io/en/stable/writingrules.html 根据官方文档,yara规则长这个样子: [1]:yara ...

最新文章

  1. 时间同步软件 windows_电脑便签设置事件时间提醒软件哪个好用
  2. PyTorch 深度学习: 60 分钟极速入门
  3. 学习面试题Day08
  4. 如何理解离散傅里叶变换(一)实数形式傅里叶变换
  5. 域名劫持到百度被黑详解DNS技术
  6. 返回最大数,不同语言之间的比较
  7. Linux学习:第一天,
  8. MFC开发IM-第十八篇、如何设置编辑框的内容
  9. L3-019 代码排版 (30 分)-PAT 团体程序设计天梯赛 GPLT
  10. [MySQL FAQ]系列 -- 如何利用触发器实现账户权限审计
  11. WPF界面设计的模式
  12. Ubuntu安装dos2unix命令
  13. 一打卡作弊软件CEO被判5年6个月,网友:这也太...
  14. 游戏开发要学习哪些东西
  15. win7设置护眼模式
  16. cmake find_package 原理简介以及使用说明
  17. 开源RPC框架Pigeon
  18. 翼支付杯大数据建模大赛-季军方案
  19. windows 离线安装nessus
  20. 适合学生党的蓝牙耳机品牌有哪些?性价比高的无线耳机推荐

热门文章

  1. AutoJs Pro 7.0.4-1 实战教程---史上最全快手极速版
  2. Unity3D基础界面
  3. 匹兹堡大学计算机科学世界排名,2020年匹兹堡大学QS世界排名
  4. mysql支持sparql吗_neo4j 中使用sparql查询
  5. SSM8==纯注解SSM项目:实现单表CRUD、事务、自定义异常和统一异常处理、RESTFUL风格接口、统一返回值格式(状态码、内容、消息)、JSON传参、axios、vue.js、elementUI
  6. 吴恩达卷积神经网络笔记,吴恩达人工智能公开课
  7. 【博弈 —— SG函数详解+例题解析】
  8. DevOps云翼日志服务实践
  9. ros机器人标定线速度与角速度
  10. [非原子批处理出现故障]使用 getNextException() 来检索已经过批处理的特定元素的异常。 ERRORCODE=-4228, SQLSTATE=null