在C光纤中,可以使用setjmp()
和longjmp()
进行编码,以在用户级别实现上下文切换。
如中所述
evanjones.ca和Portable Multithreading(pdf)还要求每根光纤具有新分配的堆栈。
由于光纤位于线程上下文中,因此在调用它时将自动具有与之关联的堆栈框架,那么为什么需要这个新分配的堆栈呢? :当光纤要切换到另一根光纤时,可以使用以下方法:
cpu_context[N] :global array where the i-th entry is the cpu context(jmp_buffer) of the i-th fiber
fiber_ith :
[...]
if ( setjmp(cpu_context[i]) == 0 ){
longjmp(cpu_context[j])
}
[...]
需要新堆栈的原因是,按照here的说明,不可能使用longjmp()
返回到光纤执行,该光纤执行的堆栈帧从光纤呼叫longjmp()
的瞬间?
编辑:这些光纤必须是非光纤的,并且可以自愿从一种光纤切换到另一种光纤
答案 0 :(得分:3)
假定光纤具有一个函数,该函数调用另一个函数,该函数调用另一个函数,然后该函数导致该光纤切换为另一个光纤。当我们恢复该光纤时,我们需要确保所有局部变量都恢复到光纤切换时的状态,并且需要确保从该函数返回的结果可以返回到调用函数。 因此,出现了以下规则:
根据这两个规则,每根光纤必须具有自己的堆栈。
答案 1 :(得分:1)
首先,线程无意于手动控制其自己的调度。也就是说,无意一个线程决定结束或暂停其执行并启动另一个线程。相反,线程可以同时运行,并且系统可以在不同的物理或虚拟处理器上同时运行多个线程,也可以启动和停止线程,以便它们共享处理器上的可用时间。
由于线程可以同时运行,因此它们必须具有单独的堆栈。每个线程可能会同时更改和使用其自己的堆栈,而其他线程可能同时更改并使用它们的堆栈。这些堆栈必须分开以避免冲突。
第二,setjmp
和longjmp
并非旨在跳转到线程状态下的任意点。程序只能在同一线程中使用longjmp
返回其当前调用堆栈中的上一个setjmp
。例如,您无法做一些工作,用A
记住状态setjmp
,再做一些工作,用B
记住状态setjmp
,然后再longjmp
声明A
,随后声明longjmp
声明B
。从longjmp
到A
之后,B
不再可用-setjmp
为其保存的任何内容都不再有效。