⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * */ /**************************************************************** * clock.c *  * $Author: bosch $ * $Date: 1998/02/10 00:30:15 $ *****************************************************************/#include <stdio.h>#include <string.h>#include "simmisc.h"#include "checkpoint.h"#include "simmagic.h"#include "sips.h"#include "eventcallback.h"#include "simutil.h"#include "embra.h"#include "cp0.h"#include "clock.h"#include "main_run.h"#include "mem_control.h"#include "stats.h"#include "callout.h"#include "translator.h"#include "debug.h"#include "driver.h"#include "hw_events.h"#include "embra_interface.h"/* ********************************************************************** * All of the clock shared state is in shared memory. All of the callbacks * must be in shared memory, event non IPI as the callbacks themselves are * queued. * **********************************************************************/#define MAX_INTERRUPT_CALLBACKS (16*SIM_MAXCPUS)typedef struct ClockSharedState {    EventCallbackHdr interrupts[MAX_INTERRUPT_CALLBACKS];    int rotor;    int lock;    EventCallbackHdr pcSampling[SIM_MAXCPUS];    EventCallbackHdr periodicCallback[SIM_MAXCPUS];    EventCallbackHdr periodicAnnotationCallback;    EventCallbackHdr statCallback[SIM_MAXCPUS];    EventCallbackHdr bootCallback;    EventCallbackHdr exitCallback;} ClockSharedState;extern K0A non_excepting_tv( int cpuNum, VA va );static ClockSharedState *clockState;/* Local Data */static int pc_sample_interval = 256;int callout_interval = 0;/* Local Functions */static void InitPeriodicCallbacks(int cpu);static void StatCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static void PeriodicCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static void PeriodicAnnotationCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static void BootCallback(int cpuNum, EventCallbackHdr *hdr,void *arg);static SimTime next_PCSample;static void InitPeriodicCallbacks(int cpu){   ASSERT (cpu==0);  if (embra.stats) {     EventDoCallback(cpu,StatCallback,                     &clockState->statCallback[cpu],0,                     embra.statInterval);  }  EventDoCallback(cpu,PeriodicCallback,                  &clockState->periodicCallback[cpu],0,                  embra.miscCheckInterval);  if (cpu == 0) {     EventDoCallback(0,PeriodicAnnotationCallback,                     &clockState->periodicAnnotationCallback,0,                     embra.periodicAnnInterval);  }}void EmbraClosePeriodicCallbacks(void){   int cpu = 0;   if (EventCallbackActive(&clockState->statCallback[cpu])) {      EventCallbackRemove(&clockState->statCallback[cpu]);   }   if (EventCallbackActive(&clockState->periodicCallback[cpu])) {      EventCallbackRemove(&clockState->periodicCallback[cpu]);   }   if (EventCallbackActive(&clockState->periodicAnnotationCallback)) {       EventCallbackRemove(&clockState->periodicAnnotationCallback);   }}voidEmbra_Clock_Init(int cpuNum){   /*    * allow fast check from assembly     */   callout_interval = embra.timeQuantum;   if( embra.MPinUP ) {      int i;      EMP[TOTAL_CPUS].eventQueueTimePtr = SingleEventQueueCalltimeAddr;      for( i = 0; i <= TOTAL_CPUS; i++) {         EMP[i].timeQuantum = embra.timeQuantum;         EMP[i].cycleCountdown = EMP[i].timeQuantum;      }      InitPeriodicCallbacks(0);   } else {      ASSERT (!cpuNum);      ASSERT( TOTAL_CPUS ==1);      EMP[0].eventQueueTimePtr = SingleEventQueueCalltimeAddr;      EMP[0].timeQuantum       = embra.timeQuantum;      EMP[cpuNum].cycleCountdown = embra.timeQuantum;      InitPeriodicCallbacks(cpuNum);   }}intUpdate_And_Check_Interrupts( int cpuNum , VA targetPC){   /*CPUWarning("CPU %d Update and Check HW 0x%x\n ",             cpuNum,            EMP[cpuNum].intrBitsPtr[0] ); */   /* Update and check for interrupts */   EMP[cpuNum].CP0[C0_CAUSE] =       (EMP[cpuNum].CP0[C0_CAUSE] & ~CAUSE_EXTINTBITS) |       ((EMP[cpuNum].intrBitsPtr[0] << CAUSE_IPSHIFT) & CAUSE_EXTINTBITS);   if (((EMP[cpuNum].CP0[C0_CAUSE] & EMP[cpuNum].CP0[C0_SR]) & SR_IMASK) &&        (EMP[cpuNum].CP0[C0_SR] & SR_IEC) &&       !((EMP[cpuNum].CP0[C0_SR] & (SR_EXL|SR_ERL)))) {      /* Processors generally take excpetions in between instructions */      /* so when  we are stalled for a cache miss (or whatever), delay */      /* excpetion (interrupt) detection */         if( !EMP[cpuNum].stalled ) {            if (targetPC) {                ASSERT (!IN_BD(targetPC));               ASSERT (IS_KSEG0(targetPC) || IS_KUSEG(targetPC));               /*                * now is the time to field the post-pc annotation,                * since we are skipping the instruction by smashing                * the PC.                */               ASSERT (cpuNum==curEmp->myNum);               AnnExec(AnnFMLookup(CLEAR_BD(EMP[cpuNum].PC),ANNFM_PC_TYPE));               EMP[cpuNum].PC = targetPC;            }            Em_EXCEPTION(cpuNum,EXC_INT,0);            EmbraSideEffect();            return 1;         }   }   return 0;}void EmIntrBitsChanged(int cpuNum){   Update_And_Check_Interrupts(cpuNum,0);}/* Do Interrupt Now (only takes exception if interrupt is enabled) */static void EmbraInterruptCallback(int cpuNum, EventCallbackHdr *hdr, void *arg){   IEC intrtoset = (IEC) (int) arg;   /* keep compiler quiet by casting thru int */   SIM_DEBUG(('i',"DEV %d %lld Send 0x%x ",               cpuNum, EmbraCpuCycleCount(cpuNum), intrtoset));   RaiseIBit(cpuNum, intrtoset);   SIM_DEBUG(('i', "Ibits 0x%x\n", EMP[cpuNum].intrBitsPtr[0]));   Update_And_Check_Interrupts( cpuNum,0 );}/* Do deliver SIPS Now */static void EmbraDeliverSIPSCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){   sim_sips_deliver(cpuNum, (int)arg /* chan */);   Update_And_Check_Interrupts( cpuNum ,0);}/* Do Interrupt Now (only takes exception if interrupt is enabled) */static void BootCallback(int cpuNum, EventCallbackHdr *hdr,void *arg){   int cpu;   for( cpu = 1; cpu < TOTAL_CPUS; cpu++ ) {      uint launchAddr = (uint)sim_misc.launchAddr[cpu];      if( launchAddr ) {        /* XXX - non-backdoor address is launch, backdoor address is call */         if( IS_BACKDOOR(launchAddr) ) {            int64 result;            /* Do call */            result = ((int64 (*)(int,int,int,int))launchAddr)               ( sim_misc.launchArg[cpu][0],                 sim_misc.launchArg[cpu][1],                 sim_misc.launchArg[cpu][2],                 sim_misc.launchArg[cpu][3] );            if( result == SLAVELOOP_CONTINUE ) {               /* signal init function done */               sim_misc.launchAddr[cpu] = 0;               /* clear so will be 0 if not set up on next call */               sim_misc.launchArg[cpu][0] = 0;               sim_misc.launchArg[cpu][1] = 0;               sim_misc.launchArg[cpu][2] = 0;               sim_misc.launchArg[cpu][3] = 0;               CPUPut("Slave %d returning to launch wait\n",cpu );            }         } else {            /* Add everybody in & let mem_control handle launch */            int i;            for( i = 0; i <= TOTAL_CPUS; i++ ) {               EMP[i].next = &EMP[(i+1)%(TOTAL_CPUS+1)];            } /* for */            /* Don't reinstall callback */            return;         }      }   }   EventDoCallback(cpuNum,BootCallback,hdr,0,embra.timeQuantum);}void Embra_Send_Interrupt( int cpuNum, IEC intrtoset, SimTime delay ){        int count = 0;    EventCallbackHdr *event;    if( delay == 0 ) {       /* SIMLOCK();*/        RaiseIBit(cpuNum, intrtoset);       /* SIMUNLOCK();*/       Update_And_Check_Interrupts( cpuNum,0 );    } else {       clockState->rotor = (clockState->rotor+1)%MAX_INTERRUPT_CALLBACKS;       while( EventCallbackActive(&clockState->interrupts[clockState->rotor]) ){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -