Tornado II support module API details:
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Note that these SWIs implement a Win32 API interface but do not provide all
the facilities Win32 does (mainly in the security area). This is not apparent
when using the module through the C veneers though.

 Tornado_Initialise						(&C0000)
 On entry:
  R0=version of support module expected * 100
  R1=ptr to name of this program instance
  R2=ptr to routine to handle poll codes 17, 18 & 19
  R3=RO Wimp task handle of this app
 On exit:
  R0=version of this support module * 100
  R1=version of RISC-OS we're running on here * 100
 Use:
   This call initialises the program instance calling it as a preemptable
multithreading multitaskable client. From this call hence the program code
will be preempted. You must already have set yourself up as a Wimp task with
Wimp_Initialise.
   NOTE: the routine for handling 17, 18 & 19 return codes is *immediately*
valid and may be started at any time - so make sure it's valid.
   Note also that on return of this call the current code becomes a thread
and other threads may be created that run alongside it. You must take account
of this before calling this call ie; be absolutely sure you're ready for it.


 Tornado_Closedown						(&C0001)
 On entry:
  R0=wimp task handle (0 for current task)
 On exit: Nothing
 Use:
   This call shuts down the program instance calling it as a preemptable
multithreading multitaskable client. Henceforth your code will NOT be
preempted. You should now exit using Wimp_CloseDown and OS_Exit and per
normal - or if you wish you can continue execution. Note that you should NOT
use Tornado_CloseDown and then Tornado_Initialise again to suspend preemption
for a while - either make your code fully preemptable or don't use this
module at all.
   All threads other than the one calling this also get terminated
*immediately*, so if they have any open file handles or memory they simply
get lost. It might be an idea to terminate all threads through (i) waiting
for them to finish using Tornado_WaitForMultipleObjects or (ii) calling
Tornado_TerminateThread which will cause an exception within the thread and
cause its error handler to be called.

 Tornado_Poll							(&C0002)
 On entry:
  R1=ptr to 256 bytes to have poll data returned into
 On exit:
  R0=wimp poll reason code
 Use:
   Use this call to fetch wimp messages sent to you by other wimp tasks,
preferably in your main thread (ie; your process thread).
   Note however that if you have not called Tornado_Poll recently that the
messages returned may be significantly out of date. Therefore you should
follow the recommendations for writing multithreading applications as
outlined in 'Guidelines'.
   Messages returned are identical in format to Wimp_Poll: except that of
the redraw window request message (1) which is returned as the following
format instead:
     +00: window handle
     +04: work area min x
     +08: work area min y
     +12: work area max x
     +16: work area max y
     +20: base x of window work area
     +24: base y of window work area
   This message upon being received should be passed to Tornado_RedrawWindow
- see its entry for details.

 Tornado_RedrawWindow						(&C0003)
 On entry:
  R1=ptr to redraw block
 On exit:
  R0=flag on whether to continue
 Use:
   This call is very similar to Wimp_UpdateWindow except that when called
preemption is halted. Tornado_GetRectangle should then be called as
necessary in the same fashion as Wimp_GetRectangle.
   As said above, preemption is halted during the redraw cycle. Therefore
you should try to make the redraw as quick as possible.
   Unlike Wimp_RedrawWindow, this call may also be called at any time to
update a window.

 Tornado_GetRectangle						(&C0004)
 On entry:
  R1=as for Wimp_GetRectangle
 On exit:
  R0 & R1 as for Wimp_GetRectangle
 Use:
   Use this call like Wimp_GetRectangle.
   
 Tornado_NeedReset						(&C0005)
 On entry: Nothing
 On exit:
  R0=zero if everything alright,
       ptr to error blk of error if reset required
 Use:
   Use this call to check if your error handler was called through an error
occuring during the execution of the tornado support module's preemption
handlers.
   If R0 returns a non zero result, you can check the error code to see what
you should do. For example, if it is a fairly transient error (eg; Not a
block) which indicates data corruption of the support module's lists then a
restart will more than likely work so you should shut yourself down using
Tornado_Closedown and restart with Tornado_Initialise. Remember to clean up
any resources left open by the forced termination of your threads (if you
can).
   A nice and very tornadoey addition to this is to ASK the user what to do -
