I create a process or kthread, with a thread control block that has an initial construction on stack so that it will "resume" to thread's entry and upon return it will call thread_exit(TCB*)
On 32-bit system it looks like this on the initial stack:
[TCB* tcb]
[TCB* tcb]
[thread_exit]
[thread_func]
So, upon context switch, it will "return" to thread_func, and thread_func will return to thread_exit, the interface will be:
Code: Select all
void thread_func(TCB* tcb) {
// do some stuff
}
void thread_exit(TCB* tcb) {
//...
}
However, on x86_64 the AMD ABI uses register to pass parameter, and it's not preserved across function calls.
I then come up with ugly hack that:
stack construction:
[TCB* tcb]
[thread_exit]
[thread_func]
RDI := tcb
Once context switch it successfully "return" to thread_func, and thread_func returns to thread_exit,
but to retrieve TCB* I now doing this:
Code: Select all
void kthread_test(PROCESS* process) {
for (int i=0; i<(int)process->pid; i++) {
kprintf ("KMAIN : thread(%d): %d\n", process->pid, i);
scheduler_sleep(1000);
}
}
void process_exit (void) { // PROCESS *process ) {
PROCESS *process;
__asm volatile ("pop %0" : "=A"(process) );
if ( process == NULL ) return;
process->flags |= PROCESS_FLAG_ZOMBIE;
for(;;) {
scheduler_sleep(0); // yield
}
}
PS. for simplicity I current test with PROCESS* which contain only single thread.