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