home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / aros / source / exec / internal / m68k / m68k-native / dispatch.s < prev    next >
Encoding:
Text File  |  1996-07-16  |  5.2 KB  |  208 lines

  1. |*****************************************************************************
  2. |
  3. |   NAME
  4. |
  5. |    __AROS_LH0(void, Dispatch,
  6. |
  7. |   LOCATION
  8. |    struct ExecBase *, SysBase, 7, Exec)
  9. |
  10. |   FUNCTION
  11. |    This function switches between the task in SysBase->ThisTask and
  12. |    the first task in the ready list. Is must be called from supervisor
  13. |    mode with all registers set to the values of the underlying user
  14. |    context and sp pointing to the normal exception frame (just as if
  15. |    it was a routine in one of the interrupt vectors).
  16. |
  17. |    SysBase->IDNestCnt is moved to and from the task structures and
  18. |    the interrupt control is prepared accordingly. The routines in
  19. |    task->tc_Launch and task->tc_Switch are called if necessary and
  20. |    a task exception for the new task is raised if TF_EXCEPT is set.
  21. |
  22. |   INPUTS
  23. |
  24. |   RESULT
  25. |
  26. |   NOTES
  27. |    Raising an exception for a waiting task reactivates the task
  28. |    completely.
  29. |
  30. |    If the current task (when calling this function) is not part of
  31. |    one of the two task lists it gets lost.
  32. |
  33. |    This function is for internal exec use only.
  34. |
  35. |    This function is processor dependant.
  36. |
  37. |   EXAMPLE
  38. |
  39. |   BUGS
  40. |    This function currently reads the global variable sysbase instead of
  41. |    *(struct ExecBase **)4. This makes it usable for link libraries.
  42. |
  43. |   SEE ALSO
  44. |
  45. |   INTERNALS
  46. |    For the task lists the following conditions must always be true as
  47. |    long as SysBase->IDNestCnt>=0. Changes are legal with interrupts
  48. |    Disable()d only:
  49. |
  50. |    * A task is in state TS_WAIT if and only if it is part of the waiting
  51. |      list.
  52. |    * It is in state TS_READY if and only if it is part of the ready list.
  53. |    * SysBase->ThisTask always points to a legal task structure.
  54. |    * In normal user context SysBase->ThisTask->tc_State is TS_RUN.
  55. |      There are two possible exceptions from this rule:
  56. |      * In supervisor mode when bit 15 of SysBase->AttnResched is set
  57. |        (dispatch pending bit).
  58. |        This ends by calling Dispatch() before falling down to user context.
  59. |      * In exec code. This ends by calling Switch() before going back to
  60. |        user code.
  61. |    * The task in SysBase->ThisTask is one of the ready tasks with the
  62. |      highest priority (round robin). There's an exception from this rule,
  63. |      too:
  64. |      * If dispatching is disabled and bit 7 of SysBase->AttnResched is set
  65. |        (switch pending bit) it is allowed to have a running task with a
  66. |        lower priority as a waiting one. This ends by calling Switch() as
  67. |        soon as the dispatcher is reactivated.
  68. |    * The ready list is sorted by priority.
  69. |    * There is always at least one task willing to run - the busy task.
  70. |
  71. |   HISTORY
  72. |
  73. |******************************************************************************
  74.  
  75.     Exception   =    -0x30
  76.     Disable     =    -0x78
  77.     Enable        =    -0x7e
  78.     ThisTask    =    0x114
  79.     IDNestCnt   =    0x126
  80.     TaskReady   =    0x196
  81.     tc_Flags    =    0xe
  82.     tc_State    =    0xf
  83.     tc_IDNestCnt=    0x10
  84.     tc_SigRecvd =    0x1a
  85.     tc_SigExcept=    0x1e
  86.     tc_ExceptData=    0x26
  87.     tc_ExceptCode=    0x2a
  88.     tc_SPReg    =    0x36
  89.     tc_Switch   =    0x42
  90.     tc_Launch   =    0x46
  91.     INTENA        =    0xdff09a
  92.     INTEN        =    0x4000
  93.     SET        =    0x8000
  94.     TS_RUN        =    2
  95.     TB_EXCEPT   =    5
  96.     TB_SWITCH   =    6
  97.     TB_LAUNCH   =    7
  98.  
  99.     | Dispatching routine for the 68000.
  100.     | Higher models (with FPU) need a slightly different
  101.     | routine or the additional registers cannot be used!
  102.  
  103.     .globl    _Exec_Dispatch
  104. _Exec_Dispatch:
  105.  
  106.     | preserve a5 then move user stack pointer into it
  107.     movel    a5,sp@-
  108.     movel    usp,a5
  109.  
  110.     | move whole user context to user stack
  111.     movel    sp@+,a5@-
  112.     movew    sp@+,a5@-
  113.     movel    sp@+,a5@-
  114.     moveml    d0-d7/a0-a4/a6,a5@-
  115.  
  116.     | get SysBase
  117.     movel    _sysbase,a6
  118.  
  119.  
  120.     | disable interrupts the simple way
  121.     movew    #0x2700,sr
  122.  
  123.     | get current task and store usp there
  124.     movel    a6@(ThisTask),a2
  125.     movel    a5,a2@(tc_SPReg)
  126.  
  127.     | call the switch routine if necessary
  128.     btst    #TB_SWITCH,a2@(tc_Flags)
  129.     jeq    noswch
  130.     movel    a2@(tc_Switch),a5
  131.     jsr    a5@
  132.  
  133.     | store IDNestCnt and reenable interrupt hardware
  134. noswch: moveb    a6@(IDNestCnt),a2@(tc_IDNestCnt)
  135.     moveb    #-1,a6@(IDNestCnt)
  136.     movew    #INTEN+SET,INTENA
  137.  
  138.     | get address of ready list
  139.     leal    a6@(TaskReady),a0
  140.  
  141.     | remove first ready task in the list
  142.     movel    a0@,a2
  143.     movel    a2@,a1
  144.     movel    a1,a0@
  145.     movel    a0,a1@(4:W)
  146.  
  147.     | and use it as new current task
  148.     movel    a2,a6@(ThisTask)
  149.     moveb    #TS_RUN,d0
  150.     moveb    d0,a2@(tc_State)
  151.  
  152.     | restore IDNestCnt and disable interrupt hardware if necessary
  153.     moveb    a2@(tc_IDNestCnt),a6@(IDNestCnt)
  154.     jpl    nodis
  155.     movew    #INTEN,INTENA
  156.  
  157.     | call the launch routine if necessary
  158. nodis:    btst    #TB_LAUNCH,a2@(tc_Flags)
  159.     jeq    nolnch
  160.     movel    a2@(tc_Launch),a5
  161.     jsr    a5@
  162.  
  163.     | get user stack pointer
  164. nolnch: movel    a2@(tc_SPReg),a5
  165.  
  166.     | test task exception bit
  167.     btst    #TB_EXCEPT,a2@(tc_Flags)
  168.     jne    exc
  169.  
  170.     | not set. read complete user context
  171.     moveml    a5@+,d0-d7/a0-a4/a6
  172.     movel    a5@+,sp@-
  173.     movew    a5@+,sp@-
  174.     movel    a5@+,sp@-
  175.  
  176.     | restore usp and a5 and return
  177.     movel    a5,usp
  178.     movel    sp@+,a5
  179.     rte
  180.  
  181.     | Raise a task exception.
  182.     | The user stack looks like: a5, ccr, pc, a6, a4-a0, d7-d0.
  183.     | Change that to         pc, ccr, a5, a6, a4-a0, d7-d0
  184.     | so that it's easier to restore the context.
  185. exc:    movel    a5@(14*4),d0
  186.     movel    a5@(14*4+6),a5@(14*4)
  187.     movel    d0,a5@(14*4+6)
  188.  
  189.     | do a Disable() to fall down to user context atomically
  190.     jsr    a6@(Disable)
  191.  
  192.     | prepare going to user mode
  193.     movel    a5,usp
  194.     movel    #usrexc,sp@-
  195.     clrw    sp@-
  196.     rte
  197.  
  198.     | handle exception
  199. usrexc: jsr    a6@(Exception)
  200.     jsr    a6@(Enable)
  201.  
  202.     | restore context
  203.     moveml    sp@+,d0-d7/a0-a4/a6
  204.     movel    sp@+,a5
  205.     movew    sp@+,ccr
  206.     rts
  207.  
  208.