实现coroutine的symmetric context switch

main.c

#include <stdio.h>
 
#define STACK_SIZE 65536
#define REG_SIZE sizeof(long)
 
typedef void (*cothread_func)();
 
typedef struct
{
    unsigned long regs[2]; /* [0]:rbp [1]:rsp */
    char stack[STACK_SIZE];
} cothread_t;

/* assembly implemented */
void cothread_yield(cothread_t* from, cothread_t* to);
 
void cothread_create(cothread_t* thread, cothread_func func)
{
    /* initialize new rbp and rsp */
    thread->regs[0] = (unsigned long)&thread->stack[STACK_SIZE];
    thread->regs[1] = (unsigned long)&thread->stack[STACK_SIZE - REG_SIZE];
    /* set function pointer for rip */
    *((unsigned long*)&thread->stack[STACK_SIZE - REG_SIZE]) = (unsigned long)func;
}

/***************************************************************/
/* test */
 
cothread_t main_thread;
cothread_t f_thread;
 
void f()
{
    int i;
    for (i = 0; ; i++)
    {
        printf("f(): %d\n", i);
        cothread_yield(&f_thread, &main_thread);
    }
}
 
int main()
{
    cothread_create(&f_thread, f);
    int i;
    for (i = 0; i < 5; i++)
    {
        printf("main(): %d\n", i);
        cothread_yield(&main_thread, &f_thread);
    }
    return 0;
}


yield.x86_64.s

.text
.globl cothread_yield
// void cothread_yield(cothread_t* from, cothread_t* to);
cothread_yield:
        mov %rbp, (%rdi)        /* save current rbp */
        mov %rsp, 8(%rdi)       /* save current rsp */
        mov (%rsi), %rbp        /* load new rbp */
        mov 8(%rsi), %rsp       /* load new rsp */
        ret                     /* pop rip and jump to */


测试

$ gcc -Wall main.c yield.x86_64.s -o test

$ ./test

main(): 0

f(): 0

main(): 1

f(): 1

main(): 2

f(): 2

main(): 3

f(): 3

main(): 4

f(): 4


你可能感兴趣的:(coroutine,协程)