VSF中的PT協(xié)程是共享堆棧的嗓蘑,任務不具備自己的堆棧须肆。這種運行方式執(zhí)行效率相對較低匿乃,因為每次調(diào)用任務的時候,都會需要一層層重建堆棧豌汇。那么幢炸,是否可以簡單實現(xiàn)一個獨立堆棧的協(xié)程呢?
這里說一個很少人知道的C語言標準庫:setjmp.h瘤礁。只是提供了2個函數(shù)阳懂,setjmp和longjmp梅尤。setjmp用于保存當前的上下文(不包括r0-r4)柜思;longjmp用于回復到以前保存下的上下文,并且巷燥,使得setjmp返回指定的值赡盘。所以,以下是死循環(huán):
jmp_buf pos;
setjmp(pos);
longjmp(pos, 1);
執(zhí)行到setjmp的時候缰揪,上下文記錄在pos里陨享,并且返回0。調(diào)用longjmp的時候钝腺,恢復pos里的上下文抛姑,并且從setjmp的調(diào)用指令之后執(zhí)行,R0內(nèi)容是1(模擬setjmp返回1)艳狐。
利用這個C語言標準庫定硝,就可以實現(xiàn)出一個具備獨立堆棧的協(xié)程。當然毫目,VSF里使用這個也一樣是事件驅(qū)動的蔬啡。這里就列出evt_handler和初始化函數(shù):
static struct vsfsm_state_t *
vsfsm_ljmp_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
struct vsfsm_ljmp_t *ljmp = (struct vsfsm_ljmp_t *)sm->user_data;
jmp_buf ret;
if ((evt == VSFSM_EVT_ENTER) || (evt == VSFSM_EVT_EXIT))
{
return NULL;
}
ljmp->ret = &ret;
if (!setjmp(ret))
{
if (evt == VSFSM_EVT_INIT)
{
// implement set_stack as a func is risky, may break the stack
vsfhal_core_set_stack((uint32_t)ljmp->stack);
ljmp->thread(ljmp);
}
else
{
longjmp(ljmp->pos, evt);
}
}
return NULL;
}
vsf_err_t vsfsm_ljmp_init(struct vsfsm_t *sm, struct vsfsm_ljmp_t *ljmp)
{
sm->user_data = ljmp;
sm->init_state.evt_handler = vsfsm_ljmp_evt_handler;
ljmp->sm = sm;
return vsfsm_init(sm);
}
不出意外,大部分人應該看不懂镀虐。既然是選修箱蟆,那就留作思考題吧。