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

📄 erosimage.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
     * routine in order to check for collisions.     */    AddDirEnt(name, key);  }  /* Step 5: add the foreign thread table entries: */  for (uint32_t ndx = 0; ndx < image.nStartups; ndx++) {    Directory& threadEnt = image.startupsDir[ndx];    DiskKey key = threadEnt.key;    InternedString name = image.GetString(threadEnt.name);    /* If the key's OID needs to be adjusted, do so: */    if (key.IsType(KT_Page) && key.IsPrepared() == false)      key.unprep.oid += nPages;    else if (key.IsType(KT_Page) && key.IsPrepared())      key.unprep.oid += nZeroPages;    else if (key.IsNodeKeyType())      key.unprep.oid += (nNodes - 1);    /* Add the resulting entry to our directory using the AddDirEnt     * routine in order to check for collisions.     */    AddStartup(name, key);  }  /* Note that any strings in the foreign image that were really   * referenced were copied somewhere in the nonsense above!   */    /* Step 5: Update the count fields that are not already up to date: */  nPages += image.nPages;  nZeroPages += image.nZeroPages;  nNodes += image.nNodes;}#endifDiskKeyErosImage::GetNodeSlot(const DiskKey& nodeKey, uint32_t slot){  if (slot >= EROS_NODE_SIZE)    Diag::fatal(5,"Slot value too high\n");    if (nodeKey.IsNodeKeyType() == false)    Diag::fatal(5,"GetNodeSlot expects node key!\n");  uint32_t ndx = nodeKey.unprep.oid;  return nodeImages[ndx][slot];}DiskKeyErosImage::GetNodeSlot(uint32_t nodeNdx, uint32_t slot){  if (slot >= EROS_NODE_SIZE)    Diag::fatal(5,"Slot value too high\n");    return nodeImages[nodeNdx][slot];}voidErosImage::SetNodeSlot(const DiskKey& nodeKey, uint32_t slot,		       const DiskKey& key){  if (slot >= EROS_NODE_SIZE)    Diag::fatal(5,"Slot value too high\n");    if (nodeKey.IsNodeKeyType() == false)    Diag::fatal(5,"GetNodeSlot expects node key!\n");  uint32_t ndx = nodeKey.unprep.oid;  nodeImages[ndx][slot] = key;}voidErosImage::SetArchitecture(ExecArch::Architecture arch){  ExecArch::ArchInfo ai = ExecArch::GetArchInfo(arch);  imageByteSex = ai.byteSex;  architecture = arch;}voidErosImage::ValidateImage(const char* target){  if (nDirEnt == 0)    Diag::fatal(2, "No directory entries in \"%s\"!\n", target);  if (!nodeImages)    Diag::fatal(2, "Missing volsize node!\n", target);  DiskNode& node = nodeImages[0];  node[OT_Node] = NumberKey(nNodes);  node[OT_DataPage] = NumberKey(nPages + nZeroPages);}voidErosImage::WriteToFile(const char *target){  ValidateImage(target);    int tfd = ::open(target, O_RDWR|O_TRUNC);  if (tfd < 0 && errno == ENOENT) {    tfd = ::open(target, O_RDWR|O_CREAT, 0666);    App.AddTarget(target);  }    if (tfd < 0)    Diag::fatal(2, "Unable to open target file \"%s\"\n", target);  /* Pin down what all the offsets will be.  We will write the pieces   * in the following order:   *    *    image header   * 	image directory   *    page content images   *    node content images   *    string table   *    */  dirOffset = sizeof(ErosHeader);  startupsOffset = dirOffset;  startupsOffset += nDirEnt * sizeof(Directory);  pageOffset = startupsOffset;  pageOffset += nStartups * sizeof(Directory);  nodeOffset = pageOffset;  nodeOffset += nPages * EROS_PAGE_SIZE;  strTableOffset = nodeOffset;  strTableOffset += nNodes * sizeof(DiskNode);  strSize = pool.Size();  int sz = sizeof(ErosHeader);  if (::write(tfd, this, sz) != sz)    Diag::fatal(3, "Unable to write image file header\n");  sz = nDirEnt * sizeof(Directory);  if (::write(tfd, dir, sz) != sz)    Diag::fatal(3, "Unable to write image directory\n");  sz = nStartups * sizeof(Directory);  if (::write(tfd, startupsDir, sz) != sz)    Diag::fatal(3, "Unable to write image thread list\n");  sz = nPages * EROS_PAGE_SIZE;  if (::write(tfd, pageImages, sz) != sz)    Diag::fatal(3, "Unable to write page images\n");  sz = nNodes * sizeof(DiskNode);  if (::write(tfd, nodeImages, sz) != sz)    Diag::fatal(3, "Unable to write node images\n");  if (pool.WriteToFile(tfd) != (int) strSize)    Diag::fatal(3, "Unable to write string pool\n");  ::close(tfd);}voidErosImage::ReadFromFile(const char *source){  nNodes = 0;  nPages = 0;  nZeroPages = 0;  delete [] pageImages;  pageImages = 0;  delete [] nodeImages;  nodeImages = 0;  nDirEnt = 0;  delete [] dir;  nStartups = 0;  delete [] startupsDir;    int sfd = ::open(source, O_RDONLY);  if (sfd < 0)    Diag::fatal(2, "Unable to open domain file \"%s\"\n", source);  struct stat statbuf;  if (::fstat(sfd, &statbuf) < 0)    Diag::fatal(2, "Can't stat domain file \"%s\"\n", source);      /* Step 1: read the image file header: */    if (::read(sfd, this, sizeof(ErosHeader)) != sizeof(ErosHeader))    Diag::fatal(2, "Cannot read image header from \"%s\"\n", source);  /* Step 1b: verify that the actual length of the file matches our   * expectations:   */  if (version != EROS_IMAGE_VERSION)    Diag::fatal(2, "Image file version in \"%s\" is obsolete\n", source);      int expect = sizeof(ErosHeader);  expect += nDirEnt * sizeof(Directory);  expect += nStartups * sizeof(Directory);  expect += nPages * EROS_PAGE_SIZE;  expect += nNodes * sizeof(DiskNode);  expect += strSize;  if (expect != statbuf.st_size)    Diag::fatal(2, "Domain image file \"%s\" is malsized.\n", source);  /* Step 2: read image directory: */  maxDir = nDirEnt;  if (maxDir % DIR_ALLOC_QUANTA) {    maxDir -= (maxDir % DIR_ALLOC_QUANTA);    maxDir += DIR_ALLOC_QUANTA;  }  dir = new Directory[maxDir];  int sz = nDirEnt * sizeof(Directory);    if (::lseek(sfd, dirOffset, SEEK_SET) < 0)    Diag::fatal(2, "Cannot seek to image directory in \"%s\"\n", source);  if (::read(sfd, dir, sz) != sz)    Diag::fatal(2, "Cannot read image directory from \"%s\"\n", source);    /* Step 3: read thread directory: */  maxStartups = nStartups;  if (maxStartups % THREAD_ALLOC_QUANTA) {    maxStartups -= (maxStartups % THREAD_ALLOC_QUANTA);    maxStartups += THREAD_ALLOC_QUANTA;  }  startupsDir = new Directory[maxDir];  sz = nStartups * sizeof(Directory);    if (::lseek(sfd, startupsOffset, SEEK_SET) < 0)    Diag::fatal(2, "Cannot seek to thread list in \"%s\"\n", source);  if (::read(sfd, startupsDir, sz) != sz)    Diag::fatal(2, "Cannot read thread list from \"%s\"\n", source);    /* Step 4: read page images: */  maxPage = nPages;  if (maxPage % PAGE_ALLOC_QUANTA) {    maxPage -= (maxPage % PAGE_ALLOC_QUANTA);    maxPage += PAGE_ALLOC_QUANTA;  }  pageImages = new uint8_t[maxPage * EROS_PAGE_SIZE];  sz = nPages * EROS_PAGE_SIZE;    if (::lseek(sfd, pageOffset, SEEK_SET) < 0)    Diag::fatal(2, "Cannot seek to page images in \"%s\"\n", source);  if (::read(sfd, pageImages, sz) != sz)    Diag::fatal(2, "Cannot read page images from \"%s\"\n", source);    /* Step 5: read cap page images: DELETED */  /* Step 6: read node images: */  maxNode = nNodes;  if (maxNode % NODE_ALLOC_QUANTA) {    maxNode -= (maxNode % NODE_ALLOC_QUANTA);    maxNode += NODE_ALLOC_QUANTA;  }  nodeImages = new DiskNode[maxNode];  sz = nNodes * sizeof(DiskNode);    if (::lseek(sfd, nodeOffset, SEEK_SET) < 0)    Diag::fatal(2, "Cannot seek to node images in \"%s\"\n", source);  if (::read(sfd, nodeImages, sz) != sz)    Diag::fatal(2, "Cannot read node images from \"%s\"\n", source);    /* Step 7: read string pool: */  if (::lseek(sfd, strTableOffset, SEEK_SET) < 0)    Diag::fatal(2, "Cannot seek to string table in \"%s\"\n", source);  if (pool.ReadFromFile(sfd, strSize) == false)    Diag::fatal(2, "Cannot load string table from \"%s\"\n", source);  ::close(sfd);}/* Given a segmode key that is the root of a segment tree, add the * specified page key at the specified offset in that segment, * inserting any needed nodes along the way. *  * DO NOT traverse a red segment boundary to do so - if you need to * add something to the contained segment, keep a handle to it and add * it directly. *  * Returns a key to the new segment root.  If the segment has grown, * this may not be a key to the same node as the original segment key. *  * The red segment expansion code found here assumes that it will not * encounter an oversize subsegment.  I'll have to get that right * (whatever that means) in the fault handling domain, but it doesn't * seem necessary here.  You can still install an oversized subsegment * if you do it with a SEGMENT key as opposed to a node key -- the * insertion code will not cross a segment boundary, because segments * are supposed to be opaque. *  */DiskKeyErosImage::DoAddPageToBlackSegment(const DiskKey& segRoot,				   uint64_t segOffset,				   const DiskKey& pageKey,				   uint64_t path,				   bool expandRedSegment){  /* segOffsetBLSS holds the LSS of the smallest segment that could   * conceivably contain segOffset.   */  uint32_t segOffsetBLSS = LSS::BiasedLSS(segOffset);  uint32_t rootBLSS = GetAnyBlss(segRoot);  #if 0  Diag::debug(2, "pageAddr=0x%04x%08x%08x\n",	   pageAddr.hi, pageAddr.mid, pageAddr.lo);#endif#ifdef KT_Wrapper  if ( segRoot.IsType(KT_Wrapper) || segRoot.IsType(KT_Segment) )    Diag::fatal(4, "AddPageToSegment: Cannot traverse subsegment\n");#else  if ( segRoot.IsRedSegmentKey() || segRoot.IsType(KT_Segment) )    Diag::fatal(4, "AddPageToSegment: Cannot traverse subsegment\n");#endif  if (rootBLSS < segOffsetBLSS) {    /* Inserting a page whose offset BLSS is too large - need to grow     * the subsegment.  The code for altering the path is a bit     * tricky, since in effect we are backing up in the path     * traversal.     */    DiskKey newRoot = AddNode();    newRoot.SetBlss(segOffsetBLSS);    if (expandRedSegment) {      Diag::printf("Expanding red seg...\n");      uint64_t pathMask = LSS::Mask(segOffsetBLSS);      uint64_t slotPath = path & ~pathMask;      slotPath |= 3u;		/* background window key */      uint64_t slotIncr = 1;      slotIncr <<= segOffsetBLSS * EROS_NODE_LGSIZE;      for (unsigned int i = 0; i < EROS_NODE_SIZE; i++) {	uint64_t bkWindowValue = slotPath;		DiskKey slotKey =          NumberKey((uint32_t) (bkWindowValue),                    (uint32_t) (bkWindowValue >> 32),                    0 );	SetNodeSlot(newRoot, i, slotKey);	slotPath += slotIncr;      }    }        SetNodeSlot(newRoot, 0, segRoot);        return DoAddPageToBlackSegment(newRoot, segOffset, pageKey, path,				   expandRedSegment);  }  if (rootBLSS > segOffsetBLSS) {    uint32_t slot = 0; /* segOffset.blssSlotNdx(segOffsetBLSS); */    DiskKey subSeg = GetNodeSlot(segRoot, slot);	    DiskKey newSlotKey =      DoAddPageToBlackSegment(subSeg, segOffset, pageKey, path,			      expandRedSegment);    SetNodeSlot(segRoot, slot, newSlotKey);          return segRoot;  }  /* The page key might replace the current key: */  if (rootBLSS == EROS_PAGE_BLSS && segOffsetBLSS == EROS_PAGE_BLSS)    return pageKey;	   /* page key goes somewhere beneath current tree: */  uint32_t slot = LSS::SlotNdx(segOffset, segOffsetBLSS);  segOffsetBLSS--;  uint64_t subSegOffset = segOffset;  subSegOffset &= LSS::Mask(segOffsetBLSS);  DiskKey subSeg = GetNodeSlot(segRoot, slot);  DiskKey newSubSeg =    DoAddPageToBlackSegment(subSeg, subSegOffset,			    pageKey, path, expandRedSegment);  SetNodeSlot(segRoot, slot, newSubSeg);  return segRoot;}static voidValidateSegKey(const ErosImage * _this,               const DiskKey& segKey){  if (segKey.IsNodeKeyType() && segKey.unprep.oid >= OID(_this->nNodes))    Diag::fatal(4, "Segment node not in image file\n");  else if (segKey.IsType(KT_Page)) {    if (segKey.IsPrepared()) {      if (segKey.unprep.oid >= OID(_this->nZeroPages))        Diag::fatal(4, "Segment page not in image file\n");    }    else if (segKey.unprep.oid >= OID(_this->nPages))      Diag::fatal(4, "Segment page not in image file\n");  }  if (segKey.IsType(KT_Process))    Diag::fatal(4, "ValidateSegKey: Domain key not valid for segment\n");  if (segKey.IsType(KT_Start))    Diag::fatal(4, "ValidateSegKey: Start key not valid for segment\n");  if (segKey.IsType(KT_Resume))    Diag::fatal(4, "ValidateSegKey: Resume key not valid for segment\n");}/* Outputs in blackRootKey a copy of segRoot, except that if segRoot   is red, blackRootKey is black. */static voidPrepareToAddObjectToSegment(ErosImage * _this,                   const DiskKey& segRoot,		   uint64_t segOffset,		   const DiskKey& objKey,		   DiskKey & blackRootKey){  ValidateSegKey(_this, segRoot);  uint32_t segOffsetBLSS = LSS::BiasedLSS(segOffset);  uint32_t rootBLSS = GetAnyBlss(segRoot);  uint32_t segBLSS = GetAnyBlss(objKey);  if (! segRoot.IsVoidKey()) {    if (segOffsetBLSS <= segBLSS &&        rootBLSS <= segOffsetBLSS)      Diag::fatal(4, "Inserted object and offset would replace entire existing segment.\n");  }  /* It is permissable for the root segment node to be a red segment.   * If so, we must verify that we are not about to get ourselves in   * trouble by growing the red segment to suitable size and fabricate   * a black segment key to pass down into the actual insertion   * routine:   */  blackRootKey = segRoot;  #ifdef KT_Wrapper  if ( segRoot.IsType(KT_Wrapper) ) {    DiskKey fmtKey = _this->GetNodeSlot(segRoot, WrapperFormat);    rootBLSS = WRAPPER_GET_BLSS(fmtKey.nk);    uint32_t newSegBlss = max(rootBLSS, segOffsetBLSS);    uint32_t initialSlots = 1;    uint32_t slot = LSS::SlotNdx(segOffset, segOffsetBLSS);    if (slot >= initialSlots)      newSegBlss++;    if (newSegBlss > rootBLSS) {      /* must grow the red segment by rewriting the format key: */      WRAPPER_SET_BLSS(fmtKey.nk, newSegBlss);      _this->SetNodeSlot(segRoot, WrapperFormat, fmtKey);    }    /* Now fabricate a black segment key to the segment's root node     * whose BLSS matches that of the red segment:     */        blackRootKey.SetBlss(newSegBlss);  }#else  if ( segRoot.IsRedSegmentKey() ) {    DiskKey fmtKey = _this->GetNodeSlot(segRoot, RedSegFormat);    rootBLSS = REDSEG_GET_BLSS(fmtKey.nk);    uint32_t newSegBlss = max(rootBLSS, segOffsetBLSS);    uint32_t initialSlots = REDSEG_GET_INITIAL_SLOTS(fmtKey.nk);    uint32_t slot = LSS::SlotNdx(segOffset, segOffsetBLSS);    if (slot >= initialSlots)      newSegBlss++;    if (newSegBlss > rootBLSS) {      /* must grow the red segment by rewriting the format key: */      REDSEG_SET_BLSS(fmtKey.nk, newSegBlss);      _this->SetNodeSlot(segRoot, RedSegFormat, fmtKey);    }    /* Now fabricate a black segment key to the segment's root node     * whose BLSS matches that of the red segment:     */        blackRootKey.SetBlss(newSegBlss);  }#endif}DiskKeyErosImage::AddPageToSegment(const DiskKey& segRoot,			    uint64_t segOffset,			    const DiskKey& pageKey){  if (! pageKey.IsType(KT_Page) &&      ! pageKey.IsVoidKey() )    Diag::fatal(4, "AddPageToSegment expects data page or void key\n");  DiskKey rootKey;  PrepareToAddObjectToSegment(this, segRoot, segOffset, pageKey,                              rootKey /* output */ );  bool wasSeg = false;    if (rootKey.IsType(KT_Segment)) {    wasSeg = true;    rootKey.SetType(KT_Node);  }  #ifdef KT_Wrapper  DiskKey newSegRoot =    DoAddPageToBlackSegment(rootKey, segOffset, pageKey, segOffset,			    segRoot.IsType(KT_Wrapper) ? true : false);#else  DiskKey newSegRoot =    DoAddPageToBlackSegment(rootKey, segOffset, pageKey, segOffset,			    segRoot.IsRedSegmentKey() ? true : false);#endif

⌨️ 快捷键说明

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