Question

In the OS X pthreads implementation (http://www.opensource.apple.com/source/Libc/Libc-825.26/pthreads/thread_setup.c?txt) they provide a fake return address on the thread stack (line 140):

    ts->rip = (uintptr_t) routine;

    /*
    ** We need to simulate a 16-byte aligned stack frame as if we had
    ** executed a call instruction. The stack should already be aligned
    ** before it comes to us and we don't need to push any arguments,
    ** so we shouldn't need to change it.
    */

    ts->rdi = (uintptr_t) thread;   /* argument to function */
    *--sp = 0;            /* fake return address */
    ts->rsp = (uintptr_t) sp;   /* set stack pointer */

I do not understand how this will not crash with an illegal instruction/segfault when the function that the thread is executing calls 'ret' and pops that return address from the stack. Can anyone explain how this is prevented/handled?

Was it helpful?

Solution

Without looking at the rest of the code, I can only venture a guess. My intuition says, the called thread procedure (the user-supplied start_routine parameter) should never return to the calling function.

Think about it: if the new thread did return, you would have two threads running over the same original code path. I imagine that the thread function that is actually called is a wrapper that calls the user-supplied start_routine. When the start_routine returns, the wrapper then calls pthread_exit.

(main thread)
     v
pthread_create
     v
thread_setup  (sets up stack), and spawns new thread
     v                                     |
return to main thread                      |
                                           |
                                           |
                                           v
                                      wrapper_function
                                           v
                    user-supplied    start_routine
                                           |   (returns)
                                           v
                                wrapper_function  calls
                                           v
                                     pthread_exit

Again, this is just a guess, but the whole point is, the new thread should never return to the code that called pthread_create. The purpose of the wrapper then would be to ensure that pthread_exit gets called.

I would have to see what they are passing as routine to thread_setup.

My feelings are confirmed by the fact that you don't have to call pthread_exit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top