📄 windalib.s
字号:
movel _errno,a0@(WIND_TCB_ERRNO) /* save errno */#ifdef PORTABLE jsr _reschedule /* goto rescheduler */#else /* FALL THRU TO RESCHEDULE *//********************************************************************************* reschedule - rescheduler for VxWorks kernel** This routine is called when either intExit, or windExit, thinks the* context might change. All of the contexts of all of the tasks are* accurately stored in the task control blocks when entering this function.* The status register is 0x3000. (Supervisor, Master Stack, Interrupts UNLOCKED)** The register a0 must contain the value of _taskIdCurrent at the entrance to* this routine.** At the conclusion of this routine, taskIdCurrent will equal the highest* priority task eligible to run, and the kernel work queue will be empty.* If a context switch to a different task is to occur, then the installed* switch hooks are called.** NOMANUAL* void reschedule ()*/_reschedule: movel _readyQHead,d0 /* get highest task to d0 */ jeq idle /* idle if nobody ready */switchTasks: movel d0,_taskIdCurrent /* update taskIdCurrent */ exg d0,a0 /* a0 gets highest task*/ movel d0,a1 /* a1 gets previous task */ movew a0@(WIND_TCB_SWAP_IN),d3 /* swap hook mask into d3 */ orw a1@(WIND_TCB_SWAP_OUT),d3 /* or in swap out hook mask */ jne doSwapHooks /* any swap hooks to do */ tstl _taskSwitchTable /* any global switch hooks? */ jne doSwitchHooks /* any switch hooks to do */dispatch: movel a0@(WIND_TCB_ERRNO),_errno /* retore errno */ movel a0@(WIND_TCB_SSP),a7 /* push dummy except */#if (CPU == MC68000) /* BUILD 68000 EXC FRAME */ movel a0@(WIND_TCB_PC),a7@- /* push new pc and sr */ movew a0@(WIND_TCB_SR),a7@- /* onto stack */#endif /* (CPU == MC68000) */#if (CPU==MC68010 || CPU==MC68020 || CPU==MC68040 || CPU==MC68060 || \ CPU==MC68LC040 || CPU==CPU32) movel a0@(WIND_TCB_FRAME2),a7@- /* push second half of frame */ movel a0@(WIND_TCB_FRAME1),a7@- /* push first half of frame */#endif /* (CPU == MC680[1246]0 || CPU==CPU32) */ moveml a0@(WIND_TCB_REGS),d0-d7/a0-a6 /* load register set */ movew _intLockTaskSR,sr /* LOCK INTERRUPTS */ tstl _workQIsEmpty /* if work q is not empty */ jeq doWorkUnlock /* then unlock and do work */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ tstl _evtAction /* intEnt instrumentation */ jeq noResched moveml d0-d3/a0-a1,a7@- /* save regs */ movel #EVENT_WIND_EXIT_DISPATCH,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 reschedCheckTrg /* 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. */ movel _taskIdCurrent, a0 /* current task */ /* priority intact in d3 */ cmpl a0@(WIND_TCB_PRI_NORMAL), d3 jge resched1Inheritance /* no inheritance */ movel #EVENT_WIND_EXIT_DISPATCH_PI, d1 /* replace event ID */resched1Inheritance: /* 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 */reschedCheckTrg: /* 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 reschedInstDone /* Jump if not set */ cmpl a0@(WIND_TCB_PRI_NORMAL),d3 jge resched1InheritanceTrg /* no inheritance */ movel #EVENT_WIND_EXIT_DISPATCH_PI, d1 /* replace event ID */resched1InheritanceTrg: /* 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 */reschedInstDone: moveml a7@+,d0-d3/a0-a1 /* restore regs */noResched: /* windview instrumentation - END */#endif clrl _kernelState /* release kernel mutex */ rte /* UNLOCK INTERRUPTS *//********************************************************************************* idle - spin here until there is more work to do** When the kernel is idle, we spin here continually checking for work to do.*/idle:#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ tstl _evtAction /* intEnt instrumentation */ jeq noIdle moveml d0-d3/a0-a1,a7@- /* save regs */ movew sr,a7@- movew _intLockTaskSR,sr /* LOCK INTERRUPTS */ /* 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 idleCheckTrg /* Jump if not set */ /* Log event */ movel #EVENT_WIND_EXIT_IDLE,a7@- /* push event ID onto int stack */ movel __func_evtLogT0,a0 /* Call log fn */ jsr a0@ addl #0x4,a7 /* Pop params */idleCheckTrg: /* 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 idleInstDone /* Jump if not set */ /* Evaluate triggers */ moveml a1/a6,a7@- /* save regs */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ clrl a7@- /* push 0 / NULL */ movel #TRG_CLASS1_INDEX,a7@- movel #EVENT_WIND_EXIT_IDLE,a7@- /* push event ID onto int stack */ movel __func_trgCheck,a0 /* Call log fn */ jsr a0@ addl #32,a7 /* Pop params */ moveml a7@+,a1/a6 /* restore regs */idleInstDone: movew a7@+,sr moveml a7@+,d0-d3/a0-a1 /* restore regs */noIdle: /* windview instrumentation - END */#endif movew #0x3000,sr /* UNLOCK INTERRUPTS (in case)*/ movel #1,_kernelIsIdle /* set idle flag for spyLib */idleLoop: tstl _workQIsEmpty /* if work queue is empty */ jne idleLoop /* keep hanging around */ clrl _kernelIsIdle /* unset idle flag for spyLib */ jra doWork /* go do the work *//********************************************************************************* doSwapHooks - execute the tasks' swap hooks*/doSwapHooks: pea a0@ /* push pointer to new tcb */ pea a1@ /* push pointer to old tcb */ lea _taskSwapTable,a5 /* get adrs of task switch rtn list */ moveq #-4,d2 /* start index at -1, heh heh */ jra doSwapShift /* jump into the loop */doSwapHook: movel a5@(0,d2:l),a1 /* get task switch rtn into a1 */ jsr a1@ /* call routine */doSwapShift: addql #4,d2 /* bump swap table index */ lslw #1,d3 /* shift swapMask bit pattern left */ jcs doSwapHook /* if carry bit set then do ix hook */ jne doSwapShift /* any bits still set */ /* no need to clean stack */ movel _taskIdCurrent,a0 /* restore a0 with taskIdCurrent */ tstl _taskSwitchTable /* any global switch hooks? */ jeq dispatch /* if no then dispatch taskIdCurrent */ jra doSwitchFromSwap /* do switch routines from swap *//********************************************************************************* doSwitchHooks - execute the global switch hooks*/doSwitchHooks: pea a0@ /* push pointer to new tcb */ pea a1@ /* push pointer to old tcb */doSwitchFromSwap: lea _taskSwitchTable,a5 /* get adrs of task switch rtn list */ movel a5@,a1 /* get task switch rtn into a1 */doSwitchHook: jsr a1@ /* call routine */ addql #4,a5 /* bump to next task switch routine */ movel a5@,a1 /* get next task switch rtn */ cmpl #0,a1 /* check for end of table (NULL) */ jne doSwitchHook /* loop */ /* no need to clean stack */ movel _taskIdCurrent,a0 /* restore a0 with taskIdCurrent */ jra dispatch /* dispatch task *//********************************************************************************* doWork - empty the work queue* doWorkUnlock - unlock interrupts and empty the work queue*/doWorkUnlock: movew #0x3000,sr /* UNLOCK INTERRUPTS */doWork: jsr _workQDoWork /* empty the work queue */ movel _taskIdCurrent,a0 /* put taskIdCurrent into a0 */ movel _readyQHead,d0 /* get highest task to d0 */ jeq idle /* nobody is ready so spin */ cmpl a0,d0 /* compare to last task */ jeq dispatch /* if the same dispatch */ jra switchTasks /* not same, do switch */#endif /* !PORTABLE */#ifdef PORTABLE/********************************************************************************* windLoadContext - load the register context from the control block** The registers of the current executing task, (the one reschedule chose),* are restored from the control block. Then the appropriate exception frame* for the architecture being used is constructed. To unlock interrupts and* enter the new context we simply use the instruction rte.** NOMANUAL* void windLoadContext ()*/_windLoadContext: movel _taskIdCurrent,a0 /* current tid */ movel a0@(WIND_TCB_ERRNO),_errno /* save errno */ movel a0@(WIND_TCB_SSP),a7 /* push dummy except. */#if (CPU == MC68000) /* 68000 EXC FRAME */ movel a0@(WIND_TCB_PC),a7@- /* push new pc and sr */ movew a0@(WIND_TCB_SR),a7@- /* onto stack */#endif /* (CPU == MC68000) */#if (CPU==MC68010 || CPU==MC68020 || CPU==MC68040 || CPU==MC68060 || \ CPU==MC68LC040 || CPU==CPU32) movew a0@(WIND_TCB_FOROFF),a7@- /* push format/offset */ movel a0@(WIND_TCB_PC),a7@- /* push new pc and sr */ movew a0@(WIND_TCB_SR),a7@- /* onto stack */#endif /* (CPU == MC680[1246]0 || CPU==CPU32) */ moveml a0@(WIND_TCB_REGS),d0-d7/a0-a6 /* load register set */ rte /* enter task's context. */#endif /* PORTABLE *//********************************************************************************* intEnt - enter an interrupt service routine** intEnt must be called at the entrance of an interrupt service routine.* This normally happens automatically, from the stub built by intConnect (2).* This routine should NEVER be called from C.** SEE ALSO: intConnect(2)* void intEnt ()*/_intEnt: movel a7@,a7@- /* bump return address up a notch */ movel _errno,a7@(0x4) /* save errno where return adress was */ addql #1,_intCnt /* Bump the counter */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ tstl _evtAction /* intEnt instrumentation */ jeq noIntEnt moveml d0-d2/a0-a6,a7@- /* save regs */ movew sr,a7@- /* save sr */ movew _intLockIntSR,sr /* LOCK INTERRUPTS */ /* * We're going to need the event ID, * so get it now. */ movew a7@,d1 /* SR */ andw #0x0700,d1 /* mask interrupt level */ asrw #8,d1 addw #MIN_INT_ID,d1 /* event ID is now in d1 */ /* 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 intEntCheckTrg /* Jump if not set */ /* Log event */ movel d1,a7@- /* push event ID onto int stack */ movel __func_evtLogT0,a0 /* Call log fn */ jsr a0@ addl #0x4,a7 /* Pop params */intEntCheckTrg: /* Check if we need to evaluate triggers for this event */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -