思科VPP系列专题十:协程模型

2023-11-29 13:59:52 浏览数 (1)

目录

  1. 向量图的绘制
  2. 协程模型
  3. 节点调度模型

协程的概念

维基百科是这样定义的

协程(英语:coroutine)是计算机程序的一类组件,推广了协作式多任务的子例程,允许执行被挂起与被恢复。相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。协程更适合于用来实现彼此熟悉的程序组件,如协作式多任务、异常处理、事件循环、迭代器、无限列表和管道。

协程有多种语言的实现方式,对于C语言来说,C标准库里有“非局部跳转”函数setjmp和longjmp,它们分别保存和恢复:栈指针、程序计数器、被调用者保存的寄存器和ABI要求的任何其他内部状态。

VPP协程模型

VPP的协程便是由setjmp/longjmp实现。使用longjmp/setjmp的轻量级多任务协程,由应用进程自行进行调度,不受操作系统调度机制的影响,上下文切换只损耗调用longjmp/setjmp的时间。

代码使用汇编编写,只关注一下对应的API接口,

clib_longjmp_t 保存CPU寄存器状态 stack 保存堆栈信息

代码语言:javascript复制
/* Return given value to saved context. */
跳转到setjmp设置点,reurn_value 就是跳转到clib—setjmp返回数值
void clib_longjmp (clib_longjmp_t * save, uword return_value);

/* Save context.  Returns given value if jump is not taken;
   otherwise returns value from clib_longjmp if long jump is taken. */
   设置跳转返回点,默认返回
uword clib_setjmp (clib_longjmp_t * save, uword return_value_not_taken);

/* Call function on given stack. */
在设置的stack区中跳转,运行fuc函数,函数返回值就是func的返回值
uword clib_calljmp (uword (*func) (uword func_arg),
		    uword func_arg, void *stack);

VPP是一个多线程程序,包括main线程,worker线程,协程。协程只能由main线程调度。

协程初始化流程:

在 vlib_main_or_worker_loop 函数中 main线程 遍历process数组,调用 dispatch_process 完成对process类型node的初始化调度。

在 vlib_process_startup 函数中,设置跳转返回点,在process的栈空间调用 vlib_process_bootstrap

vlib_process_bootstrap 函数中,执行 process类型node的function, 执行完之后跳转到返回点。此时的跳转返回点见process调度状态图。

每个 VLIB_NODE_TYPE_PROCESS 类型 node的function都遵循相同的模式:

  1. 在while循环中等待事件、或者事件超时;
  2. 获取事件类型,执行不同的事件;

以上便是协程初始化调度流程。此时每个process处于挂起状态。

process调度状态图如下:

0 人点赞