Implementing 'yield()' by faking hardware interrupt.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
skeen
Member
Member
Posts: 59
Joined: Tue Sep 27, 2011 6:45 am
Location: Denmark

Implementing 'yield()' by faking hardware interrupt.

Post by skeen »

First of all; This question is asked out of curiosity.

My kernel currently schedules tasks on the PIT interrupt (IRQ0).
Which issues would there be in causing a software interrupt on IRQ0, in order to implement yield?
// Skeen
// Developing a yet unnamed microkernel in C++14.
User avatar
Nessphoro
Member
Member
Posts: 308
Joined: Sat Apr 30, 2011 12:50 am

Re: Implementing 'yield()' by faking hardware interrupt.

Post by Nessphoro »

Your code will expect that when an IRQ happens it needs to send an end-of-interrupt, which might have some issues.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Implementing 'yield()' by faking hardware interrupt.

Post by Brendan »

Hi,
skeen wrote:First of all; This question is asked out of curiosity.

My kernel currently schedules tasks on the PIT interrupt (IRQ0).
This is bad design. Most task switches are caused when the currently running task blocks for some reason (e.g. terminates, waits for disk IO, waits for network, waits for key press, etc); or are caused a higher priority task starting or unblocking for some reason (e.g. new task spawned, disk IO completes, network packet arrives, a key press occurs, etc). The timer is relatively unimportant, and only really exists so that when there's 2 or more "CPU bound" tasks they can share the CPU's time.

A better design would be to start implement the scheduler by writing a "switch_to_task(taskID)" function. Then write a "find_task_to_switch_to(void)" function that decides which task to switch to and calls the "switch_to_task(taskID)" function. Your timer IRQ handler would just call the "find_task_to_switch_to(void)" function (but it's not the only thing that would call this function).

Next would be a "make_current_task_block(reason)" function (that ends up calling "find_task_to_switch_to(void)"); which would be used whenever a task blocks for any reason. Then you'd have a "make_task_ready_to_run(taskID)" function that checks if the task that has become ready to run is higher priority than the currently running task and calls "switch_to_task(taskID)" if it is.
skeen wrote:Which issues would there be in causing a software interrupt on IRQ0, in order to implement yield?
It depends what other things the timer is being used for. Typically it's also used for keeping track of the current time (so the current time would be messed up), and also used to unblock tasks that have called "sleep()" (so if a task does "sleep(123)" it might only sleep for 10 seconds instead of 123 seconds).

Of course Nessphoro is also correct - the timer IRQ handler will send an EOI; and this can/will cause other IRQs to be lost. For example, a disk controller might send an IRQ to the PIC chip, and you send an unwanted EOI (from the IRQ0 handler) at the wrong time, so the PIC chip thinks you've finished handling the disk controller's IRQ when you haven't. Now the disk controller is waiting for you to handle its IRQ, and the device driver for the disk controller is waiting for the IRQ, but the IRQ got lost so they both just wait for each other forever and all disk IO grinds to a halt until the user realises the OS has locked up and resets/reboots.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Implementing 'yield()' by faking hardware interrupt.

Post by sortie »

Right, you should not send IRQs, user-space programs must not be allowed to do that because it would interfere with correct driver operation (sending EIOs, etc). Simply allocate an otherwise unused interrupt number and allow user-space to call it.
Post Reply