📄 windalib.s
字号:
* 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: movl _taskIdCurrent,%edx /* move taskIdCurrent to edx */ cmpl _readyQHead,%edx /* compare highest ready task */ je checkWorkQ /* if same then time to leave */ cmpl $0,WIND_TCB_LOCK_CNT(%edx) /* is task preemption allowed */ jne checkTaskReady /* if no, check task is ready */saveTaskContext: movl (%esp),%eax /* save return address as PC */ movl %eax,WIND_TCB_PC(%edx) pushfl /* save a eflags */ popl WIND_TCB_EFLAGS(%edx) bts $9,WIND_TCB_EFLAGS(%edx) /* set IF to enable INT */ movl %ebx,WIND_TCB_EBX(%edx) /* e[adc]x are volatile */ movl %esi,WIND_TCB_ESI(%edx) movl %edi,WIND_TCB_EDI(%edx) movl %ebp,WIND_TCB_EBP(%edx) movl %esp,WIND_TCB_ESP(%edx) movl $0,WIND_TCB_EAX(%edx) /* clear saved eax for return */ addl $4,WIND_TCB_ESP(%edx) /* fix up SP for no ret adrs */ pushl _errno /* save errno */ popl WIND_TCB_ERRNO(%edx)#ifdef PORTABLE call _reschedule#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 0x800f0000. (Supervisor, Stack0, Interrupts UNLOCKED)** The register %edx 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 ()*/ .align 4,0x90_reschedule: movl _readyQHead,%eax /* get highest task to %eax */ cmpl $0,%eax je idle /* idle if nobody ready */switchTasks: movl %eax,_taskIdCurrent /* update taskIdCurrent */ movw WIND_TCB_SWAP_IN(%eax),%bx /* swap hook mask into %bx */ orw WIND_TCB_SWAP_OUT(%edx),%bx /* or in swap out hook mask */ jne doSwapHooks /* any swap hooks to do */ cmpl $0,_taskSwitchTable /* any global switch hooks? */ jne doSwitchHooks /* any switch hooks to do */dispatch: movl WIND_TCB_ERRNO(%eax),%ecx /* retore errno */ movl %ecx,_errno movl WIND_TCB_ESP(%eax),%esp /* push dummy except */ pushl WIND_TCB_EFLAGS(%eax) /* push EFLAGS */ pushl _sysCodeSelector /* push CS */ pushl WIND_TCB_PC(%eax) /* push PC */ movl WIND_TCB_EDX(%eax),%edx /* restore registers */ movl WIND_TCB_ECX(%eax),%ecx movl WIND_TCB_EBX(%eax),%ebx movl WIND_TCB_ESI(%eax),%esi movl WIND_TCB_EDI(%eax),%edi movl WIND_TCB_EBP(%eax),%ebp movl WIND_TCB_EAX(%eax),%eax cli /* LOCK INTERRUPTS */ cmpl $0,_workQIsEmpty /* if work q is not empty */ je doWorkUnlock /* then unlock and do work */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * exit windExit with dispatch; */ cmpl $0,_evtAction /* is WindView on? */ je noInst3 pushl %eax /* save regs */ pushl %edx pushl %ecx movl $ WV_CLASS_1_ON,%eax andl _wvEvtClass,%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckInst3 movl __func_evtLogTSched,%edx /* event log routine */ cmpl $0,%edx je trgCheckInst3 movl _taskIdCurrent,%eax /* current task */ movl WIND_TCB_PRIORITY(%eax),%ecx pushl %ecx /* WIND_TCB_PRIORITY */ pushl %eax /* taskIdCurrent */ /* Here we try to determine if the task is running at an * inherited priority, if so a different event is generated. */ cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx jge noInst3Inheritance /* no inheritance */ pushl $ EVENT_WIND_EXIT_DISPATCH_PI jmp inst3Inheritance /* no inheritance */noInst3Inheritance: pushl $ EVENT_WIND_EXIT_DISPATCH /* event id */inst3Inheritance: call *%edx /* call evtsched routine */ addl $12,%esptrgCheckInst3: movl $ TRG_CLASS_1,%eax orl $ TRG_ON,%eax cmpl _trgEvtClass,%eax /* any trigger? */ jne inst3Clean movl __func_trgCheck,%edx /* triggering routine */ cmpl $0,%edx je inst3Clean movl _taskIdCurrent,%eax /* current task */ movl WIND_TCB_PRIORITY(%eax),%ecx pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl %ecx /* WIND_TCB_PRIORITY */ pushl %eax /* taskIdCurrent */ pushl $ 0 /* obj */ pushl $ 0 /* TRG_CLASS1_INDEX */ /* Here we try to determine if the task is running at an * inherited priority, if so a different event is generated. */ cmpl WIND_TCB_PRI_NORMAL(%eax),%ecx jge noTrgInst3Inheritance /* no inheritance */ pushl $ EVENT_WIND_EXIT_DISPATCH_PI jmp trgInst3Inheritance /* no inheritance */noTrgInst3Inheritance: pushl $ EVENT_WIND_EXIT_DISPATCH /* event id */trgInst3Inheritance: call *%edx /* call triggering routine */ addl $32,%espinst3Clean: popl %ecx /* restore regs */ popl %edx popl %eaxnoInst3: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ movl $0,_kernelState /* release kernel mutex */ iret /* 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.*/ .align 4,0x90idle:#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter idle state * * NOTE: I am making the assumption here that it is okay to * modify the %eax,%edx,%ecx registers. They are not being saved. */ cmpl $0,_evtAction /* is WindView on? */ je noInstIdle pushal cli /* LOCK INTERRUPTS */ movl $ WV_CLASS_1_ON,%eax andl _wvEvtClass,%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckInstIdle movl __func_evtLogT0,%edx /* event log routine */ cmpl $0,%edx je trgCheckInstIdle pushl $ EVENT_WIND_EXIT_IDLE /* event id */ call *%edx /* call event log routine */ addl $4,%esptrgCheckInstIdle: movl $ TRG_CLASS_1,%eax orl $ TRG_ON,%eax cmpl _trgEvtClass,%eax /* any trigger? */ jne instIdleClean movl __func_trgCheck,%edx /* triggering routine */ cmpl $0,%edx je instIdleClean pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* obj */ pushl $ 0 /* TRG_CLASS1_INDEX */ pushl $ EVENT_WIND_EXIT_IDLE /* EVENT_WIND_EXIT_IDLE */ call *%edx /* call triggering routine */ addl $32,%esp instIdleClean: popalnoInstIdle: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ sti /* UNLOCK INTERRUPTS (just in case) */ movl $1,_kernelIsIdle /* set idle flag for spyLib */idleLoop: cmpl $0,_workQIsEmpty /* if work queue is still empty */ jne idleLoop /* keep hanging around */ movl $0,_kernelIsIdle /* unset idle flag for spyLib */ jmp doWork /* go do the work *//********************************************************************************* doSwapHooks - execute the tasks' swap hooks*/ .align 4,0x90doSwapHooks: pushl %eax /* push pointer to new tcb */ pushl %edx /* push pointer to old tcb */ leal _taskSwapTable,%edi /* get adrs of task switch rtn list */ movl $-4,%esi /* start index at -1, heh heh */ jmp doSwapShift /* jump into the loop */ .align 4,0x90doSwapHook: movl (%esi,%edi,1),%ecx /* call task switch rtn into r3+4*n */ call *%ecxdoSwapShift: addl $4,%esi /* bump swap table index */ shlw $1,%bx /* shift swapMask bit pattern left */ jc doSwapHook /* if carry bit set then do ix hook */ jne doSwapShift /* any bits still set */ /* no need to clean stack */ movl _taskIdCurrent,%eax /* restore %eax with taskIdCurrent */ cmpl $0,_taskSwitchTable /* any global switch hooks? */ je dispatch /* if no then dispatch taskIdCurrent */ jmp doSwitchFromSwap /* do switch routines from swap *//********************************************************************************* doSwitchHooks - execute the global switch hooks*/ .align 4,0x90doSwitchHooks: pushl %eax /* push pointer to new tcb */ pushl %edx /* push pointer to old tcb */doSwitchFromSwap: leal _taskSwitchTable,%edi /* get adrs of task switch rtn list */ movl (%edi),%esi /* get task switch rtn into %esi */doSwitchHook: call *%esi /* call routine */ addl $4,%edi /* bump to next task switch routine */ movl (%edi),%esi /* get next task switch rtn */ cmpl $0,%esi jne doSwitchHook /* check for end of table (NULL) */ /* no need to clean stack */ movl _taskIdCurrent,%eax /* restore %eax with taskIdCurrent */ jmp dispatch /* dispatch task *//********************************************************************************* doWork - empty the work queue* doWorkUnlock - unlock interrupts and empty the work queue*/ .align 4,0x90doWorkUnlock: sti /* UNLOCK INTERRUPTS */doWork: call _workQDoWork /* empty the work queue */ movl _taskIdCurrent,%edx /* %edx = taskIdCurrent */ movl _readyQHead,%eax /* %eax = highest task */ cmpl $0,%eax je idle /* nobody is ready so spin */ cmpl %edx,%eax /* compare to last task */ je dispatch /* if the same dispatch */ jmp switchTasks /* not same, do switch */#endif /* PORTABLE */#ifdef PORTABLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -