setjmp / longjmp 实现的?
xhawk18 opened this issue · 8 comments
longjmp 只有栈顶向栈底跳才是安全的,而且某些平台下不排除析构对象(例如windows),慎重使用
longjmp 只有栈顶向栈底跳才是安全的,而且某些平台下不排除析构对象(例如windows),慎重使用
你说的对,但这里的setjmp/longjmp只用于跨Task的上下文(不同栈之间)切换,不涉及同一个栈的不同帧之间切换,所以是安全的。
之前搞过一版基于longjmp的,
https://github.com/xhawk18/s_task/tree/ac7046e5b872911a0625920fdf2d2f44cde4828a
实现方式确实为 ”同一个栈“,在同一个栈上,通过定义个大数组变量保留出空间,
然后将这个空间当作子任务的 "栈”,longjmp就在这些栈上挑来挑去。
好处是一点汇编都没有,坏处就是visual studio下测不通过,stm8下也不太稳定。
后来没深究windows下栈的原理,直接放弃了这个方案,改成汇编切换context了。
之前搞过一版基于longjmp的,
https://github.com/xhawk18/s_task/tree/ac7046e5b872911a0625920fdf2d2f44cde4828a实现方式确实为 ”同一个栈“,在同一个栈上,通过定义个大数组变量保留出空间,
然后将这个空间当作子任务的 "栈”,longjmp就在这些栈上挑来挑去。好处是一点汇编都没有,坏处就是visual studio下测不通过,stm8下也不太稳定。
后来没深究windows下栈的原理,直接放弃了这个方案,改成汇编切换context了。
如果大数组空分复用作为每个Task的栈,虽然地址空间上是连续的,但仍然应该视为多个独立的Task栈,这种情况下如果出现问题的可能应该是栈溢出,导致覆盖了其它Task的栈中数据。
调试验证的话可以再调大每个Task的栈空间,或使用mmap来分配这个“大数组”,并且在每个Task栈空间中使用PROT_NONE的一个或多个页间隔,这样触发溢出访问就能被明确的捕获到。
之前搞过一版基于longjmp的,
https://github.com/xhawk18/s_task/tree/ac7046e5b872911a0625920fdf2d2f44cde4828a实现方式确实为 ”同一个栈“,在同一个栈上,通过定义个大数组变量保留出空间,
然后将这个空间当作子任务的 "栈”,longjmp就在这些栈上挑来挑去。好处是一点汇编都没有,坏处就是visual studio下测不通过,stm8下也不太稳定。
后来没深究windows下栈的原理,直接放弃了这个方案,改成汇编切换context了。
我的实现是比较传统的方法,Task栈是动态分配出来的,不同Task栈地址空间上是否连续不确定,在Task首次执行时用了一点架构相关的汇编来切换栈指针,随后的上下文切换就直接利用了setjmp/longjmp。
使用大数组局部变量来划算Task栈的扩展性会不会不灵活,而且如何精确控制?
使用大数组局部变量来划算Task栈的扩展性会不会不灵活,而且如何精确控制?
感觉不太好呢,需要程序本身的栈够大,才能分配更多的栈给协程用。
改天仔细拜读下老哥的大作学习下:grinning:,看看要不要将 longjmp 的方式重新拉回来。
之前搞过一版基于longjmp的,
https://github.com/xhawk18/s_task/tree/ac7046e5b872911a0625920fdf2d2f44cde4828a
我大概看了一下代码,如果不考虑Task退出后它的栈回收与复用,看上去新的Task只能由最后创建的Task来操作,调用allocate_task()才能拿到一个空间上不重叠的栈,是吧?
实现方式确实为 ”同一个栈“,在同一个栈上,通过定义个大数组变量保留出空间,
然后将这个空间当作子任务的 "栈”,longjmp就在这些栈上挑来挑去。好处是一点汇编都没有,坏处就是visual studio下测不通过,stm8下也不太稳定。
后来没深究windows下栈的原理,直接放弃了这个方案,改成汇编切换context了。
我大概看了一下代码,如果不考虑Task退出后它的栈回收与复用,看上去新的Task只能由最后创建的Task来操作,调用allocate_task()才能拿到一个空间上不重叠的栈,是吧?
是的,分配新的空间,需要跳到最后一个分配空间的末尾
使用大数组局部变量来划算Task栈的扩展性会不会不灵活,而且如何精确控制?
感觉不太好呢,需要程序本身的栈够大,才能分配更多的栈给协程用。
改天仔细拜读下老哥的大作学习下grinning,看看要不要将 longjmp 的方式重新拉回来。
毛线大作:confused:,纯属自娱自乐吧,起初都是用EventLoop来写一些小应用,实在受不了回调了,玩起了协程化的同步方式。多交流哈。