📄 windalib.s
字号:
/********************************************************************************* 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: movl _taskIdCurrent,%eax /* current tid */ movl WIND_TCB_ERRNO(%eax),%ecx /* save 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 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 ()*/ .align 4,0x90_intEnt: pushl (%esp) /* bump return address up a notch */ pushl %eax movl _errno,%eax /* save errno where return adress was */ movl %eax,8(%esp) popl %eax incl _intCnt /* Bump the counter */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * enter an interrupt handler. * * ALL registers must be saved. */ cmpl $0,_evtAction /* is WindView on? */ je noIntEnt pushal /* save regs */ cli /* LOCK INTERRUPTS */ movl 32(%esp),%edi /* use %edi to store the return address */ movl $ WV_CLASS_1_ON,%eax andl _wvEvtClass,%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckIntEnt movl INT_CONNECT_CODE29(%edi), %eax /* get IRQ number */ addl $ MIN_INT_ID,%eax /* get event ID */ movl __func_evtLogT0,%edx /* event log routine */ cmpl $0,%edx je trgCheckIntEnt pushl %eax call *%edx /* call event log routine */ addl $4,%esptrgCheckIntEnt: movl $ TRG_CLASS_1,%eax orl $ TRG_ON,%eax cmpl _trgEvtClass,%eax /* any trigger? */ jne intEntClean movl INT_CONNECT_CODE29(%edi), %eax /* get IRQ number */ addl $ MIN_INT_ID,%eax /* get event ID */ movl __func_trgCheck,%edx /* triggering routine */ cmpl $0,%edx je intEntClean pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* obj */ pushl $ 0 /* TRG_CLASS1_INDEX */ pushl %eax /* push event ID */ call *%edx /* call triggering routine */ addl $32,%espintEntClean: sti popal /* restore regs */noIntEnt: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ ret/********************************************************************************* intExit - exit an interrupt service routine** Check the kernel ready queue to determine if resheduling is necessary. If* no higher priority task has been readied, and no kernel work has been queued,* then we return to the interrupted task.** If rescheduling is necessary, the context of the interrupted task is saved* in its associated TCB with the PC, EFLAGS and EFLAGS retrieved from the * exception frame on the master stack.** This routine must be branched to when exiting an interrupt service routine.* This normally happens automatically, from the stub built by intConnect (2).** This routine can NEVER be called from C.** It can only be jumped to because a jsr will push a return address on the* stack.** SEE ALSO: intConnect(2)* void intExit ()* INTERNAL* This routine must preserve all registers up until the context is saved,* so any registers that are used to check the queues must first be saved on* the stack.** At the call to reschedule the value of taskIdCurrent must be in edx.*/ .align 4,0x90_intExit: popl _errno /* restore errno */ pushl %eax /* push %eax onto interrupt stack */#ifdef WV_INSTRUMENTATION /* windview instrumentation - BEGIN * log event if work has been done in the interrupt handler. * NOTE: a0 is still on the stack */ cmpl $0,_evtAction /* is WindView on? */ je noIntExit pushl %edx pushl %ecx cli movl $ WV_CLASS_1_ON,%eax andl _wvEvtClass,%eax /* is event collection on? */ cmpl $ WV_CLASS_1_ON,%eax /* is event collection on? */ jne trgCheckIntExit movl __func_evtLogT0,%edx /* event log routine */ cmpl $0,%edx je trgCheckIntExit cmpl $0,_workQIsEmpty /* work in work queue? */ jne intExitEvent pushl $ EVENT_INT_EXIT_K /* event id */ jmp intExitContintExitEvent: pushl $ EVENT_INT_EXIT /* event id */intExitCont: call *%edx /* call event log routine */ addl $4,%esp trgCheckIntExit: movl $ TRG_CLASS_1,%eax orl $ TRG_ON,%eax cmpl _trgEvtClass,%eax /* any trigger? */ jne intExitClean movl __func_trgCheck,%edx /* triggering routine */ cmpl $0,%edx je intExitClean pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* 0 */ pushl $ 0 /* obj */ pushl $ 0 /* TRG_CLASS1_INDEX */ cmpl $0,_workQIsEmpty /* work in work queue? */ jne trgIntExitEvent pushl $ EVENT_INT_EXIT_K /* event id */ jmp trgIntExitConttrgIntExitEvent: pushl $ EVENT_INT_EXIT /* event id */trgIntExitCont: call *%edx /* call triggering routine */ addl $32,%espintExitClean: sti /* UNLOCK INTERRUPTS */ popl %ecx /* restore regs */ popl %edxnoIntExit: /* windview instrumentation - END */#endif /* WV_INSTRUMENTATION */ decl _intCnt /* decrement intCnt */ cmpl $0,_kernelState /* if kernelState == TRUE then */ jne intRte /* just clean up and rte */ movw 8(%esp),%ax /* if CS on stack and CS on IDT is */ cmpw _intIdtSelector,%ax /* same, then we were */ je intRte /* in an ISR so just clean up/rte */ cli /* LOCK INTERRUPTS */ movl _taskIdCurrent,%eax /* put current task in %eax */ cmpl _readyQHead,%eax /* compare to highest ready task */ je intRte /* if same then don't reschedule */ cmpl $0,WIND_TCB_LOCK_CNT(%eax) /* is task preemption allowed */ je saveIntContext /* if yes, then save context */ cmpl $0,WIND_TCB_STATUS(%eax) /* is task ready to run */ jne saveIntContext /* if no, then save context */intRte: popl %eax /* restore %eax */ iret /* UNLOCK INTERRUPTS *//* We are here if we have decided that rescheduling is a distinct possibility. * The context must be gathered and stored in the current task's tcb. * The stored stack pointers must be modified to clean up the stacks (SP). */ .align 4,0x90saveIntContext: /* interrupts are still locked out */ movl $1,_kernelState /* kernelState = TRUE; */ movl _taskIdCurrent,%eax /* tcb to be fixed up */ popl WIND_TCB_EAX(%eax) /* store %eax in tcb */ popl WIND_TCB_PC(%eax) /* save pc in tcb */ leal 4(%esp),%esp /* do not save %cs in tcb */ popl WIND_TCB_EFLAGS(%eax) /* save eflags in tcb */ sti /* UNLOCK INTERRUPTS */ /* interrupts unlocked and using master stack*/ movl %edx,WIND_TCB_EDX(%eax) /* save %edx */ movl %ecx,WIND_TCB_ECX(%eax) /* save %ecx */ movl %ebx,WIND_TCB_EBX(%eax) /* save %ebx */ movl %esi,WIND_TCB_ESI(%eax) /* save %esi */ movl %edi,WIND_TCB_EDI(%eax) /* save %edi */ movl %ebp,WIND_TCB_EBP(%eax) /* save %ebp */ movl %esp,WIND_TCB_ESP(%eax) /* save %esp */ movl _errno,%edx /* save errno */ movl %edx,WIND_TCB_ERRNO(%eax) movl %eax,%edx /* taskIdCurrent into %edx */ jmp _reschedule /* goto rescheduler *//********************************************************************************* vxTaskEntry - task startup code following spawn** This hunk of code is the initial entry point to every task created via* the "spawn" routines. taskCreate(2) has put the true entry point of the* task into the tcb extension before creating the task,* and then pushed exactly ten arguments (although the task may use* fewer) onto the stack. This code picks up the real entry point and calls it.* Upon return, the 10 task args are popped, and the result of the main* routine is passed to "exit" which terminates the task.* This way of doing things has several purposes. First a task is easily* "restartable" via the routine taskRestart(2) since the real* entry point is available in the tcb extension. Second, the call to the main* routine is a normal call including the usual stack clean-up afterwards,* which means that debugging stack trace facilities will handle the call of* the main routine properly.** NOMANUAL* void vxTaskEntry ()*/ .align 4,0x90_vxTaskEntry: xorl %ebp,%ebp /* make sure frame pointer is 0 */ movl _taskIdCurrent,%eax /* get current task id */ movl WIND_TCB_ENTRY(%eax),%eax /* entry point for task is in tcb */ call *%eax /* call main routine */ addl $40,%esp /* pop args to main routine */ pushl %eax /* pass result to exit */ call _exit /* gone for good *//********************************************************************************* windIntStackSet - set the interrupt stack pointer** This routine sets the interrupt stack pointer to the specified address.* It is only valid on architectures with an interrupt stack pointer.** NOMANUAL* void windIntStackSet (pBotStack)* char *pBotStack; /* pointer to bottom of interrupt stack **/ .align 4,0x90_windIntStackSet: ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -