home *** CD-ROM | disk | FTP | other *** search
- |*****************************************************************************
- |
- | NAME
- |
- | void Dispatch (
- |
- | SYNOPSIS
- | void)
- |
- | FUNCTION
- | This function switches between the task in SysBase->ThisTask and
- | the first task in the ready list. Is must be called from supervisor
- | mode with all registers set to the values of the underlying user
- | context and sp pointing to the normal exception frame (just as if
- | it was a routine in one of the interrupt vectors).
- |
- | SysBase->IDNestCnt is moved to and from the task structures and
- | the interrupt control is prepared accordingly. The routines in
- | task->tc_Launch and task->tc_Switch are called if necessary and
- | a task exception for the new task is raised if TF_EXCEPT is set.
- |
- | If the ready list is empty this function waits (with interrupts
- | enabled) until a task is willing to run.
- |
- | INPUTS
- |
- | RESULT
- |
- | NOTES
- | If the current task (when calling this function) is not part of
- | one of the two task lists it gets lost.
- |
- | This function is for internal exec use only.
- |
- | This function is processor dependant.
- |
- | EXAMPLE
- |
- | BUGS
- | This function currently doesn't read *(struct ExecBase **)4 to get
- | SysBase and thus works only from Switch(). But it makes it usable
- | for link libraries.
- |
- | SEE ALSO
- |
- | INTERNALS
- | For the task lists the following conditions must always be true as
- | long as SysBase->IDNestCnt>=0. Changes are legal with interrupts
- | Disable()d only:
- |
- | * A task is in state TS_WAIT if and only if it is part of the waiting
- | list.
- | * It is in state TS_READY if and only if it is part of the ready list.
- | * SysBase->ThisTask always points to a legal task structure.
- | * In normal user context SysBase->ThisTask->tc_State is TS_RUN.
- | There are two possible exceptions from this rule:
- | * In supervisor mode when bit 15 of SysBase->AttnResched is set
- | (dispatch pending bit).
- | This ends by calling Dispatch() before falling down to user context.
- | * In exec code. This ends by calling Switch() before going back to
- | user code.
- | * The task in SysBase->ThisTask is one of the ready tasks with the
- | highest priority (round robin). There's an exception from this rule,
- | too:
- | * If dispatching is disabled and bit 7 of SysBase->AttnResched is set
- | (switch pending bit) it is allowed to have a running task with a
- | lower priority as a waiting one. This ends by calling Switch() as
- | soon as the dispatcher is reactivated.
- | * The ready list is sorted by priority.
- |
- | HISTORY
- |
- |******************************************************************************
- .globl _Dispatch_68000
- _Dispatch_68000:
- movel a5,sp@-
- movel usp,a5
- movel sp@+,a5@-
- movew sp@+,a5@-
- movel sp@+,a5@-
- moveml d0-d7/a0-a4/a6,a5@-
- | movel 4,a6
- movew #0x2700,sr | disable interrupts
- movel a6@(0x114:W),a2 | SysBase->ThisTask
- movel a5,a2@(0x36) | ThisTask->tc_SPReg
- btst #6,a2@(0xe) | TB_SWITCH
- jeq noswch
- movel a2@(0x82),a5
- jsr a5@
- noswch: moveb a6@(0x126),a2@(0x10) | store SysBase->IDNestCnt
- moveb #-1,a6@(0x126) | set interrupt control
- movew #0xc000,0xdff09a
- leal a6@(0x196:W),a0 | &SysBase->TaskReady
- loop: movel a0@,a2 | ->lh_Head
- movel a2@,d0 | ->ln_Succ()
- jeq ready
- stop #0x2000 | wait for interrupts
- movew #0x2700,sr | disable interrupts
- jra loop
- ready: movel d0,a1 | remove first node
- movel a1,a0@
- movel a0,a1@(4:W)
- movel a2,a6@(0x114:W) | store it into SysBase->ThisTask
- moveb a2@(0x10),a6@(0x126) | restore SysBase->IDNestCnt
- jpl nodis
- movew #0x4000,0xdff09a | set interrupt control
- nodis: btst #7,a2@(0xe) | TB_LAUNCH
- jeq nolnch
- movel a2@(0x86),a5
- jsr a5@
- nolnch: movel a2@(0x36),a5 | get ThisTask->tc_SPReg
- btst #5,a2@(0xe) | TF_EXCEPT set?
- jeq noexc
- bclr #5,a2@(0xe)
- movel a5@(14*4),d0 | swap returnaddress
- movel a5@(14*4+6),a5@(14*4) | and stored a5
- movel d0,a5@(14*4+6)
- movew #0x4000,0xdff09a | mini-disable
- movel a5,usp | prepare going to user mode
- movel exloop,sp@-
- clrw sp@-
- rte
- exloop: movel a2@(0x1e),d0 | get signals causing the exception
- andl a2@(0x1a),d0
- jeq excend | none?
- eorl d0,a2@(0x1e) | disable them
- movel a2@(0x26),a1 | tc_ExceptData
- movel a2@(0x2a),a0 | tc_ExceptCode
- movew #0xc000,0xdff09a | mini-enable
- jsr a0@
- movew #0x4000,0xdff09a
- orl d0,a2@(0x1e) | reenable signals
- jra exloop | look again
- excend: movew #0xc000,0xdff09a | OK, we're done.
- moveml sp@+,d0-d7/a0-a4/a6
- movel sp@+,a5
- movew sp@+,ccr
- rts
- noexc: movew #0x2000,sr | enable interrupts
- moveml a5@+,d0-d7/a0-a4/a6
- movel a5@+,sp@-
- movew a5@+,sp@-
- movel a5@+,sp@-
- movel a5,usp
- movel sp@+,a5
- rte
-