📄 windalib.s
字号:
/* windALib.s - internal VxWorks kernel assembly library *//* Copyright 1984-1998 Wind River Systems, Inc. */ .data .globl _copyright_wind_river .long _copyright_wind_river/*modification history--------------------03a,17jun98,cjtc fix 68060 crash when logging. (SPR 21321)02z,26mar98,nps bug fixes for wv2.0 port.02y,04mar98,nps completed triggering instrumentation.02x,04mar98,nps upgrade to WV2.0, triggering not complete.02w,08jul96,sbs made windview instrumentation conditionally compiled02r,31oct94,tmk added MC68LC040 support.02q,31may94,tpr added MC68060 cpu support.02v,04mar94,smb added some kernel optimisations EVENT_WIND_EXIT_NODISPATCH does not log taskIdCurrent introduced EVENT_INT_EXIT_K removed EVENT_WIND_EXIT_IDLENOT02u,03feb94,smb changed interrupt locks to respect intLockLevelSet()02t,28jan94,smb corrected intCnt check, optimised idle loop02s,24jan94,smb added EVENT_WIND_EXIT_DISPATCH_PI and EVENT_WIND_EXIT_NODISPATCH_PI02r,19jan94,smb fixed modhist for 02q event buffer overrun fix SPR #290402q,19jan94,smb added instrumentation02p,23aug92,jcf changed bxxx to jxx. removed AS_WORKS_WELL.02o,04jul92,jcf private header files.02n,26may92,rrr the tree shuffle02m,04oct91,rrr passed through the ansification filter -fixed #else and #endif -changed VOID to void -changed ASMLANGUAGE to _ASMLANGUAGE -changed copyright notice02l,25sep91,yao added support for CPU32.02k,28aug91,shl added support for MC68040, cleaned up #if CPU, updated copyright.02j,24aug91,jcf windExitInt empties work queue. fixed elr modhist.02i,17may91,elr made portable for Motorola's SVR402h,22jan91,jcf made portable to the 68000/68010.02g,01oct90,dab changed conditional compilation identifier from HOST_SUN to AS_WORKS_WELL.02f,12sep90,dab changed tstl a<n> to cmpl #0,a<n>. changed complex +lpf addressing modes instructions to .word's to make non-SUN hosts happy. changed jra to jmp in 680[01]0 section of _intExit.02e,15jul90,jcf moved emptyWorkQ to workQDoWork () in workQALib. unlocked interrupts for idle in OPTIMIZED windExit ().02d,27jun90,jcf unlocked interrupts for idle in PORTABLE windExit ()02c,26jun90,jcf fixed PORTABLE version for wind. unlocked interrupts when saving context.02b,23apr90,jcf changed name and moved to src/68k.02a,20aug89,jcf version 2.0 enhancements.01g,29mar89,shl documentation.01f,29mar89,shl changed syntax of TCB_AREGS +4, TCB_AREGS +8, TCB_DREGS +4, andTCB_DREGS +8 to TCB_AREGS4, TCB_AREGS8 TCB_DREGS4, and TCB_DREGS8 respectively so to make force host happy01e,30oct88,jcf fixed erroneous conditional compile that broke 68000 version.01d,31aug88,jcf changed exception frame handling to preserve format/offset word, so floating point works correctly. changed windIntStackSet to modify variable _ispBot.01c,23aug88,gae documentation; moved TCB definitions to wind.h.01b,12aug88,jcf reworked stack usage and optimized as per code review.01a,13mar88,jcf written.*//*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.*/#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 */#ifdef PORTABLE .globl _windLoadContext /* needed by portable reschedule () */#else .globl _reschedule /* optimized reschedule () routine */#endif /* PORTABLE */ .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,sr /* LOCK INTERRUPTS */ tstl _workQIsEmpty /* test for work to do */ jeq windExitIntWork /* workQueue is not empty */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ tstl _evtAction /* intEnt instrumentation */ jeq noWindE moveml d0-d3/a0-a1,a7@- /* save regs */ movel #EVENT_WIND_EXIT_NODISPATCH,d1 /* event ID is now in d1 */ movel _taskIdCurrent, a0 /* current task */ movel a0@(WIND_TCB_PRIORITY),d3 /* ...and priority */ /* Check if we need to log this event */ movel _wvEvtClass,d2 /* Load event class */ andl #WV_CLASS_1_ON,d2 /* Examine these bits */ cmpl #WV_CLASS_1_ON,d2 jne windECheckTrg /* Jump if not set */ /* Here we try to determine if the task is running at an * inherited priority, if so a different event is generated. */ cmpl a0@(WIND_TCB_PRI_NORMAL), d3 jge windE1Inheritance /* no inheritance */ movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1 /* replace event ID */windE1Inheritance: /* Log event */ movel d3,a7@- /* push priority */ movel #0,a7@- /* push unused param */ movel d1,a7@- /* push event ID onto int stack */ movel __func_evtLogTSched,a1 /* Call log fn */ jsr a1@ addl #12,a7 /* Pop params */windECheckTrg: /* Check if we need to evaluate triggers for this event */ movel _trgEvtClass,d2 /* Load event class */ andl #TRG_CLASS_1_ON,d2 /* Examine these bits */ cmpl #TRG_CLASS_1_ON,d2 jne windEInstDone /* Jump if not set */ movel _taskIdCurrent, a0 /* current task */ /* priority intact in d3 */ cmpl a0@(WIND_TCB_PRI_NORMAL),d3 jge windE1InheritanceTrg /* no inheritance */ movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1 /* replace event ID */windE1InheritanceTrg: /* Evaluate triggers */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ movel d3,a7@- /* push priority */ movel a0,a7@- /* push task ID */ clrl a7@- /* push 0 / NULL */ movel #TRG_CLASS1_INDEX,a7@- movel d1,a7@- /* push event ID onto int stack */ movel __func_trgCheck,a0 /* Call log fn */ jsr a0@ addl #32,a7 /* Pop params */windEInstDone: moveml a7@+,d0-d3/a0-a1 /* restore regs */noWindE: /* windview instrumentation - END */#endif 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,sr /* LOCK INTERRUPTS */ tstl _workQIsEmpty /* test for work to do */ jeq doWorkPreSave /* workQueue is not empty */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ tstl _evtAction /* intEnt instrumentation */ jeq noChkW moveml d0-d3/a0-a1,a7@- /* save regs */ movel #EVENT_WIND_EXIT_NODISPATCH,d1 /* event ID is now in d1 */ movel _taskIdCurrent, a0 /* current task */ movel a0@(WIND_TCB_PRIORITY),d3 /* ...and priority */ /* Check if we need to log this event */ movel _wvEvtClass,d2 /* Load event class */ andl #WV_CLASS_1_ON,d2 /* Examine these bits */ cmpl #WV_CLASS_1_ON,d2 jne chkWCheckTrg /* Jump if not set */ /* Here we try to determine if the task is running at an * inherited priority, if so a different event is generated. */ cmpl a0@(WIND_TCB_PRI_NORMAL), d3 jge chkW1Inheritance /* no inheritance */ movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1 /* replace event ID */chkW1Inheritance: /* Log event */ movel d3,a7@- /* push priority */ movel a0,a7@- /* push task ID onto int stack */ movel d1,a7@- /* push event ID onto int stack */ movel __func_evtLogTSched,a1 /* Call log fn */ jsr a1@ addl #12,a7 /* Pop params */chkWCheckTrg: /* Check if we need to evaluate triggers for this event */ movel _trgEvtClass,d2 /* Load event class */ andl #TRG_CLASS_1_ON,d2 /* Examine these bits */ cmpl #TRG_CLASS_1_ON,d2 jne chkWInstDone /* Jump if not set */ movel _taskIdCurrent, a0 /* current task */ /* priority intact in d3 */ cmpl a0@(WIND_TCB_PRI_NORMAL),d3 jge chkW1InheritanceTrg /* no inheritance */ movel #EVENT_WIND_EXIT_NODISPATCH_PI, d1 /* replace event ID */chkW1InheritanceTrg: /* Evaluate triggers */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ movel d3,a7@- /* push priority */ movel a0,a7@- /* push task ID */ movel #TRG_CLASS1_INDEX,a7@- movel d1,a7@- /* push event ID onto int stack */ movel __func_trgCheck,a0 /* Call log fn */ jsr a0@ addl #32,a7 /* Pop params */chkWInstDone: moveml a7@+,d0-d3/a0-a1 /* restore regs */noChkW: /* windview instrumentation - END */#endif 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 #0x3000,a0@(WIND_TCB_SR) /* save a brand new SR */ clrw a0@(WIND_TCB_FOROFF) /* clear the format/offset */ 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 */ addql #4,a0@(WIND_TCB_SSP) /* fix up SP for no ret adrs */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -