📄 windalib.s
字号:
/* windALib.s - internal VxWorks kernel assembly library *//* Copyright 1984-2000 Wind River Systems, Inc. */ .data .globl _copyright_wind_river .long _copyright_wind_river/*modification history--------------------01h,09may03,dee fix SPR 8591301g,26nov02,dee fix SPR# 8510501f,01mar02,tcr fix interrupt instrumentation (SPR 73858)01e,26nov01,dee remove references to _DIAB_TOOL01d,09nov00,dh WV support01c,07jul00,dh Adding MAC support01b,14jun00,dh Mods to compile for Coldfire.01a,17mar00,dra Created from T1.0.1 ColdFire and T2 m68k ports.*//*DESCRIPTIONThis module contains internals to the VxWorks kernel.These routines have been coded in assembler because they are eitherspecific to this processor, or they have been optimized for performance.WARNINGThe assembler instructions to move to and from the MAC registers arecoded as .word values rather than correct mnemonics. This is because thefile must be compiled with the -m5200 switch, and with this switch theassembler doesn;t recognise these instructions. However, we must have themin order to support all the 52xx and 53xx families in one library archive.*/#define _ASMLANGUAGE#include "vxWorks.h"#include "asm.h"#include "private/eventP.h"#include "private/taskLibP.h"#include "private/semLibP.h"#include "private/workQLibP.h" .globl _windExit /* routine to exit mutual exclusion */ .globl _vxTaskEntry /* task entry wrapper */ .globl _intEnt /* interrupt entrance routine */ .globl _intExit /* interrupt exit routine */ .globl _windIntStackSet /* interrupt stack set routine */ .globl _intEntTrap /* interrupt handler trap */ .globl __coldfireHasMac /* MAC support needed */#ifdef PORTABLE .globl _windLoadContext /* needed by portable reschedule () */#else .globl _reschedule /* optimized reschedule () routine */#endif /* PORTABLE */ .data .even__coldfireHasMac: .long 0 /* defaults to no mac support */ .text .even/********************************************************************************* windExitInt - exit kernel routine from interrupt level** windExit branches here if exiting kernel routine from int level* No rescheduling is necessary because the ISR will exit via intExit, and* intExit does the necessary rescheduling. Before leaving kernel state* the work queue is emptied.*/windExitIntWork: movew d0,sr /* UNLOCK INTERRUPTS */ jsr _workQDoWork /* empty the work queue */windExitInt: movew sr,d0 movew _intLockIntSR,d1 /* LOCK INTERRUPTS */ movew d1,sr tstl _workQIsEmpty /* test for work to do */ jeq windExitIntWork /* workQueue is not empty */#ifdef WV_INSTRUMENTATION /* wv0: windExit (interrupt) */ /* Is instrumentation on? */ tstl _evtAction jeq wv0_skip /* Save registers. */ subl #24,a7 moveml d0-d3/a0-a1,a7@ /* Do we need to log this event? */ movel _wvEvtClass,d2 andl #WV_CLASS_1_ON,d2 cmpl #WV_CLASS_1_ON,d2 jne wv0_chkTrig movel _taskIdCurrent, a0 /* current task */ movel a0@(WIND_TCB_PRIORITY),d3 /* ...and priority */ /* Is the task running with an inherited priority? If so, * a different event is logged. */ movel #EVENT_WIND_EXIT_NODISPATCH,d1 cmpl a0@(WIND_TCB_PRI_NORMAL), d3 jge wv0_log movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1wv0_log: /* Now log the event. */ movel d3,a7@- movel #0,a7@- movel d1,a7@- movel __func_evtLogTSched,a1 jsr a1@ addl #12,a7wv0_chkTrig: /* Do we need to evaluate triggers for this event? */ movel _trgEvtClass,d2 andl #TRG_CLASS_1_ON,d2 cmpl #TRG_CLASS_1_ON,d2 jne wv0_restore movel _taskIdCurrent, a0 /* current task */ movel a0@(WIND_TCB_PRIORITY),d3 /* ...and priority */ /* Is the task running with an inherited priority? If so, * a different event is logged. */ movel #EVENT_WIND_EXIT_NODISPATCH,d1 cmpl a0@(WIND_TCB_PRI_NORMAL),d3 jge wv0_trigger movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1wv0_trigger: /* Evaluate triggers. */ clrl a7@- /* param 8 - unused */ clrl a7@- /* param 7 - unused */ clrl a7@- /* param 6 - unused */ movel d3,a7@- /* param 5 - priority */ movel a0,a7@- /* param 4 - task id */ clrl a7@- /* param 3 - unused */ movel #TRG_CLASS1_INDEX,a7@- /* param 2 - class index */ movel d1,a7@- /* param 1 - event id */ movel __func_trgCheck,a0 jsr a0@ addl #32,a7 /* Pop params */wv0_restore: moveml a7@,d0-d3/a0-a1 /* restore regs */ addl #24,a7wv0_skip:#endif /* WV_INSTRUMENTATION wv0 */ clrl _kernelState /* else release exclusion */ movew d0,sr /* UNLOCK INTERRUPTS */ clrl d0 /* return OK */ rts /* back to calling task *//********************************************************************************* checkTaskReady - check that taskIdCurrent is ready to run** This code branched to by windExit when it finds preemption is disabled.* It is possible that even though preemption is disabled, a context switch* must occur. This situation arrises when a task block during a preemption* lock. So this routine checks if taskIdCurrent is ready to run, if not it* branches to save the context of taskIdCurrent, otherwise it falls thru to* check the work queue for any pending work.*/checkTaskReady: tstl a0@(WIND_TCB_STATUS) /* is task ready to run */ jne saveTaskContext /* if no, we blocked with preempt off */ /* FALL THRU TO CHECK WORK QUEUE *//********************************************************************************* checkWorkQ - check the work queue for any work to do** This code is branched to by windExit. Currently taskIdCurrent is highest* priority ready task, but before we can return to it we must check the work* queue. If there is work we empty it via doWorkPreSave, otherwise we unlock* interrupts, clear d0, and return to taskIdCurrent.*/checkWorkQ: movew _intLockTaskSR,d1 /* LOCK INTERRUPTS */ movew d1,sr tstl _workQIsEmpty /* test for work to do */ jeq doWorkPreSave /* workQueue is not empty */#ifdef WV_INSTRUMENTATION /* wv1: windExit (task, no dispatch) */ /* Is instrumentation on? */ tstl _evtAction jeq wv1_skip /* Save registers. */ subl #24,a7 moveml d0-d3/a0-a1,a7@ /* Do we need to log this event? */ movel _wvEvtClass,d2 andl #WV_CLASS_1_ON,d2 cmpl #WV_CLASS_1_ON,d2 jne wv1_chkTrig movel _taskIdCurrent, a0 /* current task */ movel a0@(WIND_TCB_PRIORITY),d3 /* ...and priority */ /* Is the task running with an inherited priority? If so, * a different event is logged. */ movel #EVENT_WIND_EXIT_NODISPATCH,d1 cmpl a0@(WIND_TCB_PRI_NORMAL), d3 jge wv1_log movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1wv1_log: /* Now log the event. */ movel d3,a7@- movel a0,a7@- movel d1,a7@- movel __func_evtLogTSched,a1 jsr a1@ addl #12,a7wv1_chkTrig: /* Do we need to evaluate triggers for this event? */ movel _trgEvtClass,d2 andl #TRG_CLASS_1_ON,d2 cmpl #TRG_CLASS_1_ON,d2 jne wv1_restore movel _taskIdCurrent, a0 /* current task */ movel a0@(WIND_TCB_PRIORITY),d3 /* ...and priority */ /* Is the task running with an inherited priority? If so, * a different event is logged. */ movel #EVENT_WIND_EXIT_NODISPATCH,d1 cmpl a0@(WIND_TCB_PRI_NORMAL),d3 jge wv1_trigger movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1wv1_trigger: /* Evaluate triggers. */ clrl a7@- /* param 8 - unused */ clrl a7@- /* param 7 - unused */ clrl a7@- /* param 6 - unused */ movel d3,a7@- /* param 5 - priority */ movel a0,a7@- /* param 4 - task id */ clrl a7@- /* param 3 - unused */ movel #TRG_CLASS1_INDEX,a7@- /* param 2 - class index */ movel d1,a7@- /* param 1 - event id */ movel __func_trgCheck,a0 jsr a0@ addl #32,a7 /* Pop params */wv1_restore: moveml a7@,d0-d3/a0-a1 /* restore regs */ addl #24,a7wv1_skip:#endif /* WV_INSTRUMENTATION wv1 */ clrl _kernelState /* else release exclusion */ movew #0x3000,sr /* UNLOCK INTERRUPTS */ clrl d0 /* return OK */ rts /* back to calling task *//********************************************************************************* doWorkPreSave - empty the work queue with current context not saved** We try to empty the work queue here, rather than let reschedule* perform the work because there is a strong chance that the* work we do will not preempt the calling task. If this is the case, then* saving the entire context just to restore it in reschedule is a waste of* time. Once the work has been emptied, the ready queue must be checked to* see if reschedule must be called, the check of the ready queue is done by* branching back up to checkTaskCode.*/doWorkPreSave: movew #0x3000,sr /* UNLOCK INTERRUPTS */ jsr _workQDoWork /* empty the work queue */ jra checkTaskSwitch /* back up to test if tasks *//******************************************************************************** windExit - task level exit from kernel** Release kernel mutual exclusion (kernelState) and dispatch any new task if* necessary. If a higher priority task than the current task has been made* ready, then we invoke the rescheduler. Before releasing mutual exclusion,* the work queue is checked and emptied if necessary.** If rescheduling is necessary, the context of the calling task is saved in its* associated TCB with the PC pointing at the next instruction after the jsr to* this routine. The SSP in the tcb is modified to ignore the return address* on the stack. Thus the context saved is as if this routine was never called.** Only the volatile registers d0,d1,a0,a1 are safe to use until the context* is saved in saveTaskContext.** At the call to reschedule the value of taskIdCurrent must be in a0.** RETURNS: OK or* ERROR if semaphore timeout occurs.** NOMANUAL* STATUS windExit ()*/ _windExit: tstl _intCnt /* if intCnt == 0 we're from task */ jne windExitInt /* else we're exiting interrupt code */ /* FALL THRU TO CHECK THAT CURRENT TASK IS STILL HIGHEST *//********************************************************************************* checkTaskSwitch - check to see if taskIdCurrent is still highest task** We arrive at this code either as the result of falling thru from windExit,* or if we have finished emptying the work queue. We compare taskIdCurrent* with the highest ready task on the ready queue. If they are same we* go to a routine to check the work queue. If they are different and preemption* is allowed we branch to a routine to make sure that taskIdCurrent is really* ready (it may have blocked with preemption disabled). If they are different* we save the context of taskIdCurrent and fall thru to reschedule.*/checkTaskSwitch: movel _taskIdCurrent,a0 /* move taskIdCurrent into a0 */ cmpl _readyQHead,a0 /* compare highest ready task */ jeq checkWorkQ /* if same then time to leave */ tstl a0@(WIND_TCB_LOCK_CNT) /* is task preemption allowed */ jne checkTaskReady /* if no, check task is ready */saveTaskContext: movel a7@,a0@(WIND_TCB_PC) /* save return address as PC */ movew sr,d0 movew d0,a0@(WIND_TCB_SR) /* save current SR in TCB */ moveml d2-d7,a0@(WIND_TCB_DREGS8) /* d2-d7; d0,d1 are volatile */ moveml a2-a7,a0@(WIND_TCB_AREGS8) /* a2-a7; a0,a1 are volatile */ clrl a0@(WIND_TCB_DREGS) /* clear saved d0 for return */ tstl __coldfireHasMac jeq saveTaskCtxtMacEnd /* jump if no MAC */saveTaskCtxtMac: .word 0xa180 /* movel acc,d0 */ movel d0,a0@(WIND_TCB_MAC) /* save MAC */ .word 0xa980 /* movel macsr,d0 */ movew d0,a0@(WIND_TCB_MACSR) /* save MACSR */ .word 0xad80 /* movel mask,d0 */ movew d0,a0@(WIND_TCB_MASK) /* save MASK */saveTaskCtxtMacEnd: addql #4,a0@(WIND_TCB_SSP) /* fix up SP for no ret adrs */ movel _errno,d0 /* save errno */ movel d0,a0@(WIND_TCB_ERRNO) /* save errno */#ifdef PORTABLE jsr _reschedule /* goto rescheduler */#else /* FALL THRU TO RESCHEDULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -