|
OS_AddCallBack vs OS_CallAfter |
|
sirbod (10:58 24/4/2012) Phlamethrower (13:07 24/4/2012) sirbod (13:36 24/4/2012) Phlamethrower (22:07 24/4/2012) sirbod (06:28 25/4/2012) Phlamethrower (12:31 25/4/2012) sirbod (14:07 25/4/2012) sirbod (13:03 28/4/2012) Phlamethrower (16:56 28/4/2012) sirbod (18:05 28/4/2012) swirlythingy (15:38 24/4/2012) sirbod (16:18 24/4/2012)
|
|
Jon Abbott |
Message #120182, posted by sirbod at 10:58, 24/4/2012 |
Member
Posts: 563
|
Can someone explain the differences, in the way the code called via these should behave and what it can/can't do.
Code called via OS_AddCallBack works, but when called via OS_CallAfter it fails - it looks like its some SWI's that are failing.
Also, is there a way to force a CallBack to occur?
I have some poorly behaved games which are hammering MiscOp 1 for a disc change, not giving any time to RISC OS to service transient callbacks.
EDIT: staying in SVC and calling OS_ReadC triggers a transient callback - sometimes - but it's not elegant. Doesn't seem to be any need to call OS_SetCallBack!
The obvious one was to use call OS_SetCallBack and call OS_Byte 19 - wait for vertical sync - in USR mode, but the callback doesn't trigger.
EDIT2: inserting a character into the keyboard buffer and then calling OS_ReadC never triggers a transient callback.
[Edited by sirbod at 13:51, 24/4/2012] |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #120183, posted by Phlamethrower at 13:07, 24/4/2012, in reply to message #120182 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
It looks like there are two callback systems in place - the old callback environment handler, and the new OS_AddCallBack system for registering one-shot callbacks.
The old environment handler callback will only trigger in the following situations:- The OS is returning from a SWI to user mode with interrupts enabled
- The SWI isn't about to generate an error (i.e. no error is being returned, or it was an X SWI)
- OS_SetCallBack has been called to request a callback
- The SWI that's being returned from isn't OS_SetCallBack
- The SVC stack is empty
OS_AddCallBack callbacks will trigger only if the following conditions are met:- The OS is returning from a SWI to user mode with interrupts enabled
- The SWI isn't about to generate an error (i.e. no error is being returned, or it was an X SWI)
How this compares with OS_CallAfter and OS_CallEvery is as follows:- OS_CallAfter/OS_CallEvery routines are called from an interrupt context - they get called by the 100Hz ticker interrupt handler. Because the CPU could have been doing pretty much anything at the time, you're only allowed to use re-entrant SWIs.
- The old-style callback handler will only ever be called when the system is returning to the foreground; i.e. no SWIs are active so it's safe to call non-reentrant SWIs, or to call SWIs which will block for long amounts of time waiting for disc access.
- New-style OS_AddCallBack routines will also get called when the system is returning to the foreground. However they can also be triggered manually if code running in SVC mode switches to user mode and then calls a dummy SWI. This is useful for SVC mode code which needs to block for a long time waiting for hardware devices to respond (especially since underlying driver layers may be dependent on callbacks for some of their operation). On RISC OS 5 (or on earlier OS versions of the right version of CallASWI is loaded) the "switch to user mode and call a dummy SWI" can be implemented in one go by calling OS_LeaveOS. But the important thing to remember is the the code should only trigger callbacks in this manner if it can be sure that everything further up the call stack is aware callbacks could occur
As you've spotted there are a couple of places in the kernel where callbacks get triggered manually - but I've run out of time to track that down this lunchtime! |
|
[ Log in to reply ] |
|
Jon Abbott |
Message #120184, posted by sirbod at 13:36, 24/4/2012, in reply to message #120183 |
Member
Posts: 563
|
Thanks, that explains the problems with OS_CallAfter - which rules that route out. I'll have to find a way to reliable trigger a transient callback.
I found "OS_LeaveOS" - which seems like it might do the job (the documentation isn't specific about transients - but I don't see how it could call any other callback). It's supposed to be in CallASWI 0.03 - however SWI "OS_LeaveOS" isn't translated when CallASWI is loaded, and it doesn't trigger the transient callback!
The OS is returning from a SWI to user mode with interrupts enabled I'm not certain this is true, as I've managed to trigger it in SVC with interrupts disabled.
they can also be triggered manually if code running in SVC mode switches to user mode and then calls a dummy SWI This doesn't seem to be the case.
EDIT:OS_LeaveOS doesn't seem to return!
[Edited by sirbod at 14:57, 24/4/2012] |
|
[ Log in to reply ] |
|
Martin Bazley |
Message #120185, posted by swirlythingy at 15:38, 24/4/2012, in reply to message #120183 |
Posts: 460
|
However they can also be triggered manually if code running in SVC mode switches to user mode and then calls a dummy SWI. The classic example of such an SWI is XOS_GenerateError, which the StrongHelp manual says can be called to force a callback to occur. |
|
[ Log in to reply ] |
|
Jon Abbott |
Message #120186, posted by sirbod at 16:18, 24/4/2012, in reply to message #120185 |
Member
Posts: 563
|
XOS_GenerateError, which the StrongHelp manual says can be called to force a callback to occur. It certainly doesn't work on transients.
I've spent the best part of 8 hours trying different methods and come to conclusion you can't reliable trigger a transient callback...a glaring omission in the OS if you ask me.
I've switched the code to cancel the callback if it's not called within a second and then manually call it. This will break on physical tin, due to FileCore re-entrancy, but there's no other choice at the minute.
The only option left is to insert a handler onto the SWI vector and trigger them on exit manually. I can't face any more testing today though! |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #120188, posted by Phlamethrower at 22:07, 24/4/2012, in reply to message #120184 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
EDIT:OS_LeaveOS doesn't seem to return! Hmm, so I see! It looks like it's a blatant copy & paste error - it acts as if the kernel SWI dispatcher uses R14 to store the SPSR (as it does on 32bit OS's), so just knocks the bottom four bits off of the register. But judging by the CVS history it looks like 26bit versions of the OS have only ever used R14 for storing the 26bit PSR+return address, so it will end up corrupting the return address and often return to a point just before the SWI call! |
|
[ Log in to reply ] |
|
Jon Abbott |
Message #120189, posted by sirbod at 06:28, 25/4/2012, in reply to message #120188 |
Member
Posts: 563
|
That explains a lot!
Whilst you're there, do the later versions have the SWI translation text? 0.03 certainly doesn't, haven't managed to get hold of 0.05 to see if it's been fixed.
More to the point, will it forcibly action transient callbacks if the callback flag is set? Or do I still need to code this myself, off the SWI vector? |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #120191, posted by Phlamethrower at 12:31, 25/4/2012, in reply to message #120189 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
Whilst you're there, do the later versions have the SWI translation text? No, they don't. There's no direct way of adding it, but I guess the module could hook onto the name <---> number conversion SWIs and handle conversion of the extra SWIs itself.
More to the point, will it forcibly action transient callbacks if the callback flag is set? Or do I still need to code this myself, off the SWI vector? The SWIs return via the exit code in the kernel, the same as any other SWI. I'm not sure why you're having so much trouble triggering callbacks; are you sure you're calling the dummy SWI with interrupts enabled? I can't see any other code that would restrict when callbacks are triggered. |
|
[ Log in to reply ] |
|
Jon Abbott |
Message #120193, posted by sirbod at 14:07, 25/4/2012, in reply to message #120191 |
Member
Posts: 563
|
Here's the code I'm using. This is entered if a disc change has been pending for at least 40 entries to MiscOp 1. It's then entered on every subsequent call to MiscOp 1, if the disc change is still pending - this is several hundred times a second.
TEQ PC, PC MRSEQ R0, CPSR MOVNE R0, PC MOV R1, R0 BICEQ R0, R0, #%10001111 BICNE R0, R0, #%11 + 1<<27 MSREQ CPSR_c, R0 TEQNEP R0, #0 NOP
STMFD R13!, {R1-R2, R14} MOV R0, #19 SWI "XOS_Byte" LDMFD R13!, {R1-R2, R14}
TEQ PC, PC MSREQ CPSR_c, R1 TEQNEP R1, #0 NOP
EDIT: Obviously replace the SWI with the one of choice, I've tried XOS_GenerateError as well.
[Edited by sirbod at 15:17, 25/4/2012] |
|
[ Log in to reply ] |
|
Jon Abbott |
Message #120223, posted by sirbod at 13:03, 28/4/2012, in reply to message #120193 |
Member
Posts: 563
|
I'm hoping the lack of responses is down to my code being okay
It's not the end of the world. As ADFFS already hooks onto the SWI hardware vector, I can check for a pending callback on entry and redirect the OS exit back via my code.
I'm still curious to know why the code above does work though. |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #120225, posted by Phlamethrower at 16:56, 28/4/2012, in reply to message #120223 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
I'm hoping the lack of responses is down to my code being okay Or possibly I haven't had enough time to look into it yet (But for what it's worth, that code does look OK - hence me needing time to look into it)
I'm still curious to know why the code above does work though. I'm assuming that's a typo? |
|
[ Log in to reply ] |
|
Jon Abbott |
Message #120226, posted by sirbod at 18:05, 28/4/2012, in reply to message #120225 |
Member
Posts: 563
|
Predictive text fail! |
|
[ Log in to reply ] |
|
|