home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / config / m68k-native / dispatch.s < prev    next >
Encoding:
Text File  |  1996-12-06  |  5.5 KB  |  220 lines

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