h6. [[RTSupport]] h6(. » [[RTSupport SWI Calls|SWI Calls]] h6((. » RT_Register h2. RT_Register h5. (SWI &575C0) Register a routine with the RTSupport module |_<^{width:4em}. Entry | | | R0 | flags (reserved, should be zero) | | R1 | pointer to default entry point for routine | | R2 | handle to pass in R0 to routine | | R3 | handle to pass in R12 to routine | | R4 | default pointer to pollword for routine | | R5 | initial value of R10 for routine | | R6 | initial value of R13_sys for routine | | R7 | initial priority for routine: integer between 1-255, or a pointer to a string | |_<^{width:4em}. Exit | | | R0 | RTSupport module's handle for this routine | | - | All other registers are preserved | Interrupts * Interrupts are disabled * Fast interrupts are enabled Processor Mode * Processor is in SVC mode Re-entrancy * SWI is re-entrant h4. Use This SWI adds a new routine to the list of routines to potentially be executed each time the interrupt dispatcher is unthreaded (but before transient and non-transient callbacks are executed, if the dispatcher is returning to USR mode). Each routine remains registered until removed by a call to RT_Deregister, but it may sleep for a time by use of a pollword. It is recommended that if it is known that a routine will sleep for an extended time, that a Deregister/Register pair should be used instead, to reduce cache thrashing during interrupt handling (when the RTSupport module has to check all possible pollwords). Each time the RTSupport module gains control of the CPU, it scans its list of routines in decreasing priority order for routines that are unblocked (ie where the pollword is non-zero). If a real-time routine was interrupted, then routines of a higher priority are executed, followed by the interrupted routine, and then equal and lower priority routines are examined. (However, note that if and only if routines have their priorities changed dynamically, it is possible that while a routine is executing, a second routine at the same priority level may be in a pre-empted state.) If the RTSupport module encounters two unblocked routines at the same priority level, then the calling order is undefined. The routines are called as follows: |_<^{width:4em}. Entry | | | R0 | contents of R2 when registered | | R10 | first time, this is contents of R5 when registered; subsequently, it is preserved from the previous call | | R11 | 0 (to support C code) | | R12 | contents of R3 when registered | | R13_sys | first time, this is contents of R6 when registered; subsequently, it is preserved from the previous call | | R13_svc | first time, this is the top of an 8K stack based at a megabyte boundary (the same logical address is used for all real-time routine SVC stacks, but it differs from the SVC stack address used by the foreground process); subsequently, it is preserved from the previous call | | R14_sys | return address (only needed if using the callback model) | | | SYS mode | | | First time, IRQs and FIQs enabled; | | | subsequently IRQ disable state is preserved | | | Other registers undefined | | | Static relocation offsets at base of SVC stack are undefined | |_<^{width:4em}. Exit | | |/6^. R0 | flags: | | bit 0 set => rescan all higher priority routines (for example, if this routine unblocked a semaphore that a higher priority routine may be sleeping on) otherwise rescan all equal priority routines, including this routine, before descending | | bit 1 set => R1 contains new pollword pointer (otherwise the pollword given at registration is used) | | bit 2 set => R2 contains a monotonic time after which control should be returned even if the pollword is not set | | bit 3 set => R14_sys contains the address to enter next time (otherwise the address used at registration is re-entered) | | other bits are reserved and must be zero | | R1 | pollword pointer (if R0 bit 1 is set) | | R2 | timeout monotonic time (if R0 bit 2 is set) | | R10 | value to use at next entry | | R13_sys | value to use at next entry | | R13_svc | value to use at next entry | | R14_sys | next entry point (if R0 bit 3 is set) | | | SYS mode, IRQs enabled or disabled, FIQs enabled | | | SVC stack may be non-empty | | | Processor flags, R1-R9 (except where used to return parameters), R11, R12 and R14_svc may be corrupted | So for example the routine may be implemented as * Assembler, with the static data referenced using R12 as is conventional in RISC OS. * C code interfaced directly, as long as R10 and R13_sys are set up to describe a standard stack chunk with the reserved words at its base set up to enable static data relocation, for example by copying them from the base of the SVC stack prior to the RT_Register call: <pre> _kernel_stack_chunk *chunk = calloc(1, CHUNK_SIZE); chunk->sc_mark = 0xF60690FF; chunk->sc_size = CHUNK_SIZE; memcpy(chunk + 1, _kernel_current_stack_chunk() + 1, 28); _kernel_swi_regs r = { /* ... */ .r[5] = ((int) chunk) + 560, .r[6] = ((int) chunk) + CHUNK_SIZE, /* ... */ }; _kernel_swi(RT_Register, &r, &r); </pre> Here is an example callback-model routine written in C that repeatedly sleeps for a second at a time (assuming the default pollword is never set): <pre> typedef struct { unsigned int flags; unsigned int *pollword; unsigned int timeout; } routine_result_t; __value_in_regs routine_result_t MyRoutine(void *r0) { unsigned int time; _swix(OS_ReadMonotonicTime, _OUT(0), &time); return (routine_result_t) { 1 << 2, NULL, time + 100 }; } </pre> * <notextile>C code interfaced via a veneer: if you want to be able to call _kernel_raise_error() and functions which rely upon it like exit(), abort() and assert(), which assume the outermost stack frame was called as a function returning a _kernel_oserror *, or for use as a threading library where actions need to be taken when the thread exits (eg unblocking joining threads) you will need an assembler veneer to the C code, to patch the r14_sys the C code sees on entry with a pointer to a suitable cleanup function.</notextile> The priority passed in R7 can be an integer from 1 (lowest priority) to 255 (highest priority). Priority 0 is reserved for the exclusive use of the foreground process. However, it is preferred that a string pointer be used instead: the string is used to look up a priority in the file RTSupport:Priorities. This enables easy tuning of priority levels for a given system, without the need for each real-time component to be individually configurable. For example, the file might be as follows: <pre> Critical:224 AudioFill:192 VideoPaint:160 Normal:128 AudioDecode:96 VideoDecode:64 Coroutine:32 </pre> h4. Notes If the routines pollword is nonzero at the time the routine is registered, and the routine is at a higher priority than the current context, then RT_Register will attempt to yield to the routine straight away. This also opens up the possibility for the routine to deregister itself before the RT_Register call returns. h4. See also * [[RT_Deregister]]