home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / misc / tornado / tndemo2 / _TRender < prev    next >
Text File  |  1996-05-16  |  7KB  |  139 lines

  1. Tornado renderers
  2. -=-=-=-=-=-=-=-=-
  3.    A tornado renderer provides facilities for rendering files. They are
  4. automatically called upon by the shell to render a file as it presents itself
  5. and should they not be already in memory they can be loaded in and cached by
  6. tornado during the execution of the rendition.
  7.  
  8. A tornado renderer is similar to a normal tornado extension module, except:
  9.  
  10.  (i) In it's initialise entry, it must declare itself as a renderer.
  11.  (ii) It must live in <Tornado$Renderers> rather than <Tornado$Extensions>.
  12.  (iii) It must provide all the mandatory entries as specified by the file
  13. type it is supporting [1].
  14.  (iv) It must be able to render more than one file at once [2]
  15.  (v) It must be able to render more than one part of a file at once [2]
  16.  (vi) It must be able to handle being loaded in and quitted repeatedly, and
  17. at any stage - even if that be in the middle of a rendition [3].
  18.  
  19. [1]: These entries are laid out in a list issued by me, the guy who's
  20. designing and writing all this stuff. If you want to add a filetype, you draw
  21. up a suitable addendum to the list, and email/post it to me. I review it, and
  22. if I don't like it I'll refuse it.
  23.    This leaves you with two options. (i) You can go away and improve it or
  24. (ii) you can go ahead and implement it anyway.
  25.    The first option is the correct one. The second will land you in trouble.
  26. I will hinder any developments/improvements on any filetype not approved by
  27. me. Is this not a bit arrogant? Yes, it is, but it's my operating system and
  28. I'll have it go the way *I* want it. You don't like it - go away and write
  29. your own operating system.
  30.    Anyway, there's always the general filetypes which you can extend if you
  31. wish.
  32.  
  33. [2]: In fact, this is implemented by you writing a very clever piece of code
  34. capable of being multithreaded (not fun). Tornado will handle all the hard
  35. work of getting your code to do the work, although this requires cooperation
  36. from you:
  37.  (i) You cannot use any static workspace unless you have developed some
  38. brilliant way of allowing any parts of your code to access it at any time and
  39. even while another thread of your code is in the middle of using it.
  40.  (ii) Thus, you should use dynamic workspace allocation. See below.
  41.  
  42. [3]: Ie; your renderer must be able to tidy itself and all its threads up
  43. should .finalise suddenly be called. As your renderer code may be
  44. initialised, quit, and then initialised again many times in one second, it
  45. must *not* leave any wkspace unfreed as this will obviously fill up memory
  46. very quickly.
  47.  
  48. Technical stuff:
  49. -=-=-=-=-=-=-=-=
  50.    Right, here's how tornado interfaces with your renderer:
  51.  
  52. In the tornado .initialise, you must call Tornado_RegisterRenderer, passing
  53. your details (see below for parameter block).
  54.  
  55. In the .threadinit entry, you should claim a piece of wkspace that will be
  56. enough for a thread to work with entirely if possible. However, if this
  57. is not possible (max memory that might be required is several K for each
  58. thread for example), check what the tornado config says - use more memory, or
  59. use less memory (Tornado_Config). If it says use less memory, assume that
  60. there is more CPU power available and dynamically alter the block's size
  61. during the thread's execution (even though this is a non-preemptable action
  62. and everything will be held up as a result). If it doesn't, allocate the most
  63. the thread could possibly need. Later versions of tornado may automate this
  64. regulation of memory for you later but currently it is up to you to mark what
  65. method you are following and follow it accordingly.
  66.  
  67. The .threadexec entry will be entered as follows:
  68.  R8  = undefined as yet, but can be ignored by your code (ie; overwritable)
  69.  R9  = a binary set of flags:
  70.        bits 0,1: unset
  71.        bits 2-25: reserved
  72.        bits 26-31: unset
  73.        You may overwrite these, but it is advisable you don't (see below).
  74.  R10 = a pointer to the file data you are rendering
  75.  R11 = a pointer to your thread's workspace as set up by your init routine
  76.  R12 = a pointer to the workspace of your module (should only be used for
  77. reference!)
  78.  R13 = a private stack peculiar to your thread which is empty (64 bytes long,
  79. so don't push too much onto it, and allow for routines you call to use it)
  80.  R14 = a link back to tornado when you have finished the rendition
  81.  
  82. Code is in USR mode (no need to stack R14), all interrupts enabled.
  83.  
  84. This leaves you R0-R7 for your own private use. This is admittedly grim, but
  85. there's not much that can be done about it.
  86.  
  87. There are a few things that should be noted about multithreading as most
  88. Acorn programmer's probably aren't familiar with it (nor am I - I'm not even
  89. sure if this will work yet!):
  90.  
  91. Firstly, your code can be interrupted at *any* time. You cannot rely on
  92. registers R10-R13 to remain static. In other words, you can't do this:
  93.  
  94. ADD R0,R11,R3
  95. STR R5,[R0,#44]
  96.  
  97. You see, if R10 gets changed between the ADD and the STR, the R5 will be
  98. stored at the wrong address, possibly causing an Address Exception or at the
  99. least corrupting someone's data (usually your own).
  100.  
  101. Here's how you would rewrite this:
  102.  
  103. ADD R0,R3,#44
  104. STR R5,[R11,R0]
  105.  
  106. A simple little change, no difference normally, but when multitasking
  107. preemptively makes a world of difference. The same goes for offsetting into
  108. the file, using a register as an offset pointer - always LDR/STR with R10 as
  109. one of the parameters.
  110.  
  111. But what happens if this isn't possible eg; building coordinates for plotting
  112. onto the screen?
  113.  
  114. Well, the solution is to halt multitasking. It's not a good idea, and should
  115. be avoided if at all possible, but often it simply isn't. Simply place a SWI
  116. "XOS_EnterOS" in front of your non-preemptable code, and a TEQP R9,#0; MOV
  117. R0,R0 after it, assuming you've left R9 intact.
  118.  
  119. Another point in all this is speed. Renditions must be *FAST*. That's why you
  120. *MUST* write your rendition code in assembler (you'll note how C or anything
  121. else would die horribly in the above circumstances). Optimising your code
  122. (rolling out loops, organising instructions in the most efficient manner etc)
  123. really does pay dividends in redraw speed, and it is this above all that
  124. marks out one application over another (eg; Zap versus Edit - redraw is so
  125. blindingly fast it hurts, especially on the older versions without
  126. ZapRedraw). To this end, it is important to note the CPU cost of disabling
  127. preemption - calling SWI's is a notoriously slow affair (much worse on RO3+
  128. than RO2 I might add) at around 50-70 instructions; added to this is the cost
  129. in everything being held up, followed by another two otherwise unnecessary
  130. instructions.
  131.  
  132. Another instance of this is using LDR/STR against LDM/STM. The latter is much
  133. quicker for multiple regs. So much quicker in fact that for any decent amount
  134. of memory shifting it may be quicker to disable preemption for it (you must
  135. as you can't index the position register). There may be support for multiple
  136. get/put's in later versions of the multitasker, but as yet you can usually
  137. not use them, and such support will not affect threads written this way now.
  138.  
  139.