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

📄 numa.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
   if( mreq->cmd & MEMSYS_DMAFLAVOR ) {      data = (byte*)DATA_ADDR(mreq->machnum, mreq->reqAddr);   } else {       data = (byte*)DATA_ADDR(mreq->machnum, mreq->addr);   }   hist = &(mState->stats.reqtime);   StatsIncHist(hist, difftime);   hist = &(globalStats[isLocal].reqtime);   StatsIncHist(hist, difftime);   if (mreq->memnum != mreq->localMemNum) {      mreq->result |= MEMSYS_RESULT_REMOTE_HOME;   }   if (mreq->mode == MEMSYS_UNCACHED) {      if ((mreq->cmd & MEMSYS_CMDMASK) == MEMSYS_UNCREAD) {         void *from = (void*)DATA_ADDR(mreq->machnum, (uint)mreq->reqAddr);         bcopy(from, mreq->data, mreq->len);         /* Unstall the processor */         ASSERT(CPUVec.ReissueUncachedOp);         CPUVec.ReissueUncachedOp(mreq->cpunum);      } else {         void *to = (void*)DATA_ADDR(mreq->machnum, (uint)mreq->reqAddr);         bcopy(mreq->data, to, mreq->len);      }            } else {      CacheCmdDone(mreq->cpunum, mreq->transId, mreq->mode, mreq->status,                    mreq->result, data);   }   mreq->state = ALL_DONE;   List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));}/* Update the stats on a new request */static voidUpdateRequestStats(MemRequest *mreq){   switch (mreq->cmd & MEMSYS_CMDMASK) {   case MEMSYS_GET:      if (mreq->cmd & MEMSYS_DMAFLAVOR) {         StatsInc(COUNT_DMAGETS, mreq, 1);      } else {         if (mreq->cmd & MEMSYS_IFFLAVOR) {            StatsInc(COUNT_IGETS, mreq, 1);         } else if (mreq->cmd & MEMSYS_LLFLAVOR) {            StatsInc(COUNT_LLGETS, mreq, 1);         } else {            StatsInc(COUNT_DGETS, mreq, 1);         }         if (mreq->replacedPaddr != MEMSYS_NOADDR) {            if (mreq->replaceWasDirty) {               StatsInc(COUNT_WRITEBACKS, mreq, 1);            } else {               StatsInc(COUNT_REPLHINTS, mreq, 1);            }         }      }      break;   case MEMSYS_GETX:      if (mreq->cmd & MEMSYS_DMAFLAVOR) {         StatsInc(COUNT_DMAGETXS, mreq, 1);      } else {         StatsInc(COUNT_GETXS, mreq, 1);         if (mreq->replacedPaddr != MEMSYS_NOADDR) {            if (mreq->replaceWasDirty) {               StatsInc(COUNT_WRITEBACKS, mreq, 1);            } else {               StatsInc(COUNT_REPLHINTS, mreq, 1);            }         }      }      break;   case MEMSYS_UPGRADE:      if (mreq->cmd & MEMSYS_SCFLAVOR) {         StatsInc(COUNT_SCUPGRADES, mreq, 1);      } else {         StatsInc(COUNT_UPGRADES, mreq, 1);      }      break;   case MEMSYS_UNCWRITE:      StatsInc(COUNT_UNCACHEDWRITES, mreq, 1);      break;   case MEMSYS_UNCWRITE_ACCELERATED:      StatsInc(COUNT_UNCACHEDACCWRITES, mreq, 1);      break;            case MEMSYS_UNCREAD:      StatsInc(COUNT_UNCACHEDREADS, mreq, 1);      break;      case MEMSYS_REPLACEMENT_HINT:      StatsInc(COUNT_REPLHINTS, mreq, 1);      break;   case MEMSYS_WRITEBACK:      StatsInc(COUNT_WRITEBACKS, mreq, 1);      break;   default:      CPUError("Unknown memsys command (0x%x) in UmaCmd\n", mreq->cmd);   }}/***************************************************************** * MemsysInit *****************************************************************/void NumaInit(void){   int i;   u_long lines_per_mem, size;   /*     * Initialize the pointers to functions and delay parameters    */   memsysVec.type = NUMA;   memsysVec.NoMemoryDelay = 0;   memsysVec.MemsysCmd = NumaCmd;   memsysVec.MemsysDumpStats = NumaDumpStats;   memsysVec.MemsysDone = NumaDone;   memsysVec.MemsysStatus = NumaStatus;#ifndef SOLO   memsysVec.MemsysDrain = NumaDrain;   memsysVec.MemsysSetRemap = NumaSetRemap;   memsysVec.MemsysControlRemap = NumaControlRemap;   memsysVec.MemsysGetNodeAddress = NumaGetNodeAddress;#endif    CPUPrint("MEM num igets llgets dmagets dgets dmagetxs getxs scupgrades upgrades writebacks replhints uncachedwrites uncachedaccwrites uncachedreads invalordngradesent naks remotedirty exclusiveonshared memoryaccess misscount totlatency\n");   /*     * Initialize the list of request structures    */   List_Init(&freeMemReqList);      for (i = 0; i < MAX_OUTSTANDING; i++) {       MemRequest *mreq = MemRequestStorage + i;      bzero((char *) (mreq), sizeof(MemRequestStorage[0]));      List_InitElement(MREQ_TO_LIST(mreq));      List_Insert(MREQ_TO_LIST(mreq), LIST_ATREAR(&freeMemReqList));   }   /*     * Initialize the list of Invalidate structures    */   List_Init(&freeInvalReqList);      for (i = 0; i < MAX_INVALS; i++) {       InvalRequest *lreq = InvalRequestStorage + i;      bzero((char *) (lreq), sizeof(InvalRequestStorage[0]));      List_InitElement(INVAL_TO_LIST(lreq));      List_Insert(INVAL_TO_LIST(lreq), LIST_ATREAR(&freeInvalReqList));   }   /*    * Allocate and initialize the directory state for each memory,    * the stats per memory and the overall stats.    */   lines_per_mem = MEM_SIZE(0) / SCACHE_LINE_SIZE;   size = sizeof(MemState)+ (sizeof(DirState)*lines_per_mem);      for (i = 0; i < NUM_MEMORIES(0); i++) {       if (!numaDoneInit) {         memState[i] = (MemState *) ZMALLOC(size, "memState");      }      ASSERT(memState[i]);      List_Init(&memState[i]->memoryQueue);      List_Init(&memState[i]->localQueue);      bzero((char *) &memState[i]->dirState, sizeof(DirState)*lines_per_mem);      bzero((char *) &memState[i]->stats, sizeof(NumaStats));         }   bzero((char *) globalStats, 2*sizeof(NumaStats));#ifndef SOLO   NumaInitRemap();   if (NUMA_STRIPE_SIZE < 0) {      numaStripeSizePages = MEM_SIZE(0)/PAGE_SIZE/NUM_MEMORIES(0);   } else {      numaStripeSizePages = NUMA_STRIPE_SIZE;   }   numaStripeSizeBytes = numaStripeSizePages*PAGE_SIZE;   numaStripeSizeLines = numaStripeSizeBytes/SCACHE_LINE_SIZE;   numaStripeChunk = numaStripeSizeBytes*NUM_MEMORIES(0);   ASSERT(NUMA_STRIPE_SIZE < 0);   if (ENABLE_COUNT)      MigRepNumaInit();#endif   numaDoneInit = 1;}/***************************************************************** * MemsysCmd *  * Main interface from secondary cache into here * For DMA opeartions, the writeback parameter holds the * length of the DMA transfer and is NOT a boolean. *****************************************************************/ResultNumaCmd(int cpuNum, int cmd, PA addr, int transId, 	PA replacedPaddr, int writeback, byte *data){   MemState  *mState;   MemRequest *mreq = NULL;   List_Links *itemPtr;   int memnum;   int stall = 1;      #ifndef SOLO   addr = REMAP_PADDR(addr, cpuNum);   replacedPaddr = REMAP_PADDR(replacedPaddr, cpuNum);#endif    if (cmd == MEMSYS_SYNC) {      return SUCCESS;   }    if ((cmd == MEMSYS_GET) && (transId == -1)) {      /*        * Ugly hack for Cache instructions. Note the DMAFLAVOR also        * uses negative transids too. However it sets MEMSYS_DMAFLAVOR       * Should be fixed by having MIPSY use the cmds MEMSYS_WRITEBACK/REPLHINT       * Original comment attached:       * Handle special case: a GET with transId -1 indicates       * a writeback or repl hint without the associated GET (due       * to a CACHE instruction executed in the processor)       */      if (writeback) {         cmd = MEMSYS_WRITEBACK;      } else {         cmd = MEMSYS_REPLACEMENT_HINT;      }   }     /* A number of cases do not need an mreq allocated */   switch (cmd & MEMSYS_CMDMASK) {   case MEMSYS_GET:   case MEMSYS_GETX:   case MEMSYS_UPGRADE:   memnum = NumaAddrToMemnum(addr);   mState = memState[memnum];   /*    * Got a request. Allocate and fill in a memrequest    */   itemPtr = List_First(&freeMemReqList);   ASSERT(itemPtr != &freeMemReqList);   List_Remove(itemPtr);   mreq = LIST_TO_MREQ(itemPtr);   mreq->cmd = cmd;   mreq->transId = transId;   mreq->reqAddr = addr;   mreq->addr =  addr & ~(SCACHE_LINE_SIZE-1);   mreq->data = data;   mreq->len = writeback;   if( cmd & MEMSYS_DMAFLAVOR ) {      ASSERT( transId < 0 );      ASSERT( data );      mreq->replaceWasDirty  = 0;   } else {      mreq->replaceWasDirty = writeback;   }   mreq->replacedPaddr = replacedPaddr;   mreq->status = MEMSYS_STATUS_SUCCESS;   mreq->memnum = memnum;   mreq->machnum = M_FROM_CPU(cpuNum);   mreq->cpunum = cpuNum;   mreq->localMemNum = NumaLocalMem(cpuNum);   mreq->dirState = &mState->dirState[NumaAddrToMemline(addr)];   mreq->result = MEMSYS_RESULT_MEMORY|MEMSYS_RESULT_NOTRANSITION;   UpdateRequestStats(mreq);      break;   default:      break;   }   switch (cmd & MEMSYS_CMDMASK) {   case MEMSYS_GET:            mreq->mode = MEMSYS_SHARED;      break;   case MEMSYS_GETX:      mreq->mode = MEMSYS_EXCLUSIVE;      break;   case MEMSYS_UPGRADE:      mreq->mode = MEMSYS_EXCLUSIVE;      break;   case MEMSYS_UNCWRITE:   case MEMSYS_UNCWRITE_ACCELERATED:      /* Currently uncached write return with no delay,       */      globalStats[1].counts[MEMSYS_UNCWRITE]++;#ifndef SOLO      {         Result ret;         ASSERT(CPUVec.UncachedPIO);         ret = CPUVec.UncachedPIO(cpuNum, addr, 0, writeback, data);         ASSERT(ret == SUCCESS);         return SUCCESS;      }      #else      stall = 0;      break;#endif      case MEMSYS_UNCREAD:      /* Data handling is done in SendReplyToCPU for non-KSEG1 */      globalStats[1].counts[MEMSYS_UNCREAD]++;#ifndef SOLO      {         Result ret;         ASSERT(CPUVec.UncachedPIO);         ret = CPUVec.UncachedPIO(cpuNum, addr, 1, writeback, data);         ASSERT(ret == SUCCESS);         return SUCCESS;      }#else      break;#endif     case MEMSYS_WRITEBACK:   case MEMSYS_REPLACEMENT_HINT:      stall = 0;      break;   default:      CPUError("Unknown memsys command (0x%x) for memsys Numa\n", cmd);   }   /*    * Handle replacement hints and writebacks here.    */   if (replacedPaddr != MEMSYS_NOADDR) {      int rmemnum = NumaAddrToMemnum(replacedPaddr);      DirState *dir = &memState[rmemnum]->dirState[NumaAddrToMemline(replacedPaddr)];      MemRequest *wreq;      /*       * Allocate and fill in a memrequest for the writeback       */      itemPtr = List_First(&freeMemReqList);      ASSERT(itemPtr != &freeMemReqList);      List_Remove(itemPtr);      wreq = LIST_TO_MREQ(itemPtr);      wreq->data = 0;      if (writeback) {         wreq->cmd = MEMSYS_WRITEBACK;         if (data) {            wreq->data = malloc(SCACHE_LINE_SIZE);            bcopy(data, wreq->data, SCACHE_LINE_SIZE);         }      } else {         wreq->cmd = MEMSYS_REPLACEMENT_HINT;      }      wreq->transId = transId;      wreq->reqAddr = 0;      wreq->addr =  0;      wreq->len = 0;      wreq->replaceWasDirty = writeback;      wreq->replacedPaddr = replacedPaddr;      wreq->status = MEMSYS_STATUS_SUCCESS;      wreq->memnum = rmemnum;      wreq->machnum = M_FROM_CPU(cpuNum);      wreq->cpunum = cpuNum;      wreq->localMemNum = NumaLocalMem(cpuNum);      wreq->dirState = dir;      wreq->result = MEMSYS_RESULT_MEMORY|MEMSYS_RESULT_NOTRANSITION;      wreq->drainNeeded = 1;      UpdateRequestStats(wreq);      /*        * add 1 cycle to this to ensure that it does not get ahead of the original       * request through the DC queue        */      EventDoCallback(wreq->cpunum, RequestLocal, (EventCallbackHdr *) wreq, 0,                      NUMA_BUS_TIME + 1);   }   if (stall) {      /*       * Queue us for the Local delay       */      mreq->starttime = CPUVec.CycleCount(mreq->cpunum);      mreq->hdr.rout = RequestLocal;      mreq->state = REQ_LOCAL_WAIT;      EventDoCallback(mreq->cpunum, RequestLocal, (EventCallbackHdr *) mreq, 0,                      NUMA_BUS_TIME);      return STALL;    } else {      return SUCCESS;   }}void NumaDone(void){   CPUPrint("Exiting the NUMA memory system\n");}/* Dump stats about the memory system */void

⌨️ 快捷键说明

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