是否允许跨线程共享上下文(由ucontext.h
中的函数操纵的对象)?也就是说,我可以swapcontext
第二个参数是在另一个线程的makecontext
中创建的上下文吗?测试程序似乎表明这可以在Linux上运行。我无法在这方面找到文档,而Windows光纤似乎明确支持这样的用例。一般来说这样安全吗?这应该是标准的POSIX行为吗?
答案 0 :(得分:6)
实际上,有一个NGPT - 用于linux的线程库,它不使用当前的1:1线程模型(每个用户线程是内核线程或LWP),而是一个M:N线程模型(几个用户线程对应于另一个,内核线程数量较少)。
根据ftp://ftp.uni-duisburg.de/Linux/NGPT/ngpt-0.9.4.tar.gz/ngpt-0.9.4/pth_sched.c:170 pth_scheduler,可以在本机(内核)线程之间移动用户线程上下文:
/*
* See if the thread is unbound...
* Break out and schedule if so...
*/
if (current->boundnative == 0)
break;
/*
* See if the thread is bound to a different native thread...
* Break out and schedule if not...
*/
if (current->boundnative == this_sched->lastrannative)
break;
要保存和恢复用户线程,可以使用ucontext ftp://ftp.uni-duisburg.de/Linux/NGPT/ngpt-0.9.4.tar.gz/ngpt-0.9.4/pth_mctx.c:64,这似乎是首选方法(mcsc
):
/*
* save the current machine context
*/
#if PTH_MCTX_MTH(mcsc)
#define pth_mctx_save(mctx) \
( (mctx)->error = errno, \
getcontext(&(mctx)->uc) )
#elif
....
/*
* restore the current machine context
* (at the location of the old context)
*/
#if PTH_MCTX_MTH(mcsc)
#define pth_mctx_restore(mctx) \
( errno = (mctx)->error, \
(void)setcontext(&(mctx)->uc) )
#elif PTH_MCTX_MTH(sjlj)
...
#if PTH_MCTX_MTH(mcsc)
/*
* VARIANT 1: THE STANDARDIZED SVR4/SUSv2 APPROACH
*
* This is the preferred variant, because it uses the standardized
* SVR4/SUSv2 makecontext(2) and friends which is a facility intended
* for user-space context switching. The thread creation therefore is
* straight-foreward.
*/
因此,即使NGPT已经死亡和未使用,它也会选择* context()来切换用户线程,甚至在内核线程之间。我假设,使用* context()系列在Linux上足够安全。
混合ucontexts和其他本机线程库时可能会出现一些问题。我将考虑一个NPTL,它是自glibc 2.4以来的标准linux本机线程库。主要问题是THREAD_SELF - 指向当前线程的struct pthread
的指针。 TLS(线程本地存储)也可以通过THREAD_SELF工作。 THREAD_SELF通常存储在x86上的寄存器(r2 on powerpc,%gs
等)上。 get / setcontext可以保存和恢复这个寄存器,打破本机pthread库的内部(例如线程本地存储,线程识别等)。
glibc setcontext will not save/restore %gs
register与pthreads兼容:
/* Restore the FS segment register. We don't touch the GS register
since it is used for threads. */
movl oFS(%eax), %ecx
movw %cx, %fs
您应该检查,setcontext是否在您感兴趣的体系结构上保存了THREAD_SELF寄存器。此外,您的代码无法在操作系统和libc
之间移植。
答案 1 :(得分:0)
来自man page
在类似System V的环境中,一个 具有在中定义的类型ucontext_t 和四个功能 getcontext(2),setcontext(2), makecontext()和swapcontext()那个 允许用户级上下文切换 在多个控制线程之间 在一个过程中。
听起来就是这样。
编辑:虽然this discussion似乎表明你不应该混合它们。