📄 windalib.s
字号:
* If a context switch to a different task is to occur, then the installed* switch hooks are called.** NOMANUAL* void reschedule ()*/ .balign 16,0x90FUNC_LABEL(reschedule) movl FUNC(readyQHead),%eax /* get highest task to %eax */ cmpl $0,%eax je idle /* idle if nobody ready */switchTasks: movl %eax,FUNC(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,FUNC(taskSwitchTable) /* any global switch hooks? */ jne doSwitchHooks /* any switch hooks to do */dispatch: movl WIND_TCB_ERRNO(%eax),%ecx /* retore errno */ movl %ecx,FUNC(errno) movl WIND_TCB_ESP(%eax),%esp /* push dummy except */ pushl WIND_TCB_EFLAGS(%eax) /* push EFLAGS */ pushl FUNC(sysCsSuper) /* 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,FUNC(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,FUNC(evtAction) /* is WindView on? */ je noInst3 pushl %eax /* save regs */ pushl %edx pushl %ecx movl $ WV_CLASS_1_ON,%eax andl FUNC(wvEvtClass),%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckInst3 movl FUNC(_func_evtLogTSched),%edx /* event log routine */ cmpl $0,%edx je trgCheckInst3 movl FUNC(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 FUNC(trgEvtClass),%eax /* any trigger? */ jne inst3Clean movl FUNC(_func_trgCheck),%edx /* triggering routine */ cmpl $0,%edx je inst3Clean movl FUNC(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,FUNC(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.*/ .balign 16,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,FUNC(evtAction) /* is WindView on? */ je noInstIdle pushal cli /* LOCK INTERRUPTS */ movl $ WV_CLASS_1_ON,%eax andl FUNC(wvEvtClass),%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckInstIdle movl FUNC(_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 FUNC(trgEvtClass),%eax /* any trigger? */ jne instIdleClean movl FUNC(_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,FUNC(kernelIsIdle) /* set idle flag for spyLib */idleLoop: cmpl $0,FUNC(workQIsEmpty) /* if work queue has work to do */ je goDoWork /* no more idling */ /* PAUSE instruction operates like a NOP in earlier IA-32 processors */ .byte 0xf3, 0x90 /* PAUSE should be in the loop */#ifdef X86_POWER_MANAGEMENT cmp $0, FUNC(vxIdleRtn) /* is Power Management enabled ? */ je idleLoop /* no: stay in loop */ call *FUNC(vxIdleRtn) /* call routine set by vxPowerModeSet */#else jmp idleLoop /* keep hanging around */#endif /* X86_POWER_MANAGEMENT */goDoWork: /* there is some work to do, can't remain idle now */ movl $0,FUNC(kernelIsIdle) /* unset idle flag for spyLib */ jmp doWork /* go do the work */#ifdef X86_POWER_MANAGEMENT/********************************************************************************* vxIdleAutoHalt - place the processor in AutoHalt mode when nothing to do*/ .balign 16,0x90FUNC_LABEL(vxIdleAutoHalt) sti /* make sure interrupts are enabled */ nop /* delay a bit */ cmpl $0,FUNC(workQIsEmpty) /* if work queue is still empty */ je vpdRet /* there is work to do - return */ hlt /* nothing to do - go in AutoHalt */vpdRet: ret#endif /* X86_POWER_MANAGEMENT *//********************************************************************************* doSwapHooks - execute the tasks' swap hooks*/ .balign 16,0x90doSwapHooks: pushl %eax /* push pointer to new tcb */ pushl %edx /* push pointer to old tcb */ leal FUNC(taskSwapTable),%edi /* get adrs of task switch rtn list */ movl $-4,%esi /* start index at -1, heh heh */ jmp doSwapShift /* jump into the loop */ .balign 16,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 FUNC(taskIdCurrent),%eax /* restore %eax with taskIdCurrent */ cmpl $0,FUNC(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*/ .balign 16,0x90doSwitchHooks: pushl %eax /* push pointer to new tcb */ pushl %edx /* push pointer to old tcb */doSwitchFromSwap: leal FUNC(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 FUNC(taskIdCurrent),%eax /* restore %eax with taskIdCurrent */ jmp dispatch /* dispatch task *//********************************************************************************* doWork - empty the work queue* doWorkUnlock - unlock interrupts and empty the work queue*/ .balign 16,0x90doWorkUnlock: sti /* UNLOCK INTERRUPTS */doWork: call FUNC(workQDoWork) /* empty the work queue */ movl FUNC(taskIdCurrent),%edx /* %edx = taskIdCurrent */ movl FUNC(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/********************************************************************************* 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 ()*/ .balign 16,0x90FUNC_LABEL(windLoadContext) movl FUNC(taskIdCurrent),%eax /* current tid */ movl WIND_TCB_ERRNO(%eax),%ecx /* save errno */ movl %ecx,FUNC(errno) movl WIND_TCB_ESP(%eax),%esp /* push dummy except. */ pushl WIND_TCB_EFLAGS(%eax) /* push eflags */ pushl FUNC(sysCsSuper) /* 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 iret /* 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 ()*/ .balign 16,0x90FUNC_LABEL(intEnt) cli /* LOCK INTERRUPTS */ pushl (%esp) /* bump return address up a notch */ pushl %eax movl FUNC(errno),%eax /* save errno where return adress was */ movl %eax,8(%esp) incl FUNC(intCnt) /* increment the counter */ incl FUNC(intNest) /* increment the private counter */#ifdef INT_STACK_USE /* * switch to the interrupt stack from the supervisor stack * used by a task running in the supervisor mode * * if we are already in the interrupt stack, no stack switch will * happen. It happens in the following cases: * int - exc(break/trace) - int * int - int - exc(break/trace) - int * To detect if the interrupt stack is already in use, the * private counter intNest is used. Checking the CS in ESF does * not work in the above cases. But the checking the CS in ESF * is necessary to detect the nesting interrupt before and after * the counter is manipulated. * * stack growth in the 1st interrupt * (supervisor stack) (interrupt stack) * ---------------------------------------------- * : +----- supervisor SP * ESF(12 bytes) | ESF(12 bytes) * errno <-----+ errno * return addr : return addr * %eax : %eax * : %ecx V * : %esi * : %edi * : * V * * stack growth in the 2nd interrupt (nested interrupt) * (supervisor stack) (interrupt stack) * ---------------------------------------------- * : +----- supervisor SP * ESF(12 bytes) | ESF(12 bytes) --- 1st int * errno <-----+ errno --- 1st int * return addr : * %eax ESF(12 bytes) --- 2nd int * : %ecx errno --- 2nd int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -