📄 erosimage.cxx
字号:
* 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 + -