📄 clock.c
字号:
count++; ASSERT( count < MAX_INTERRUPT_CALLBACKS ); clockState->rotor = (clockState->rotor+1)% MAX_INTERRUPT_CALLBACKS; } event = &clockState->interrupts[ clockState->rotor]; EventDoCallback(cpuNum,EmbraInterruptCallback,event,(void *)(int)intrtoset,delay); }}void Embra_Deliver_SIPS( int cpuNum, int chan, SimTime delay ){ int count = 0; EventCallbackHdr *event; clockState->rotor = (clockState->rotor+1)%MAX_INTERRUPT_CALLBACKS; while( EventCallbackActive(&clockState->interrupts[clockState->rotor]) ){ count++; ASSERT( count < MAX_INTERRUPT_CALLBACKS ); clockState->rotor = (clockState->rotor+1)% MAX_INTERRUPT_CALLBACKS; } event = &clockState->interrupts[ clockState->rotor]; EventDoCallback(cpuNum,EmbraDeliverSIPSCallback,event,(void *)chan,delay);}static void StatCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){ Print_Recent_Stats(cpuNum); EventDoCallback(cpuNum,StatCallback,hdr,0,embra.statInterval);}static void PeriodicCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){#if 0 CPUPrint("callback %i %lld\n",cpuNum,CPUVec.CpuCycleCount(cpuNum));#endif EventDoCallback(cpuNum,PeriodicCallback,hdr,0,embra.miscCheckInterval); EmbraPollSigUsr(cpuNum); if( sim_misc.myCPUType != sim_misc.enterThisCPU) { EmbraExit(sim_misc.enterThisCPU); }}static void PeriodicAnnotationCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){ ASSERT(cpuNum == 0); EventDoCallback(0,PeriodicAnnotationCallback,hdr,0,embra.periodicAnnInterval); PERIODIC_EVENT;}/* **************************************************************** * Periodic_Callout is called very frequently. Keep it as short as * possible. * ****************************************************************/void IncCC(int cpuNum, int inc){ EMP[cpuNum].cycleCount += EMP[cpuNum].timeQuantum;}/*#define DEBUG_EVENTPOLL*/#ifdef DEBUG_EVENTPOLLstatic struct { uint cycleCountdown; uint PC; uint64 cycleCount; uint stalled;} debug_evpoll[SIM_MAXCPUS];static SimTime last_call;#endifvoid GeneralEmEventPoll(int cpuNum){ /*CPUPrint("%d GeneralEmEventPoll\n", cpuNum);*/ ASSERT(cpuNum < TOTAL_CPUS);#ifdef notdef#ifdef STALL_BY_REMOVING_FROM_LOOP /* This needs justification */ /*EMP[TOTAL_CPUS].cycleCount += EMP[0].timeQuantum;*/ /*EventPollSingleQueue(EMP[TOTAL_CPUS].cycleCount);*/#else ASSERT(cpuNum == 0 );#endif#endif /* notdef */ /* Value passed to EventPoll is a hint telling it how far down the callback queue to look. We know all cycle counts are within 1 quantum, so this should suffice */#ifdef DEBUG_EVENTPOLL ASSERT( EmbraCpuCycleCount(0) + 4*EMP[0].timeQuantum > last_call);#endif EventPollSingleQueue(EmbraCpuCycleCount(0) + 4*EMP[0].timeQuantum);#ifdef DEBUG_EVENTPOLL debug_evpoll[cpuNum].cycleCountdown = EMP[cpuNum].cycleCountdown; debug_evpoll[cpuNum].PC = EMP[cpuNum].PC; debug_evpoll[cpuNum].cycleCount = EMP[cpuNum].cycleCount; debug_evpoll[cpuNum].stalled = EMP[cpuNum].stalled; last_call = EmbraCpuCycleCount(0) + 4*EMP[0].timeQuantum;#endif /* some event hung off the cycle count may have * changed memory (eg. the debugger). This checks that. */ FlushTCIfNecessary(cpuNum); ReenterTC(EMP[TOTAL_CPUS].next); /* NOT REACHED */}/* This is called when a single event queue is used TOTAL_CPUS == 1 || MPinUP */EmbraState* CEmEventPoll(void){ /* Value passed to EventPoll is a hint telling it how far down the callback queue to look. We know all cycle counts are within 1 quantum, so this should suffice */ SimTime now_ish = EmbraCpuCycleCount(0); if (eventQueues->calltime + 100000 < now_ish) { CPUWarning("CEmEventPoll missing callouts calltime=%lld, nowish=%lld \n", eventQueues->calltime, now_ish); } #ifdef DEBUG_EVENTPOLL ASSERT( now_ish >= last_call );#endif if( EventPendingSingleQueue(now_ish) ) { EventProcessSingleQueue( now_ish ); /* Code is written to assume that this will happen because exceptions can be raised in a callback */ ReenterTC( &EMP[0] ); /* NOT REACHED */ }#ifdef DEBUG_EVENTPOLL debug_evpoll[cpuNum].cycleCountdown = EMP[cpuNum].cycleCountdown; debug_evpoll[cpuNum].PC = EMP[cpuNum].PC; debug_evpoll[cpuNum].cycleCount = EMP[cpuNum].cycleCount; debug_evpoll[cpuNum].stalled = EMP[cpuNum].stalled; last_call = EmbraCpuCycleCount(0) + 4*EMP[0].timeQuantum;#endif /* ReenterTC(EMP[TOTAL_CPUS].next);*/ /* NOT REACHED */ return &EMP[0];}void NonReturningProcReturned(void){ VASSERT(0,("Non-returning procedure returned. This is bad.\n"));}SimTime EmbraReadTime( void ){ if( embra.MPinUP ) { return EmbraCpuCycleCount(0); } else { return EmbraCpuCycleCount(CURR_CPU); }}/*#define DEBUG_CLOCK*/#ifdef DEBUG_CLOCKstatic struct { uint cycleCountdown; uint PC; uint64 cycleCount; uint clock_val;} debug_clock[SIM_MAXCPUS];#endifSimTime EmbraCpuCycleCount(int cpuNum){ static SimTime last_returned_value; SimTime new_value; new_value = EMP[cpuNum].cycleCount + ( (int64)(EMP[cpuNum].timeQuantum - EMP[cpuNum].cycleCountdown ) ); #ifdef DEBUG_CLOCK if (new_value < debug_clock[cpuNum].clock_val) { CPUWarning("cpu %d retrograde clock %lld->%lld, staying at max\n", cpuNum, debug_clock[cpuNum].clock_val, new_value); new_value = debug_clock[cpuNum].clock_val; } debug_clock[cpuNum].cycleCountdown = EMP[cpuNum].cycleCountdown; debug_clock[cpuNum].cycleCount = EMP[cpuNum].cycleCount; debug_clock[cpuNum].PC = EMP[cpuNum].PC; debug_clock[cpuNum].clock_val = new_value;#endif return new_value;}/* Make the .cycleCount field the actual current time */void EmbraFixCycleCounts(void){ int cpuNum; SimTime maxTime = 0; for (cpuNum=0;cpuNum<TOTAL_CPUS;cpuNum++) { EMP[cpuNum].cycleCount += EMP[cpuNum].timeQuantum - EMP[cpuNum].cycleCountdown; EMP[cpuNum].cycleCountdown = EMP[cpuNum].timeQuantum; if ( EMP[cpuNum].cycleCount > maxTime) { maxTime = EMP[cpuNum].cycleCount; } } for (cpuNum=0;cpuNum<TOTAL_CPUS;cpuNum++) { EMP[cpuNum].cycleCount = maxTime; }}void EmbraClockInit(void){ if( !clockState ) { clockState = MallocShared(sizeof(ClockSharedState),"EmClock"); } ASSERT( clockState );}/****************************************************************** * Write a call to the system call exit on the user's stack. Then * jump to it *****************************************************************/void EmbraMakeProcExit(int cpuNum){ EmbraState *P = &EMP[cpuNum]; uint *pPtr; VA vSP; /* Insure that we are not writting over a page boundary by using */ /* the beginning of the page*/ vSP = FORM_ADDR( PAGE_NUMBER(P->R[REG_SP]), 0 ); pPtr = (uint*) non_excepting_tv( cpuNum, vSP ); if( !pPtr ) { CPUWarning("Failure to translate stack addr in MakeProcExit\n"); return; } CPUWarning("PROCexit: CPU %d smashing address %#x\n", P->myNum, vSP); *pPtr++ = CIi( addiu_op, A0, G0, 0 ); /* li a0, 0 */ *pPtr++ = CIi( addiu_op, V0, G0, 1001 ); /* li v0, 1001 */ /* This trick won't work in base mode both because of this opcode */ /* because we are not flushing the data cache*/ *pPtr++ = CIs( syscall_op, 0, 0, 0); /* syscall */ P->PC = vSP; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -