CallbackChange 2.38 KB
Newer Older
Ben Avison's avatar
Ben Avison committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
Callbacks can be triggered when a SWI returns to USR mode with interrupts
enabled. (Non-transient callbacks have an additional constraint that the
SVC stack must be empty.) However, if an X SWI returns an error (and R0 is
in RAM) then there is a danger that a callback will cause the data pointed
to by R0 to be overwriten, so at some time before RISC OS 2.00, the concept
of callback postponement was introduced: if an X SWI returns to USR mode
with interrupts enabled, V set and R0 pointing to RAM, then no callbacks are
triggered, but instead the callback postpone flag is set, which also stops
callbacks being handled after interrupts. There is also some code to attempt
to ensure that callbacks are only postponed until the next SWI.

However, the execution of this is flawed: the callback postpone flag is
not cleared until the next time a *non-transient* callback is dispatched.
The only reason that this hasn't been seen more often is that there is
*another* bug, namely that the postpone flag if only set if there were
callbacks pending (either transient or non-transient) during SWI exit.
This means that between an X SWI returning V set to USR mode with interrupts
enabled and callbacks pending, and the first time after OS_SetCallBack is used
that any X or non-X SWI returns V set or clear to USR mode with interrupts
enabled and the SVC stack empty, the following holds:
* transient callbacks are handled when any SWI exits to USR mode with
  interrupts enabled irrespective of the V flag, except after the first SWI
  (the one that set the postpone flag) - plus of course, during OS_ReadLine etc;
* transient callbacks are not handled after any interrupt.

This is obviously nonsensical, so we are changing the behaviour to what we
believe is closer to the original intent:

      SWI     XThing    -> error   set Postpone
      ..
      ..      (no callbacks on interrupts)
      ..
      SWI     (X)Anything          if no error, or non-X error,
                                   clear Postpone,
                                   callbacks (if any) happen
                                   
                                   if X error, and callbacks pending
                                   then clear Postpone, callbacks happen
                                   
                                   if X error, and no callbacks pending,
                                   leave Postpone set

BA/KB  21 Feb 2003