Page 1 of 2

Software task switch - interrupted ISR

Posted: Sun Jun 03, 2012 3:19 pm
by suslik
Hello!

There is a lot of information about software task switch, but I can't understand one thing: we store context in the timer interrupt, supposing that this is interrupted task context, but when the timer interrupt interrupts some other interrupt handler? What about this case?

Re: Software task switch - interrupted ISR

Posted: Sun Jun 03, 2012 3:54 pm
by Combuster
In many cases interrupts are prevented from nesting altogether, or operations are postponed until the last interrupt handler completes.

Re: Software task switch - interrupted ISR

Posted: Sun Jun 03, 2012 9:32 pm
by suslik
Sorry, but I don't understand your idea. In all sources, I've seen before, the timer interrupt can interrupt, for example, kbd ISR (IRQ with less priority)... and I think that it is right.

Re: Software task switch - interrupted ISR

Posted: Sun Jun 03, 2012 10:59 pm
by Combuster
Interrupts have priority over normal tasks. The scheduler deals with normal tasks, therefore executing interrupts should have some priority over the scheduler as well.

Specifically you do not want a task switch out of an interrupt handler, because it means that that interrupt, and any lower-priority ones will only be serviced when the original task is run again, which can result in several IRQs being missed.

Re: Software task switch - interrupted ISR

Posted: Sun Jun 03, 2012 11:51 pm
by suslik
OK, but I again miss a main idea. I'll try to explain what I want to understand:
suppose, I have a routine void switch_task(struct task *next_task) and global variable struct task *current_task. switch_task() do a software context switch from current_task to the next_task and can be invoked from: timer ISR (when the task time slice is expired), system call ISR (syscalls: sleep, exit, wait, yield). So, I wonder what can I do when timer ISR interrupts not task but some other ISR (for example, keyboard ISR)?

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 12:38 am
by Combuster
suslik wrote:So, I wonder what can I do when timer ISR interrupts not task but some other ISR (for example, keyboard ISR)?
In many cases interrupts are prevented from nesting altogether, or operations are postponed until the last interrupt handler completes.
Same question, same answer. I'm at work so I can't just post a pageful to cover any lack of understanding or reading skills you might have.

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 1:14 am
by rdos
You could keep a variable (counter) in the scheduler for the number of nested IRQs. Whenever an ISR is entered, you increase it, and enable interrupts. When the ISR exists, it disables interrupts and decrease the counter. The scheduler will then check this variable when doing context switches, and if it is non-zero, it will not switch task. You probably need to combine it with a function to do delayed context switches when the last IRQ exists. I also combine this function with doing wakeups of tasks from IRQs.

Alternatively, you never enable interrupts in ISRs. Then no other IRQs can fire.

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 1:36 am
by bluemoon
If you have kernel stack per thread (which is easier but not the best design), you can invoke scheduler at any place, then you just need to disable interrupt when performing switch:

Code: Select all

pushf
cli
save state (with flags before cli)
pick next
load state (interrupt flag restored for new process)

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 2:18 am
by rdos
bluemoon wrote:If you have kernel stack per thread (which is easier but not the best design), you can invoke scheduler at any place, then you just need to disable interrupt when performing switch:

Code: Select all

pushf
cli
save state (with flags before cli)
pick next
load state (interrupt flag restored for new process)
To disable IRQs in the (possibly) nested IRQ does no good. If any IRQs can run with interrupts enabled, your task-switch IRQ might happen during that time, and then you will switch-away from the IRQ that happened in the old thread.

BTW. I use one kernel stack per thread.

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 2:44 am
by suslik
OK, I think to make something like this:

Code: Select all

ISR:
cli
...
sti
iret
is not good, since when ISR is time consuming I lose some timer interrupts. And timer interrupt can occure right before cli in ISR beginning (or it can not?).

I know nothing about "one kernel stack per task", but before I begin to study this technique I want to understand how others implements "software context switch with kernel stack per each task". I've seen Simplix OS sources and realized that the moment of interrupted ISR by timer interrupt is not clear for me.

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 2:54 am
by rdos
suslik wrote:OK, I think to make something like this:

Code: Select all

