Software task switch - interrupted ISR

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.
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Software task switch - interrupted ISR

Post 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?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Software task switch - interrupted ISR

Post by Combuster »

In many cases interrupts are prevented from nesting altogether, or operations are postponed until the last interrupt handler completes.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Re: Software task switch - interrupted ISR

Post 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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Software task switch - interrupted ISR

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Re: Software task switch - interrupted ISR

Post 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)?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Software task switch - interrupted ISR

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

Re: Software task switch - interrupted ISR

Post 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.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Software task switch - interrupted ISR

Post 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)
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

Re: Software task switch - interrupted ISR

Post 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.
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Re: Software task switch - interrupted ISR

Post 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.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

Re: Software task switch - interrupted ISR

Post 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
suslik
Member
Member
Posts: 45
Joined: Sun May 27, 2012 1:00 am
Location: Russia

Re: Software task switch - interrupted ISR

Post 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?
Nable
Member
Member
Posts: 453
Joined: Tue Nov 08, 2011 11:35 am

Re: Software task switch - interrupted ISR

Post 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.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

Re: Software task switch - interrupted ISR

Post 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.
rdos
Member
Member
Posts: 3307
Joined: Wed Oct 01, 2008 1:55 pm

Re: Software task switch - interrupted ISR

Post 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.
Last edited by rdos on Mon Jun 04, 2012 3:52 am, edited 1 time in total.
Post Reply