Showing changes from revision #5 to #6:
Added | Removed | Changed
The kernel is responsible for the overall control of the Operating System. Extra functionality is provided by modules. Each module is responsible for a handling a specific task, such as font handing, filer windows and sound scheduling. The end result is a modular Operating System that can be easily developed, updated and extended.
Unlike modules, the kernel cannot be altered in any way. However, RISC OS does provide a method of allowing certain key routines used by the kernel to be changed or replaced. This is achieved by use of software vectors, or vectors for short.
When an ordinary SWI instruction is issued, RISC OS must determine which routine is requested. It does this by looking up the address of the SWI routine, and then branching to it, thereby running the routine. However, if the SWI instruction issued has a corresponding software vector (known as a vectored SWI), the required address is returned from the vector. Normally this would return the address of the standard SWI routine, although this can be altered.
By changing the address of a vectored SWI, this is called claiming a vector, To claim a vector, you use OS_Claim.
As detailed above, vectors store the address of the vectored SWI routine. This address is used by the kernel to determine which routine should be called. However, instead of just replacing an address, it is possible for multiple addresses to be added to a vector. In summary:
If your routine completely replaces the standard routine, then it is deemed to interpret the call, otherwise it is known to pass on the call.
A vector can be claimed by any application resulting in multiple addresses being added to a vector. This means your routine can:
To claim a vector, you use OS_Claim. This SWI actually removes any identical earlier instances of the routine from the list of addresses. If this is not desired, then it is possible to simply add an address to the list by using OS_AddToVector.
Any routine that uses a vector must use the same registers as the default routine for both entry and exit conditions.
If your routine passes the call on, you can deliberately alter some of the registers values to change the effect of the call, however, you must arrange for control to return to your routine again to restore to those that the original routine would have returned. It should then return control back to the calling program.
To remove a routine from the list of those that claim a vector, use OS_Release.
There are some vectors that must not be intercepted, that is, to completely replace the standard routine. This is because the standard routine (also known as the default owner), might perform an important action that must executed. A good example of this is the ErrorV? vector, which be default calls the error handler. If this vector was to be intercepted, then the error handler would never be called, and thus never dealt with.
RISC OS is a co-operative multitasking Operating System, that is, where each application is written to pass control back to the Window Manager after it has done what it needed to do. When multiple tasks are running concurrently, the application memory of the active task is mapped into memory at &8000. When the next application is to assume control, the current task is mapped out of memory, and the new application is mapped into the same space (at &8000).
Because of this process, any application that claims a vector, must release the vector each time it is mapped out of application space, and then reclaim it again when mapped back in. This is achieved by two SWIs:
Like normal SWIs, routines using most of the vectors can return errors by setting the V flag, and making R0 point to an error block.
However, when generating an error inside a vector routine, the routine must intercept the call instead of passing it on. This is to prevent other routines in the vector chain from malfunctioning; for example if R0 was being used as an argument for the vector call then the other claimants won’t be able to cope with the fact that it’s now an error pointer.
Note that some vectors (such as those involving IRQ calls) should never be made to return errors, as there is nowhere sensible for the error to be sent to.
The processor mode used by the routine depends on the vector:
If you call a SWI from a routine that is in SVC mode you will corrupt the return address held in R14. Therefore your routine should use the full, descending stack address by R13 to save R14 first.
If your routine will entered in IRQ mode, then further restrictions apply. These are detailed in full within the Interrupts and handling them?.
When returning from a vectored routine, the method differs depending on whether the vector is intercepted or whether you are passing on the call. The methods are shows below:
Passing on the call | Return by copying R14 into the Program counter |
Intercepting the call | Pull an exit address from the stack and jump to it |
There are many different software vectors available. The complete list is available here.