Take the 2-minute tour ×

Are contexts (the objects manipulated by functions in ucontext.h) allowed to be shared across threads? That is, can I swapcontext with the second argument being a context created in makecontext on another thread? A test program seems to show this working on Linux. I can't find documentation one way or the other on this, whereas Windows fibers appear to explicitly support such a use case. Is this safe and OK to do in general? Is it standard POSIX behavior that this should work?

share|improve this question
Can you post your test program as well, here? –  vpit3833 Mar 25 '11 at 23:05

2 Answers 2

Actually, there was an NGPT - threading library for linux, which uses not a current 1:1 threading model (each user thread is the kernel thread or LWP), but a M:N threading model (several user threads corresponds to another, smaller number of kernel threads).

According to ftp://ftp.uni-duisburg.de/Linux/NGPT/ngpt-0.9.4.tar.gz/ngpt-0.9.4/pth_sched.c:170 pth_scheduler it was possible of moving user thread contexts between native (kernel) threads:

         * See if the thread is unbound...
         * Break out and schedule if so...
        if (current->boundnative == 0)
         * See if the thread is bound to a different native thread...
         * Break out and schedule if not...
        if (current->boundnative == this_sched->lastrannative)

To save and restore user threads, the ucontext can be used ftp://ftp.uni-duisburg.de/Linux/NGPT/ngpt-0.9.4.tar.gz/ngpt-0.9.4/pth_mctx.c:64 and seems this was a preferred method (mcsc):

 * save the current machine context
#if PTH_MCTX_MTH(mcsc)
#define pth_mctx_save(mctx) \
        ( (mctx)->error = errno, \
          getcontext(&(mctx)->uc) )
 * 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)

 * 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.

So, even if NGPT is dead and unused, it selected *context() for switching user threads even between kernel threads. I assume, that using *context() family is safe enough on Linux.

There can be some problems when mixing ucontexts and other native threads library. I will consider a NPTL, which is standard linux native threading library since glibc 2.4. The main problem is THREAD_SELF - pointer to struct pthread of the current thread. TLS (Thread-local storage) also works via THREAD_SELF. The THREAD_SELF is usually stored on register (r2 on powerpc, %gs on x86, etc). get/setcontext might save and restore this register breaking internals of native pthread library (e.g. thread-local storage, thread identification, etc).

The glibc setcontext will not save/restore %gs register to be compatible with 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

You should check, does setcontext saves THREAD_SELF register on the architecture you are interested in. Also, your code can be not portable between OSes and libcs.

share|improve this answer
Not entirely satisfactory, but I guess it's the best info you can have around. Thanks. –  Flavio Jul 14 '11 at 8:09

From the man page

In a System V-like environment, one has the type ucontext_t defined in and the four functions getcontext(2), setcontext(2), makecontext() and swapcontext() that allow user-level context switching between multiple threads of control within a process.

Sounds like that's what it's for.

EDIT: although this discussion seems to indicate that you shouldn't be mixing them.

share|improve this answer
No. This says about "threads of control", the threads which are saved and restored by *context(). It says nothing about mixing *context() functions and pthreads. –  osgx Jul 8 '11 at 7:47
Is the Solaris discussion helpful? Why on earth do you want to do this anyway? Threading is slippery enough as it is without mixing up thread definitions. –  spraff Jul 8 '11 at 7:55
Its not for me. Native threads can be enough to plain C, but not enough for 1) coroutines, e.g. in Go, etc 2) languages with green threads, e.g. Ruby/Python –  osgx Jul 8 '11 at 8:15

Your Answer


