首页 > 其他分享 >srs(state thread)如何实现协程切换

srs(state thread)如何实现协程切换

时间:2024-02-01 17:58:27浏览次数:36  
标签:md 协程 thread st srs cxt rdi JB movq

417行的宏执行协程A上下文的保存 419行 _st_vp_schedule 在RUNQ中找到一个待执行协程B, 恢复协程B的上下文, 切换到该协程B执行. 协程B执行到io阻塞或者sleep事件, 就会重新把协程B缓存起来, 并寻找一个待执行协程(假设这里就AB两个协程),恢复协程A的上下文继续执行. 完成协程切换.

协程上下文保存



#define MD_SETJMP(env) _st_md_cxt_save(env)
/****************************************************************/

    /*
     * Internal __jmp_buf layout
     */
    #define JB_RBX  0
    #define JB_RBP  1
    #define JB_R12  2
    #define JB_R13  3
    #define JB_R14  4
    #define JB_R15  5
    #define JB_RSP  6
    #define JB_PC   7

    .file "md.S"
    .text

    /* _st_md_cxt_save(__jmp_buf env) */
    .globl _st_md_cxt_save
        .type _st_md_cxt_save, @function
        .align 16
    _st_md_cxt_save:
        /*
         * Save registers.
         * 寄存器数据的转存
         */
        movq %rbx, (JB_RBX*8)(%rdi)
        movq %rbp, (JB_RBP*8)(%rdi)
        movq %r12, (JB_R12*8)(%rdi)
        movq %r13, (JB_R13*8)(%rdi)
        movq %r14, (JB_R14*8)(%rdi)
        movq %r15, (JB_R15*8)(%rdi)
        /* Save SP */
        // 关于leaq和movq的区别:
        // refs: https://courses.cs.washington.edu/courses/cse374/16wi/lectures/leaq-movq.pdf
        // rsp寄存器存放的内容是栈顶的地址, leaq指令是把rsp+8的地址信息存放到(JB_RSP*8)(%rdi)中.
        // 相当于是把栈pop之后的栈顶地址存放到了(JB_RSP*8)(%rdi).
        leaq 8(%rsp), %rdx
        movq %rdx, (JB_RSP*8)(%rdi)
        /* Save PC we are returning to */
        // rsp寄存器指向的栈顶地址上存放的是_st_md_cxt_save函数的返回地址, 
        // 把rsp放在(JB_PC*8)(%rdi)中, 等恢复协程的时候就可以jump到(JB_PC*8)(%rdi),相当于恢复的时候直接返回了. 
        // 注意现在只是把协程上下文保存了, 还没有切换呢.切回该协程的时候, 会jump到PC(下面_st_md_cxt_restore函数写明)
        movq (%rsp), %rax
        movq %rax, (JB_PC*8)(%rdi)
        // 返回值为rax的异或, 恒为0; 
        // _st_md_cxt_save返回值什么时候为1呢? 
        // 在切回该协程的时候,jump到PC,PC就是_st_md_cxt_save返回的地方(上图417行), _st_md_cxt_restore根据输入的val设置了eax, eax作为函数返回值.
        xorq %rax, %rax
        ret
    .size _st_md_cxt_save, .-_st_md_cxt_save


/****************************************************************/

  

 

协程上下文恢复

#define MD_LONGJMP(env, val) _st_md_cxt_restore(env, val)
/****************************************************************/

    /* _st_md_cxt_restore(__jmp_buf env, int val) */
    .globl _st_md_cxt_restore
        .type _st_md_cxt_restore, @function
        .align 16
    _st_md_cxt_restore:
        /*
         * Restore registers.
         */
        movq (JB_RBX*8)(%rdi), %rbx
        movq (JB_RBP*8)(%rdi), %rbp
        movq (JB_R12*8)(%rdi), %r12
        movq (JB_R13*8)(%rdi), %r13
        movq (JB_R14*8)(%rdi), %r14
        movq (JB_R15*8)(%rdi), %r15
        /* Set return value */
        // 把val参数作为返回值. jump之后作为了_st_md_cxt_save的返回值.
        test %esi, %esi
        mov $01, %eax
        cmove %eax, %esi
        mov %esi, %eax
        // 把栈顶寄存器rsp恢复为(之前_st_md_cxt_save中rsp栈pop之后的栈顶地址)
        // 把PC指针恢复为_st_md_cxt_save的调用者, 并跳转到调用_st_md_cxt_save的地方
        movq (JB_PC*8)(%rdi), %rdx
        movq (JB_RSP*8)(%rdi), %rsp
        /* Jump to saved PC */
        jmpq *%rdx
    .size _st_md_cxt_restore, .-_st_md_cxt_restore

    /****************************************************************/ 

  

 

 

 

