跨线程的ucontext

时间:2010-12-14 23:10:02

标签: linux coroutine

是否允许跨线程共享上下文(由ucontext.h中的函数操纵的对象)?也就是说,我可以swapcontext第二个参数是在另一个线程的makecontext中创建的上下文吗?测试程序似乎表明这可以在Linux上运行。我无法在这方面找到文档,而Windows光纤似乎明确支持这样的用例。一般来说这样安全吗?这应该是标准的POSIX行为吗?

2 个答案:

答案 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似乎表明你不应该混合它们。