I have issues with my scheduler. It switches the first few times until it gets back to the start, then the registers get trashed and stop working. I've tried a multitude of different ways to capture the registers and save them, but nothing I try seems to be working, so I need a little help with getting this final issue resolved. I will give a quick run-down of the code,
My scheduler is linked to my PIT, and each timer tick runs the following code:
Code: Select all
static void timer_irq0(struct registers * r) {
timer_tenths++;
if(timer_tenths > 100) {
Scheduler::next(r);
timer_tenths = 0;
}
}
Code: Select all
extern "C" struct registers * isr_handler(registers_t* registers) {
if ((registers->isr_num >= IRQ0) && (registers->isr_num <= IRQ15)) { // IRQ
if (registers->isr_num >= IRQ8) { // IRQ originated from the slave PIC
outportb(PIC2_COMMAND, PIC_EOI);
}
outportb(PIC1_COMMAND, PIC_EOI);
}
if (isr_handlers[registers->isr_num] != 0) {
isr_handlers[registers->isr_num](registers);
}
return registers;
}
The Scheduler then runs this function:
Code: Select all
void Scheduler::next(registers* r) {
if(!has_initialised) {
memcpy(&base_state, r, sizeof(registers));
has_initialised = true;
return;
}
if(!thread_list[task_idx]->ran) {
// if this is the first time the thread has been scheduled,
// we need to initialize it's state register beforehand
thread_list[task_idx]->state_reg.eflags = base_state.eflags;
thread_list[task_idx]->state_reg.cs = base_state.cs;
thread_list[task_idx]->state_reg.ss = base_state.ss;
thread_list[task_idx]->ran = true;
}
int lastThread = task_idx - 1;
if(task_idx == 0)
lastThread = thread_list.size()-1;
// save the previous threads state
if(thread_list[lastThread]->ran) {
memcpy(&(thread_list[lastThread]->state_reg), r, sizeof(registers));
}
// set the registers from the current thread's saved state
memcpy(r, &(thread_list[task_idx]->state_reg), sizeof(registers));
task_idx++;
// Loop around 0 -> 1 -> 2 -> 0 -> ...
if(task_idx >= thread_list.size()) {
task_idx = 0;
}
}
Code: Select all
class Thread {
public:
size_t thread_id;
registers state_reg;
uintptr_t entry_ptr;
bool ran;
Thread() : ran(false) {}
};
Finally, to start a thread I run this function:
Code: Select all
void start_thread(void_fn entry) {
Thread* thread = new Thread();
thread->thread_id = next_tid;
thread->entry_ptr = reinterpret_cast<uintptr_t>(entry);
thread->state_reg.eax = 0;
thread->state_reg.ebx = 0;
thread->state_reg.ecx = 0;
thread->state_reg.edx = 0;
thread->state_reg.esi = 0;
thread->state_reg.edi = 0;
thread_list.push_back(thread);
next_tid++;
}