Page 1 of 1

Multitasking idea i wanted some feedback on

Posted: Sat Jun 07, 2008 4:45 am
by lukem95
Right.. my OS is going no where fast at the moment (stupid exams/revision/social life/ELF DLL's!), but i'm still thinking of ideas to implement when i have time.

So, i was thinking about drivers earlier, and once i get them succesfully relocated i realised that if i run them as normal tasks a large percentage of CPU time is going to be wasted while waiting for while() loops involved in hardware checks etc.

It would be a bit much to expect all the programmers making drivers to use the syscall i will implement to release the tasks time in the while loop (something like sleeptask()), so i was thinking about how i could do this in my scheduler.

If i had my scheduler check the current task was a driver, and then every n PIT IRQ's dissassemble the code being executed (say 5 instructions either way), i could analyse that and see if it was in a while() loop (or equivalent). Then the time would be released, and the when the task next comes into the scheduler (this is dependant on the priority etc) the requirements of the while() are checked before control is passed to the task. for example:

- code is dissassembled every 20 timer ticks
- the driver is discovered to be waiting for a inb() to read a certain value
- the latency for the command is taken into accound and the task is put to sleep for a certain amount of time - say half a second
- when the task is fed back into the scheduler the scheduler performs the inb() command to see if execution is ready to carry on
- if so, control is returned to the task. if not, the time to put the task to sleep is reanalysed.

Does this sound like it would work?

The possible issues i identified where:

when i while() loop is about to finish, but the scheduler cannot work this out and so puts the task to sleep, wasting time.

could put the task to sleep for far longer than was needed

Posted: Sat Jun 07, 2008 9:46 am
by iammisc
Why don't you just convert those while loops into a syscall that will put the thread to sleep until the value of a port changes or something? That will not only be faster but much more easy to properly implement. I could see major problems with your disassembly idea. Computers aren't too good at trying to figure out what things like that do. You'll have to write so many special cases and such that the work required to get it working will be way too difficult.

Posted: Sat Jun 07, 2008 11:46 am
by suthers
iammisc wrote:Why don't you just convert those while loops into a syscall that will put the thread to sleep until the value of a port changes or something? That will not only be faster but much more easy to properly implement. I could see major problems with your disassembly idea. Computers aren't too good at trying to figure out what things like that do. You'll have to write so many special cases and such that the work required to get it working will be way too difficult.
Not only that, but to actually understand what is causing the while loop to not terminate, he would require a level off reverse engineering nearly worthy off the word decompiling, which is extremely computationally expensive and hard to implement. It would be so computationally expensive that it would probably take longer to do this than to just let the loop terminate naturally.

Jules

Re: Multitasking idea i wanted some feedback on

Posted: Sat Jun 07, 2008 3:08 pm
by Brendan
Hi,

I'm tired (probably not thinking well due to lack of sleep), but have you considered a kernel API function like:

Code: Select all

waitForIO( IOport, ANDmask, result, delayTime, timeoutTime) {

    endTime = getCurrentSystemTime() + timeoutTime;
    if(delayTime >= minSleepDelayTime) {
        do {
            sleep(delayTime);
            value = inbyte(IOport) & ANDmask;
            if(value = result) return OK;
        } while (endTime < getCurrentSystemTime() );
    } else if(delayTime >= minNanoSleepDelayTime) {
        do {
            nanosleep(delayTime);
            value = inbyte(IOport) & ANDmask;
            if(value = result) return OK;
        } while (endTime < getCurrentSystemTime() );
    } else {
        do {
            asm("pause");
            value = inbyte(IOport) & ANDmask;
            if(value = result) return OK;
        } while (endTime < getCurrentSystemTime() );
    }
    return TIMEOUT;
}
The main idea is to remove the "CPL=3 -> CPL=0 -> CPL=3" context switches by doing the polling at CPL=0, but also to make it easy for device driver programmers (who are sometimes too lazy to implement things like timeouts to make sure everything doesn't lock-up when there's a hardware failure).

Note: You'd probably want three kernel API functions - one for bytes, one for words and one for dwords....

Also, sometimes wasting a little bit of CPU time for a very short delay is much better than wasting a lot more CPU time doing task switches...


Cheers,

Brendan

Posted: Sat Jun 07, 2008 11:07 pm
by bewing
Tell all the 3rd party driver creators that if they poll any IO ports, instead of using your syscall, that you will hunt them down and shoot them.

Any other method is going to require tremendous code overhead -- far more than it could possibly save.

Posted: Sun Jun 08, 2008 9:26 am
by lukem95
ah, thankyou for your feedback.

it was just an idea, shame about it uselesness.

on the plus side however, the API approach will be much easier to implement :)