ISR:
cli
...
sti
iret
is not good, since when ISR is time consuming I lose some timer interrupts. And timer interrupt can occure right before cli in ISR beginning (or it can not?).
This will work just as well:

Code: Select all

ISR:
...
iret
This is the "IRQs run with interrupts disabled" version. You don't need to disable interrupts at the beginning since this is normally done by the CPU (if you use the right gate-type at least), and you should end the ISR with having interrupts disabled as you don't want to build-up return addresses on your kernel stack. Part of the iret is to restore interrupt flag, so you don't need to do that at the end.
suslik wrote:I know nothing about "one kernel stack per task", but before I begin to study this technique I want to understand how others implements "software context switch with kernel stack per each task". I've seen Simplix OS sources and realized that the moment of interrupted ISR by timer interrupt is not clear for me.
The alternative (locking scheduler) looks something like this: (int_nesting starts as -1)

Code: Select all


ISR:
   add int_nesting,1
   sti
   ...
   cli
   sub int_nesting,1
   jnc isr_leave

   DoPossiblyDelayedTaskSwitch

isr_leave:
    iretd

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 3:20 am
by suslik
rdos, I forget about: "The difference between interrupt gates and trap gates is that for interrupt gates, interrupts are automatically disabled upon entry and reenabled upon IRET which restores the saved EFLAGS". I use interrupt gates in my IDT and I've belived that interrupt with greater priority interrupts one with less priority. In Simplix interrupt gates are used for hardware interrupts too, so there is no need for worrying about interrupted ISR.

I need to know if it is right to use not nested interrupts?

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 3:33 am
by Nable
> jnc isr_leave
Did you mean jnz?

Also, I don't remember exactly, but add/sub instr-s don't have implicit lock. Why not inc/dec?

Ontopic: afaik, people avoid doing heavy things in hardware interrupts' handlers. Handler just adds some data to irq data queue and exits. So, you don't have to think about nested interrupts and possibility to miss some of them.

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 3:44 am
by rdos
suslik wrote:rdos, I forget about: "The difference between interrupt gates and trap gates is that for interrupt gates, interrupts are automatically disabled upon entry and reenabled upon IRET which restores the saved EFLAGS". I use interrupt gates in my IDT and I've belived that interrupt with greater priority interrupts one with less priority. In Simplix interrupt gates are used for hardware interrupts too, so there is no need for worrying about interrupted ISR.
Regardless of design, you should always use interrupt gates. Otherwise, the ISR might be switched from before you can execute cli.
suslik wrote:I need to know if it is right to use not nested interrupts?
There is no right or wrong about that. It is a design-decision that is linked to several other issues.

Some of the issues:
1. If you keep interrupts disabled, you need to keep interrupts short. That might be hard to do for complex devices that might chain each others (for instance, several PCI devices can use the same IRQ).

2. If you want to signal from ISR to some main code (lower half or kernel thread), it might be convinient to use delayed task switches, and to do the task switches as the last ISR exists. Then you need most of the code I posted above anyway.

The thing is that the requirement to keep ISRs short leads to offloading things from the ISR to mainline code, which will require some kind of locking of the scheduler, and some kind of IRQ-status / delayed scheduling.

Re: Software task switch - interrupted ISR

Posted: Mon Jun 04, 2012 3:51 am
by rdos
Nable wrote:> jnc isr_leave
Did you mean jnz?

Also, I don't remember exactly, but add/sub instr-s don't have implicit lock. Why not inc/dec?
Because inc/dec don't update flags.

Also, for an SMP-approach, the code need to be revised. The scheduler lock should be per CPU, not per system, so there is a need to find the address of the current CPU, and then do the add/sub within that memory block. There is no need for multiporocessor locks in my implementation as the scheduler lock is per CPU, and is never accessed by other CPUs. Other implementations might need the lock.
Nable wrote:Ontopic: afaik, people avoid doing heavy things in hardware interrupts' handlers. Handler just adds some data to irq data queue and exits. So, you don't have to think about nested interrupts and possibility to miss some of them.
But if you want that data to be promptly handled, you need to activate the lower half, kernel thread or handler procedure, which needs to involve the scheduler. You just can't iret back to the original thread that might do some low-priority stuff unrelated to the IRQ.