📄 bank.c
字号:
}uint32_tBankDestroyBankAndStorage(Bank *bank, bool andStorage){ /* the way this works is a depth-first deallocation: we first delete * (effectively recursively, actually in-place) all of the children * of a bank, then delete the bank itself. Of course, if one of the * children of that bank has children, those get deleted first, * etc. The deletion stops when we delete /bank/. * * NOTE that there is a perverse piece of nonsense that we are * taking advantage of here: the space occupied by the node(s) of a * given bank are part of that bank's allocated tree. */#ifdef PARANOID if (bank == &primebank || bank == &bank0) kpanic(KR_OSTREAM, "spacebank: attempt to destroy primebank/bank0\n");#endif DEBUG(children) kprintf(KR_OSTREAM, "DestroyBank: Destroying bank 0x%08x%s\n", bank, (andStorage)?" and storage":" and returning storage to parent"); /* destroy this bank and all of its children */ { Bank *curBank = 0; Bank *parentBank = bank->parent; Bank *next; while (bank) { if (curBank == 0) curBank = bank; while (curBank->firstChild) curBank = curBank->firstChild; /* curbank now points to a leftmost child */ next = curBank->nextSibling; FlushBankCache(curBank); /* rescind all outstanding red segment nodes that point to this bank */ { /* FIX: There is a HUGE problem here -- if the underlying range is unavailable (e.g. dismounted) then this operation will fail! */ int i; for (i = 0; i < BANKPREC_NUM_PRECLUDES; i++) { if (curBank->exists[i]) { uint32_t result; result = range_getobjectkey(KR_SRANGE, OT_Node, curBank->limitedKey[i], KR_TMP); if (result != RC_OK) { DEBUG(children) kprintf(KR_OSTREAM, "SpaceBank: Unable to create key to limited " "node %d oid 0x"DW_HEX" (0x%08x)\n", i, DW_HEX_ARG(curBank->limitedKey[i]), result); } /* It will do no harm to rescind it if we didn't get it */ result = range_rescind(KR_SRANGE, KR_TMP); if (result != RC_OK) { DEBUG(children) kprintf(KR_OSTREAM, "SpaceBank: Unable to create key to limited " "node %d oid 0x"DW_HEX" (0x%08x)\n", i, DW_HEX_ARG(curBank->limitedKey[i]), result); } result = allocTree_removeOID(&curBank->allocTree, curBank, OT_Node, curBank->limitedKey[i]); if (result == 0) { /* failed */ DEBUG(children) kprintf(KR_OSTREAM, "SpaceBank: Unable to remove allocTree entry of " "node %d oid 0x"DW_HEX"\n", i, DW_HEX_ARG(curBank->limitedKey[i])); } } } } if (andStorage) DestroyStorage(curBank); else allocTree_mergeTrees(&parentBank->allocTree,&curBank->allocTree); /* unlink the bank we are blowing away */ curBank->parent->firstChild = curBank->nextSibling; /* blow it away */ free_bank(curBank); if (curBank == bank) bank = 0; if (next) curBank = next; else curBank = bank; } } return RC_OK;}/* FIXED BY SHAP -- this function has no need to grok the message structure. */uint32_tBankAllocObjects(Bank *bank, uint8_t type, uint8_t number, uint32_t kr){ int retval = 0; struct Bank_MOFrame *obj_frame; uint32_t count = 0; uint32_t i; uint64_t oids[3];#ifdef PARANOID if (number < 1 || number > 3) { kpanic(KR_OSTREAM, "SpaceBank: asked for strange number (%i) of" " objects of type %i\n", (int)number,(int)type); }#endif obj_frame = bank_getTypeFrame(bank, type); if (obj_frame == NULL) { /* single frame per object type -- preallocate all objects */ if (bank_ReserveFrames(bank, number) != RC_OK) { return RC_SB_LimitReached; } } while(count < number) { uint64_t newFrame; uint32_t retVal; /* take care of frame stuff */ if (obj_frame) { if (obj_frame->frameMap != 0u) { uint32_t offset = ffs(obj_frame->frameMap) - 1; OID oid = obj_frame->frameOid | offset; obj_frame->frameMap &= ~(1u << offset); oids[count++] = oid; DEBUG(alloc) kprintf(KR_OSTREAM, "Allocated %s oid=0x%08x%08x. Map now 0x%08x\n", type_name(type), (uint32_t) (oid >> 32), (uint32_t) oid, obj_frame->frameMap); continue; } /* need to grab another frame. -- reserve it first */ if (bank_ReserveFrames(bank, 1u) != RC_OK) goto cleanup; } DEBUG(alloc) kprintf(KR_OSTREAM, "spacebank: allocating new frame\n"); if (type == OT_Node) retVal = ob_AllocNodeFrame(bank, &newFrame); else retVal = ob_AllocPageFrame(bank, &newFrame); if (retVal != RC_OK) goto cleanup; /* got some space in newFrame */ if (bank != &bank0) allocTree_insertOIDs(&bank->allocTree, type, newFrame, objects_per_frame[type]); if (obj_frame) { /* shove the frame into the cache, then go back to the top to do the allocation */ obj_frame->frameOid = newFrame; obj_frame->frameMap = objects_map_mask[type]; continue; /*CONTINUE*/ } else { oids[count++] = newFrame; continue; /*CONTINUE*/ } } /* now oids contains the /count/ oids -- create the keys */ for (i = 0; i < number; i++) { DEBUG(alloc) kprintf(KR_OSTREAM, "spacebank: getting object key "DW_HEX"\n", DW_HEX_ARG(oids[i])); retval = range_getobjectkey(KR_SRANGE,type,oids[i],kr+i); DEBUG(alloc) kprintf(KR_OSTREAM, "spacebank: got back %x\n", retval); if (retval != RC_OK) { /* ack! we've got to undo everything! * note that we don't need to rescind the keys we made, since they * point to a zero object */ goto cleanup; } } bank->allocs[type] += number; return retval;cleanup: DEBUG(alloc) kdprintf(KR_OSTREAM, "spacebank: Out of frames.\n"); while (count--) bank_deallocOID(bank, type, oids[count]); return RC_SB_LimitReached;} uint32_tBankDeallocObjects(Bank *bank, uint8_t type, uint8_t count, uint32_t kr){ int i; uint32_t retval = (1<<count) - 1; /* assume failure until proven innocent. */#ifdef PARANOID if (count < 1 || count > 3) { kpanic(KR_OSTREAM, "SpaceBank: asked to dealloc strange number (%i) of" " objects of type %i\n", (int)count,(int)type); }#endif for (i = 0; i < count; i++) { OID oid; uint32_t obType; uint32_t k = kr + i; uint32_t code; code = range_identify(KR_SRANGE, k, &obType, &oid); if (code != RC_OK) { DEBUG(dealloc) kdprintf(KR_OSTREAM, "SpaceBank: range_identify failed (%u)\n", code); continue; } if (obType != type) { DEBUG(dealloc) kdprintf(KR_OSTREAM, "SpaceBank: Key %u has type %s, which is not the " "deallocation type (%s)\n", i, type_name(obType), type_name(type)); continue; } if (bank_containsOID(bank,type,oid)) { /* It's ours */ if (range_rescind(KR_SRANGE,k) != RC_OK) { continue; /* CONTINUE "not a strong key" */ } if ( ! bank_deallocOID(bank,type,oid)) { kpanic(KR_OSTREAM, "SpaceBank: Dealloc failed after contains succedded!\n"); } DEBUG(dealloc) { uint32_t result, nType; result = key_kt(k, &nType, 0); if (result != RC_OK || nType != RC_Void) { /* Didn't dealloc! */ kpanic(KR_OSTREAM, "spacebank: rescind successful but new keytype not " "Number\n" " (passed in type %s, new type %d, OID " "0x"DW_HEX")\n", type, nType, DW_HEX_ARG(oid)); } } retval &= ~(1u << i); /* mark success */ } else DEBUG (dealloc) { kdprintf(KR_OSTREAM, "Bank does not contain %s 0x"DW_HEX"\n", type_name(type), DW_HEX_ARG(oid)); } } return retval;}uint32_tBankIdentifyObjects(Bank *bank, uint8_t type, uint8_t count, uint32_t kr){ int i; uint32_t retval = (1<<count) - 1; /* assume failure until proven innocent. */#ifdef PARANOID if (count < 1 || count > 3) { kpanic(KR_OSTREAM, "SpaceBank: asked to dealloc strange number (%i) of" " objects of type %i\n", (int)count,(int)type); }#endif for (i = 0; i < count; i++) { OID oid; uint32_t obType; uint32_t k = kr + i; uint32_t code; code = range_identify(KR_SRANGE, k, &obType, &oid); if (code != RC_OK) { DEBUG(dealloc) kdprintf(KR_OSTREAM, "SpaceBank: range_identify failed (%u)\n", code); continue; } if (obType != type) { DEBUG(dealloc) kdprintf(KR_OSTREAM, "SpaceBank: Key %u has type %s, which is not the " "identification type (%s)\n", i, type_name(obType), type_name(type)); continue; } if (bank_containsOID(bank,type,oid)) { retval &= ~(1u << i); /* mark success */ } else DEBUG (dealloc) { kdprintf(KR_OSTREAM, "Bank does not contain %s 0x"DW_HEX"\n", type_name(type), DW_HEX_ARG(oid)); } } return retval;}uint32_tbank_containsOID(Bank *bank, uint8_t type, OID oid){ struct Bank_MOFrame *obj_frame; /* valid key slot */ uint64_t frameOff = EROS_FRAME_FROM_OID(oid); uint8_t subObj = EROS_OBNDX_IN_FRAME(oid); obj_frame = bank_getTypeFrame(bank, type); if (obj_frame) { if (obj_frame->frameMap != 0u && obj_frame->frameOid == frameOff) { /* bit is set implies object is free */ return !(obj_frame->frameMap & (1<<subObj)); } } return allocTree_checkForOID(&bank->allocTree,oid);}uint32_tbank_deallocOID(Bank *bank, uint8_t type, OID oid){ struct Bank_MOFrame *obj_frame; /* valid key slot */ uint64_t frameOff = EROS_FRAME_FROM_OID(oid); uint8_t subObj = EROS_OBNDX_IN_FRAME(oid); obj_frame = bank_getTypeFrame(bank, type); if (obj_frame) { if (obj_frame->frameMap != 0u && obj_frame->frameOid == frameOff) { if (obj_frame->frameMap & (1<<subObj)) kpanic(KR_OSTREAM, "Spacebank: (frame)dealloc passed already " "unallocated object!\n"); obj_frame->frameMap |= (1<<subObj); /* mark free */ if (obj_frame->frameMap == objects_map_mask[type]) { /* now the frame is empty -- return it */ uint32_t x; DEBUG(dealloc) kprintf(KR_OSTREAM, "Returning empty %s frame\n",type_name(type)); for (x = 0; x < objects_per_frame[type]; x++) { allocTree_removeOID(&bank->allocTree, bank, type, obj_frame->frameOid | x); obj_frame->frameMap &= ~(1u << x); } /* no need to return the frame, as allocTree_removeOID takes care of all of that. */ obj_frame->frameOid = 0ull; } bank->deallocs[type]++; return 1; } /* if (obj_frame->frameMap != 0u && frameOid == frameOff) */ } /* if (obj_frame) ... */ /* not in the frame cache -- try the tree */ if (! allocTree_removeOID(&bank->allocTree, bank, type, oid) ) { /* failed */ kprintf(KR_OSTREAM, "spacebank: oid 0x"DW_HEX" (%s) not in bank " "to dealloc\n", DW_HEX_ARG(oid), type_name(oid) ); return 0; } else { bank->deallocs[type]++; return 1; }}voidBankPreallType(Bank *bank, uint32_t type, uint64_t startOID, uint64_t number){ OID oid = startOID; uint32_t residual; uint32_t i; uint32_t obPerFrame = objects_per_frame[type]; DEBUG(init) kprintf(KR_OSTREAM, "Adding 0x%08x%08x %s\n", (uint32_t) (number>>32), (uint32_t) number, type_name(type)); residual = number; for (i = 0; i < number; i += obPerFrame, oid += EROS_OBJECTS_PER_FRAME) { uint32_t count = MIN(residual, obPerFrame); OID top = oid + obPerFrame; if (bank_ReserveFrames(bank, 1u) != RC_OK) { kpanic(KR_OSTREAM, "SpaceBank: Hit limit while preallocating space!\n"); } DEBUG(init) kprintf(KR_OSTREAM, "Adding oids [0x"DW_HEX":0x"DW_HEX") resid %d count %d\n", DW_HEX_ARG(oid), DW_HEX_ARG(top), residual, count); allocTree_insertOIDs(&bank->allocTree, type, oid, obPerFrame); /* If last frame, set up residual in active alloc word * Test can only be true if obPerFrame > 1. */ if (count && count < obPerFrame) { struct Bank_MOFrame *obj_frame; uint32_t obMask; /* get the type frame for the residual */ obj_frame = bank_getTypeFrame(bank, type); if (!obj_frame) { /* not a recognized multi-page object */ kpanic(KR_OSTREAM, "Spacebank: Fatal error: bank_preall_type got " "unsupported >1 per page type (%i)!\n", type); break; /* BREAK */ } if (obj_frame->frameMap != 0u) { uint32_t x; /* deallocate old stuff */ while (obj_frame->frameMap != 0u) { x = ffs(obj_frame->frameMap); allocTree_removeOID(&bank->allocTree, bank, type, obj_frame->frameOid | x); obj_frame->frameMap &= ~(1u << x); } } obMask = (1u << obPerFrame) - 1; obj_frame->frameOid = oid; /* now mark the first /count/ objects allocated */ obj_frame->frameMap = ~( (1u << count) - 1 ); /* mask out the extraneous bits */ obj_frame->frameMap &= obMask; DEBUG(init) kdprintf(KR_OSTREAM, "Residual %s frame: oid=0x"DW_HEX" map: 0x%08x\n", type_name(type), DW_HEX_ARG(obj_frame->frameOid), obj_frame->frameMap); } residual -= count; } return;}static Bank *FreeBanks = 0;Bank *alloc_bank(void){ Bank *newBank; if (FreeBanks) { newBank = FreeBanks; FreeBanks = *((Bank**) FreeBanks); } else newBank = (Bank *) malloc(sizeof(Bank)); if (!newBank) return NULL; bzero(newBank, sizeof(Bank*)); return newBank;}voidfree_bank(Bank * b){ *((Bank **)b) = FreeBanks; FreeBanks = b;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -