coctx_swap.S源码阅读

协程切换,实际上有点像偷梁换柱,将寄存器的环境改变来实现协程的切换,在用户的角度去切换。

有一种说法,协程是非抢占式切换。首先明确什么是抢占式切换:就是当低优先性任务遇到高优先性任务,将会被迫让出CPU,供高优先级任务执行。而对于用户态实现的协程来说,什么时候切换,是由我用户决定,所以就没有被迫让出协程这一回事。

只看 x86 代码

# copy from https://github.com/Tencent/libco/blob/master/coctx_swap.S
.globl coctx_swap
coctx_swap:
    leaq (%rsp),%rax      # 栈指针 赋值给 ras 
    movq %rax, 104(%rdi) # 13 栈顶
    movq %rbx, 96(%rdi)  # 12 
    movq %rcx, 88(%rdi)  # 11 第三个参数
    movq %rdx, 80(%rdi)  # 10 第四个参数
    movq 0(%rax), %rax
    movq %rax, 72(%rdi)  # 9 返回 时的状态
    movq %rsi, 64(%rdi)  # 8 第二个参数 。 实际上就是第二个指针参数的 coctx数组
    movq %rdi, 56(%rdi)  # 7 第一个参数  第一个指针参数的 coctx数组
    movq %rbp, 48(%rdi)  # 6 栈底
    movq %r8, 40(%rdi)   # 5 第五个参数
    movq %r9, 32(%rdi)   # 4 第六个参数
    movq %r12, 24(%rdi)  # 3 是内部调用暂时寄存器 ip。
    movq %r13, 16(%rdi)  # 2 是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。
    movq %r14, 8(%rdi)   # 1  是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复
    movq %r15, (%rdi)    # 0 r15 PC寄存器
    xorq %rax, %rax      #  把rax 置为零

    movq 48(%rsi), %rbp  # 栈底
    movq 104(%rsi), %rsp # 栈顶
    movq (%rsi), %r15    # PC 指针   
    movq 8(%rsi), %r14 
    movq 16(%rsi), %r13
    movq 24(%rsi), %r12 
    movq 32(%rsi), %r9
    movq 40(%rsi), %r8
    movq 56(%rsi), %rdi
    movq 80(%rsi), %rdx
    movq 88(%rsi), %rcx
    movq 96(%rsi), %rbx
    leaq 8(%rsp), %rsp  # 栈顶指针 rsp的 -8 ?
    pushq 72(%rsi)      # 把返回时的状态压栈 (这样就能够 恢复之前的状态
    movq 64(%rsi), %rsi  # 恢复第二个参数 
    ret 

  • 该函数的参数是两个 char [14]数组,用该数组去保存当前程序的状态,和即将跳转的下一个状态
  • 指令后面带 q,是指8个字节,
#include "lib_prot_pd.h" #include "mod_input_output.h" #include "mod_display.h" #include "mod_queue.h" #include "app_typec_deal.h" #include "app_init.h" #include "lib_multi_protocol.h" uint8_t typeca_ufp= 0; void typeca_hard_reset_cb(void) { static uint8_t b_typec_hard_reset_lock= RESET; if(h_pd.output.b_source_read_hard|| \ h_pd.output.b_sink_read_hard) { if(b_typec_hard_reset_lock== RESET) { b_typec_hard_reset_lock= SET; mod_queue_send(PLUG_CA_RST_P); } }else { if(b_typec_hard_reset_lock) { b_typec_hard_reset_lock= RESET; mod_queue_send(PLUG_CA_RST_N); } } } void typecb_hard_reset_cb(void) { static uint8_t b_typec_hard_reset_lock= RESET; if(h_pd.output.b_source_read_hard|| \ h_pd.output.b_sink_read_hard) { if(b_typec_hard_reset_lock== RESET) { b_typec_hard_reset_lock= SET; mod_queue_send(PLUG_CB_RST_P); } }else { if(b_typec_hard_reset_lock) { b_typec_hard_reset_lock= RESET; mod_queue_send(PLUG_CB_RST_N); } } } void typeca_pr_swap_cb(void) { static uint8_t b_pd_power_role_swap_lock; if(h_pd.output.b_pr_swap_en) { if(h_pd.output.b_source_read_pr_swap) { b_pd_power_role_swap_lock= SET; /*用户代码*/ //关 VBus }else if(h_pd.output.b_sink_read_pr_swap) { /*用户代码*/ //DC-DC 进入放电状态,升压,打开 VBus } }else { b_pd_power_role_swap_lock= RESET; } } void typecb_pr_swap_cb(void) { static uint8_t b_pd_power_role_swap_lock; if(h_pd.output.b_pr_swap_en) { if(h_pd.output.b_source_read_pr_swap) { b_pd_power_role_swap_lock= SET; /*用户代码*/ //关 VBus }else if(h_pd.output.b_sink_read_pr_swap) { /*用户代码*/ //DC-DC 进入放电状态,升压,打开 VBus } }else { b_pd_power_role_swap_lock= RESET; } } bool typeca_vbus_exist_cb(void) { //判断一下0.8V VBus电压 return mod_io_typeca_acin(); } bool typecb_vbus_exist_cb(void) { //判断一下0.8V VBus电压 return mod_io_typecb_acin(); } void typeca_attached_src_cb(void) { /** * !!! * 兼容性测试需要 */ mod_io_a1d_out(); mod_queue_send(PLUG_CAD_IN); } void typecb_attached_src_cb(void) { mod_io_a1d_out(); mod_queue_send(PLUG_CBD_IN); } void typeca_attached_snk_cb(void) { mod_queue_send(PLUG_CAC_IN); typeca_ufp = 1; } void typecb_attached_snk_cb(void) { mod_queue_send(PLUG_CBC_IN); typeca_ufp = 1; } void typeca_unattached_cb(void) { mod_queue_send(PLUG_CAX_OUT); typeca_ufp = 0; } void typecb_unattached_cb(void) { mod_queue_send(PLUG_CBX_OUT); }
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值