Unable to switch task via stack
Posted: Thu Sep 10, 2020 5:59 pm
Hi.
Previously, I was able to switch tasks using the stack, but I decided to completely rewrite the code and now I have problems.
I'll describe how my task switching works:
When I get an interrupt from PIT, control is passed to the first handler(isr_common_stub:) which passes control to a high-level handler (isr_handler), which causes the PIT handler(pit_handler) to call the scheduler(scheduler_switch), the scheduler(scheduler_switch) configures next_thread(this is where control should be passed), then the main function scheduler_low_thread_switch: which saves the stack of the interrupted task and loads a new stack.
So, what we have in this case: isr_common_stub -> isr_handler -> pit_handler -> scheduler_switch -> scheduler_low_thread_switch(problem here)
In this case, there is one thread in the system - the main thread of the kernel, this function should continue its execution.
(in this case, current_thread and next_thread are absolutely equal)
Ńurrent_thread uses the eax register, and next_thread uses ebx.
ecx and edx do not play any role in this case)
Offsets described here(just in case)
Its logic is very simple at the moment: first, it saves eflags and general-purpose registers, then it saves the stack of the interrupted task to the current_thread structure, then it goes to the check_kernel_init_or_continue: label, there it goes to the continue_kernel_thread: label and loads the stack, then it tries to pass control to the function using ret.
Since current_thread and next_thread are equal, the stack loaded before ret will be exactly the same as we saved earlier.
(I have previously used this function(it looks bad and so I decided to rewrite it, but it worked correctly))
Previously, I was able to switch tasks using the stack, but I decided to completely rewrite the code and now I have problems.
I'll describe how my task switching works:
When I get an interrupt from PIT, control is passed to the first handler(isr_common_stub:) which passes control to a high-level handler (isr_handler), which causes the PIT handler(pit_handler) to call the scheduler(scheduler_switch), the scheduler(scheduler_switch) configures next_thread(this is where control should be passed), then the main function scheduler_low_thread_switch: which saves the stack of the interrupted task and loads a new stack.
So, what we have in this case: isr_common_stub -> isr_handler -> pit_handler -> scheduler_switch -> scheduler_low_thread_switch(problem here)
In this case, there is one thread in the system - the main thread of the kernel, this function should continue its execution.
(in this case, current_thread and next_thread are absolutely equal)
Ńurrent_thread uses the eax register, and next_thread uses ebx.
ecx and edx do not play any role in this case)
Offsets described here(just in case)
Its logic is very simple at the moment: first, it saves eflags and general-purpose registers, then it saves the stack of the interrupted task to the current_thread structure, then it goes to the check_kernel_init_or_continue: label, there it goes to the continue_kernel_thread: label and loads the stack, then it tries to pass control to the function using ret.
Since current_thread and next_thread are equal, the stack loaded before ret will be exactly the same as we saved earlier.
(I have previously used this function(it looks bad and so I decided to rewrite it, but it worked correctly))