[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [f-cpu] Smooth Register backup issues...



Hi #3,

Yann Guidon wrote:

We have to distinguish between interrupts and task switches.

This distinction is very important !
Well, at least it was in the beginning, because the purpose of the SRB mechanism
has been extended beyond the simple mechanismthat allows IRQs to be serviced faster.
It still is important, IMHO.

Now, it is used for task switches, IRQs and exceptions.
In each case, one must be careful not to make mistakes with the other cases.
Not all of that has to be done in hardware. We have the srb_save
and srb_restore instructions. Assuming that the instructions work in the
current context, and that the address of the CMB is stored in the
SR_CMB_PHYSICAL_ADDRESS special register, a task switch could look like
this:

# old task
srb_save
loadcons $new_cmb_address, r1
puti $SR_CMB_PHYSICAL_ADDRESS, r1
srb_restore
# new task

The only thing we really need to support in hardware is saving registers on entry of an ISR, and restoring them on RFE. This would be mostly the same for IRQs and exceptions.

An (asynchronous) interrupt will suspend the running task for a while, and
then return to it. A task switch stops the current task and start a new one. A software interrupt (e.g. system call) is similar to a hardware interrupt but will run in the context of the current task (i.e. no SRB is performed).

At least some context must be saved ! access rights (properties), PC (in case the system calls traps,
we want to be able to locate the offending call location) and PC+4 (so we return nicely).
That's probably not the task of the SRB.

When a task is created, the OS will allocate a CMB for it. When the OS
(or the CPU) switches from task A to task B, the CPU will have to save
register values to the CMB of task A and load new values from the CMB of
task B. It can do so beforehand or on an as-needed basis.

Just like "old school SRB".

With shadow
registers, it could swap register banks, trigger an SRB-SAVE for the now
invisible bank, switch CMBs and start running the new task, performing an SRB-RESTORE while it continues.

why do i see only drawbacks with shadow registers ?
except that it /may/ be a few cycles faster than "old school SRB",
there are no benefit.
Well, I do not insist. I said I *prefer* double buffering, but I do not think it's absolutely necessary.

and simply switching banks does not take into account
the pipeline that needs some synchronisation because of the *OOOC*
scheduling. If i blindly follow your description,
"late" results from the interrupted task will land in the
alternate bank, thus corrupting both the saved CMB
(which will not be complete) and the new task.
Well, of course `late' results would go to the switched-away bank, and would be saved when they have arrived. The new task would be unaffected.

If you solve this, you end up doing the same thing as "old school SRB" :
tracking whose task each register belongs and adding flags to
keep coherency. Back to the beginning.
The scheduler has to keep track of that anyway. It needs to remember when the result arrives, at which port, and to which register it is going to be written. It could also remember the bank (1 more bit).

Hardware interrupts work similar, but they usually have no task context.

well, they have no _previous_ state, it's like spawning a thread out of nothing.
That's what I meant -- the initial state is undefined, with few exceptions (e.g. the PC value will of course be known).

The kernel can also allocate a CMB if the handler is known to be recursive.

Register values of the current task will have to be saved to the task's CMB on entry, and restored when the interrupt service routine ends. With shadow registers, you can simply swap register banks - but you'll have to take care that a running SRB-SAVE for the shadow set (caused by a task switch) is finished first.

why wait ???
Because you'll clobber a `foreign' CMB otherwise.

In order to make the interrupt service routine itself interruptible, you can allocate a CMB for it and switch CMBs manually.

What do you mean with "manually" ?
Maybe I should have said "explicitly". I meant: set the new CMB's address in software, as in the example above.

Or you just turn off interrupts until the ISR finishes (provided that the ISR is short). This won't work with exceptions, however, because they may nest. Maybe they should run inside their own task context (with a pre-allocated CMB).

(that's what i said for a while).
Well, the remaining problem is that interrupt service routines must be reentrant if there is a chance that the same interrupt (or exception) occurs again before the ISR returns. Statically pre-allocated CMBs won't be sufficient in that case.


*************************************************************
To unsubscribe, send an e-mail to majordomo@seul.org with
unsubscribe f-cpu in the body. http://f-cpu.seul.org/