标签:md,协程,thread,st,srs,cxt,rdi,JB,movq
From: https://www.cnblogs.com/micoblog/p/18001757

相关文章

  • [cpp]: thread -- with header <syncstream>
    [cpp]: thread--withheader<syncstream>    一、说明: 1、【并发编程】thread编程中的同步输出:std::osyncstream// Definedinheader <syncstream>   二、程序代码1#include<iostream>2#include<string>3#include<......
  • Thread和ThreadLocal、ThreadLocalMap的关系
    ThreadLocal是什么 ThreadLocal官方注释: 翻译过来大致意思是:ThreadLocal可以提供局部变量,通过set和get方法对局部变量进行操作,并且局部变量是每个线程独立的、数据隔离的。ThreadLocal通常作为线程的私有的静态变量,用于和UserId、事务Id相关联。set方法:publicvoidse......
  • ThreadPoolExecutor源码阅读
    目录简介继承结构ExecutorExecutorServiceAbstractExecutorServiceExecutorCompletionService线程池配置代码分析成员变量方法总结参考链接本人的源码阅读主要聚焦于类的使用场景,一般只在java层面进行分析,没有深入到一些native方法的实现。并且由于知识储备不完整,很可能出现疏漏......
  • Python笔记四之协程
    本文首发于公众号:Hunter后端原文链接:Python笔记四之协程协程是一种运行在单线程下的并发编程模型,它的特点是能够在一个线程内实现多个任务的并发操作,通过在执行任务时主动让出执行权,让其他任务继续执行,从而实现并发。以下所有的代码都是在Python3.8版本中运行。本篇笔记......
  • C# AsyncLocal 是如何实现 Thread 间传值
    一:背景1.讲故事这个问题的由来是在.NET高级调试训练营第十期分享ThreadStatic底层玩法的时候,有朋友提出了AsyncLocal是如何实现的,虽然做了口头上的表述,但总还是会不具体,所以觉得有必要用文字+图表的方式来系统的说一下这个问题。二:AsyncLocal线程间传值1.线程间传值途径在C#编......
  • 标准库版thread group
    使用标准库替代boost中的threadgroup转载修改自秋天的栗树:用std::thread替换实现boost::thread_group使用unique_ptr替换了其中的auto_ptr(已不受支持);添加了<functional>和<algorithm>两个头文件;#include<list>#include<mutex>#include<thread>#include<memory>......
  • pthread_detach函数
     线程分离状态:指定该状态,线程主动与主控线程断开关系。使用pthread_exit或者线程自动结束后,其退出状态不由其他线程获取,而直接自己自动释放。网络、多线程服务器常用。    进程若有该机制,将不会产生僵尸进程。僵尸进程的产生主要由于进程死后,大部分资源被释放,一点残留资......
  • java中的ThreadLocal
    1.ThreadLocal的基本使用在Java的多线程并发执行过程中,为了保证多个线程对变量的安全访问,可以将变量放到ThreadLocal类型的对象中,使变量在每个线程中都有独立值,不会出现一个线程读取变量时而被另一个线程修改的现象。ThreadLocal类通常被翻译为线程本地变量类或者线程局部变......
  • 线程进程协程
    python(48):进程,线程,协程区别进程:拥有代码和打开的文件资源、数据资源、独立的内存空间。线程:线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。线程拥有自己的栈空间。对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。进程--......
  • python(48) 进程,线程 ,协程、
    python(48):进程,线程,协程、区别进程:拥有代码和打开的文件资源、数据资源、独立的内存空间。线程:线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。线程拥有自己的栈空间。对操作系统来说,线程是最小的执行单元,进程是最小的资源管理单元。......