Skip to content

yuchangyuan/naive_coroutine_implementation_on_picorv32

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A naive coroutine implementation on picorv32

intro

coroutine

  • a switchable task
  • need manually switch

picorv32

A pico 32bit RISC-V core

coroutine API

what we need

  • init/create a coroutine
    • for main function, we init as 1st exist coroutine
    • for other coroutine, we need to create
  • switch context: yield
  • exit coroutine

switch context: implementation of yield function

3 step

  • save context
  • find next coroutine to execute
  • restore context

save context: what

  • register: all callee saved register in ABI need to save, besides return address ra
  • stack: not save, just use different stack for different coroutine
nameABI MnemonicMeaningPreserved across calls?
x0zerozero- (immutable)
x1rareturn addressno
x2spstack pointeryes
x3gpglobal pointer- (unallocatable)
x4tpthread pointer- (unallocatable)
x5-x7t0-t2temporary registersno
x8-x9s0-s1callee-saved registersyes
x10-x17a0-a7argument registersno
x18-x27s2-s11callee-saved registersyes
x28-x31t3-t6temporary registersno

save context: where

global variable

typedef struct _nc_ctx_t {
    uintptr_t ra;
    uintptr_t sp;
    uintptr_t s[12];
} nc_ctx_t;

find next task

  • as naive implementation, chain all coroutine with linked list, form a ring
  • merged into struct _nc_ctx_t
  • define a global variable, point to current context: _curr
typedef struct _nc_ctx_t {
    struct _nc_ctx_t *next;
    uintptr_t ra;
    uintptr_t sp;
    uintptr_t s[12];
} nc_ctx_t;

nc_ctx_t *_curr;

restore context

  • restore ra, sp & s[12] from new _curr
  • jump to address ra, with instruction ret
    • alternative: restore _curr->ra to other reg, then jump

implementation

nc_yield

  • naked function
  • need some special handling, see next sections

init/create a coroutine

init, for main coroutine

  • define a static context: _main_ctx
  • init _main_ctx, point _main_ctx.next to self
  • set init value of _curr
static nc_ctx_t _main_ctx = {
    .next = &_main_ctx;
};

nc_ctx_t *_curr = &_main_ctx;

create a coroutine: nc_new

nc_new: 3 arguments

  • func: function pointer as main body of new coroutine
  • ctx: context variable, a pointer global/static variable
  • stack_top: pointer to stack top

nc_new: 2 views

  • caller: view of nc_yield,
    • which called from other coroutine to switch to ctx
    • as if a previous nc_yield is called just before the beginning of func
  • callee: view of func
    • which jump from nc_yield called by previous coroutine
    • as regular call to func by caller function

nc_new: how

review the last step of nc_yield

  • set sp of context to stack_top
  • set ra of context to func
  • add this context as next element of coroutine list
  • ra need special handle, see next section
ctx->sp = (uintptr_t)stack_top;
ctx->ra = (uintptr_t)func;

ctx->next = _curr->next;
_curr->next = ctx;

exit coroutine

what happen when coroutine function return?

  • jump to initial value of ra at beginning of coroutine function
  • which point to beginning of coroutine function

special handle ra

  • old ra for target address when exit from nc_yield
  • new ra for actual value that ra register should restore
  • setup new ra when initial context, to specify where to jump when coroutine exit
  • set old ra to the beginning of coroutine function
typedef struct _nc_ctx_t {
    struct _nc_ctx_t *next;
    uintptr_t ra_old;
    uintptr_t sp_old;
    uintptr_t s_old[12];

    uintptr_t ra_new;
} nc_ctx_t;

finalize function

  • set finalize function to ra_new when create coroutine
  • remove current coroutine context from linked list

full implementation

  • file:./src/nc.h
  • file:./src/nc.c

test

picorv32 simulation environment

file:./run_c_snippet_on_picorv32

single task example

file:./test/t1.c

3 task example

file:./test/t2.c

reference

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published