Search code examples
cmultithreadingassemblyuserland

Implementing user level threads library Starting a new thread [Homework]


I have seen this: Implementing a User-Level Threads Package and it doesn't apply.

During the implementation of Thread_new(int func(void*)), that assigns a thread and creates a stack, I am unable to think of a way to set the program counter (%eip) if I am correct, so when the thread is started by the scheduler, it starts at the given function's (func) entry point.

Although I have seen many c-only (no assembly) implementations, we have been given the following code (x86):

_thrstart:
    pushl  %edi
    call *%esi
    pushl %eax
    call Thread_exit

Is there a specific reason to push %edi to the stack? I can't seem to find another use for esi/edi apart from byte copying.

I realize that the indirect call to *%esi is probably used to call the function from the context of the new thread, but apart from that, I don't seem to understand how (or what) %esi points to being a valid function address when _thrstart is called from Thread_new

NOTES:

Thread_exit is the cleanup thread, implemented in c.

This is HOMEWORK


Solution

  • Seems that the problem wasn't as complicated as before.

    Based on the answer given by @Martin James, the Stack is prepared so that the return address is the _thrstart function. Based on the assembly used to perform a context switch, the registers edi and esi are stored in specific locations on the stack (when the thread is inactive). By using edi and esi as general purpose registers, edi contains the void* argument, and esi contains the address of the function to be called from the new thread.

    _thrstart:
    pushl  %edi        #pushes argument for function func to the stack
    call *%esi         #indirect call to func
    pushl %eax         #Expect return value in eax, push to stack
    call Thread_exit   #Call thread cleanup