Page 1 of 1

Multiple thread switching issue

Posted: Wed Mar 29, 2017 2:44 pm
by prasoc
Hi all,

I have been implementing a thread system and am implementing a VERY basic time slicing algorithm to start. I have been having issues with the instruction pointer being corrupted after a few cycles.
It switches between two separate threads (which are essentially just an address to a function located in the kernel) but after a few switches, my eip register gets corrupt and manages to take one thread out. The other one seems to be stable, so it's very confusing as to why only a single thread has this issue.

Here is the basic outline of my code, a few lines removed for clarity:

Code: Select all

static int cTask = 0;
std::vector<Thread *> thread_list;

void schedule_next(registers * r) {
    if(cTask == 0) {
        if(thread_list[thread_list.size()-1]->ran) 
            thread_list[thread_list.size()-1]->eip = r->eip;
    } else {
        thread_list[cTask-1]->eip = r->eip;
    }

    thread_list[cTask]->ran = true;

    r->eip = thread_list[cTask]->eip;
    cTask++;

    if(cTask >= thread_list.size()) {
        cTask = 0;
    }
}
This function is called in my timer interrupt every 10 ticks (which is where the "register * r" parameter comes from)

Is this the direction that I need to take for thread switching?

-----

Here are my thread functions, purely for clarity's sake:

Code: Select all

static void test_thread() {
	for(;;) {
		BochsConsolePrintChar('a');
	}
}

static void test_thread2() {
	for(;;) {
		BochsConsolePrintChar('b');
	}
}
so just saving "eip" should be enough for how simple the functions are

Re: Multiple thread switching issue

Posted: Wed Mar 29, 2017 3:33 pm
by Korona
Err, what makes you think that only EIP needs to be saved? The compiler will surely generate code that uses other registers and unless your debugging function is completely inlined it will manipulate your stack. EIP then gets corrupted on function return. You need to save all GPRs.

Re: Multiple thread switching issue

Posted: Thu Mar 30, 2017 4:50 am
by prasoc
Of course, now it makes more sense. I thought that such simple functions wouldn't need registers, as it's an infinite for(;;) loop calling a #define function. Turns out that the definition of BochsConsolePrintChar() makes use of one of my IO functions "outb". This would explain the value of my trashed EIP being 0xE9, as that is one of the parameters passed through to my outb() call. I will see what improving my register save code does to switching.

Thanks for the quick reply
prasoc

Re: Multiple thread switching issue

Posted: Thu Mar 30, 2017 7:13 am
by prasoc
It seems to be mostly functional now, great help! When my scheduler gets initialized, I save a copy of the registers and copy them to each thread. From there, I can switch the registers according to what the thread vector element stores

edit: after running the scheduler for 30 minutes with no issues, i'm sure that it's stable enough to build upon :)