quit or not quit (of course both save the files out where necessary).
   Finally, note that memory full errors get dealt with internally by the
preemptor routine and you should not receive these. If you do, something is
seriously wrong and you should quit rather than restart.

 Tornado_SetPollMask						(&C0006)
 On entry:
  R0=mask to be passed from hence to wimp poll
 On exit:
  R0=previous mask
 Use:
   Use this call to set what mask should be passed to Wimp_Poll when
tornado calls it for you - this obviously affects what codes then will be
returned to you via Tornado_Poll but do remember there may be a "stack" of
codes still waiting to be processed that will be unaffected by the mask
change.

 ************ THE FOLLOWING SWI'S ARE NOT CURRENTLY IMPLEMENTED ************

 Tornado_CreateThread						(&Cxxxx)
 On entry:
  R0=ptr to security attributes (N/I)
  R1=initial thread stack size in bytes or zero for default
  R2=address of thread function
  R3=argument for new thread
  R4=creation flags (N/I - leave as zero)
 On exit:
  R0 corrupted if R1=0
  R1=thread id
 Use:
   Use this call to create a thread in your code. The security attributes
and the creation flags are currently N/I and should be left as zero.
   If the thread id returned is zero then the thread create has failed.
Examine R0 which will contain the standard error block to see why.
   The thread is entered with a1 (R0) equal to R3 on entry to this
call. The thread code must return an integer which then can be retreived
using Tornado_GetExitCodeThread.

 Tornado_ExitThread						(&Cxxxx)
 On entry:
  R0=exit code
 On exit: Never returns
 Use:
   This call terminates the current thread and attachs the exit code to the
threads handle, and then marks that handle as signaled.
   This is the preferred method of ending a thread. However, the main thread
(as in the one that called Tornado_Initialise) should NOT end by this method
- instead it should call Tornado_Closedown.

 Tornado_TerminateThread					(&Cxxxx)
 On entry:
  R0=thread id
  R1=exit code to be returned by the thread
 On exit: Nothing
 Use:
   This call forcibly terminates a thread. While the thread's stack is
removed and the thread killed off, anything that the thread was doing (eg;
file work etc) will NOT be killed off and thus keep using system resources.
Therefore you should use this call with a great deal of care.

 Tornado_ReadMonotonicTime					(&Cxxxx)
 On entry: Nothing
 On exit:
  R0=low word of timer
  R1=high word of timer
 Use:
   This call returns the value of a timer incremented 1000 times a second.

 Tornado_CallAfter						(&Cxxxx)
 On entry:
  R0=time from now to call routine in ms
  R1=addr of routine
  R2=R12 on entry
 On exit: All preserved
 Use:
   This call calls the specified code in R1 after R0 milliseconds have
elapsed with R12 set to R2 on entry.
   Your code is called in supervisor mode with interrupts enabled and so you
should take the usual precautions for calling SWIs and such. Note that you
should not take time when called by this method as the system is
effectively hung while you are in this call. You may corrupt R0, R1 and R12
if you wish.

 Tornado_StopCallAfter						(&Cxxxx)
 On entry:
  R0=addr of routine
  R1=R12 on entry
 On exit: All preserved
 Used:
   This call stops the scheduled call set up by Tornado_CallAfter.



17, 18 & 19 poll code API
-=-=-=-=-=-=-=-=-=-=-=-=-

In C, your routine will be called as follows:

int routine(int msgno, int msgblk)

In assembler, this goes to:

R0=poll code number
R1=message block attached to poll code number

You should return in R0 a value to indicate what should be done with this
message - 0 causes the message to be placed in the normal message queue to be
handled by Tornado_Poll called by the main process. 1 tells tornado that the
message has been dealt with and to take no further action.

Note that any changes you make to the message block pointed to by R1 are
permanent ie; it is directly the message block that will be put in the
message queue if R0=0 on exit. This can be advantageous or not.

Note also that this routine is NOT preempted. Therefore you should be fast to
finish your business. Also be aware that your have 256 bytes of stack
available and currently no more - if you extend over that you will invoke the
C stack extender and then things will become very nasty indeed as in fact the
stack resides in 'limbo' in RMA. So *ensure* this doesn't happen.

Please see the enclosed C example for how to implement this.
