void CopiedSpace::doneFillingBlock(CopiedBlock* block) { ASSERT(block); ASSERT(block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); ASSERT(m_inCopyingPhase); if (block->m_offset == block->payload()) { recycleBlock(block); return; } { MutexLocker locker(m_toSpaceLock); m_toSpace->push(block); m_toSpaceSet.add(block); m_toSpaceFilter.add(reinterpret_cast<Bits>(block)); } { MutexLocker locker(m_loanedBlocksLock); ASSERT(m_numberOfLoanedBlocks > 0); m_numberOfLoanedBlocks--; if (!m_numberOfLoanedBlocks) m_loanedBlocksCondition.signal(); } }
/** * Refresh the physical pages associated with the file table. * Any logical blocks marked for deletion on those pages are recycled back to UNUSED. * * @return MICROBIT_OK on success. */ int MicroBitFileSystem::recycleFileTable() { bool pageRecycled = false; for (uint16_t block = 0; block < fileSystemSize; block++) { // if we just crossed a page boundary, reset pageRecycled. if (block % (PAGE_SIZE / MBFS_BLOCK_SIZE) == 0) pageRecycled = false; if (fileSystemTable[block] == MBFS_DELETED && !pageRecycled) { recycleBlock(block); pageRecycled = true; } } // now, recycle the FileSystemTable itself, upcycling entries marked as DELETED to UNUSED as we go. for (uint16_t block = 0; getPage(block) < (uint32_t *)rootDirectory; block += PAGE_SIZE / MBFS_BLOCK_SIZE) recycleBlock(block); return MICROBIT_OK; }
void Block::release(){ if(this->shapes != NULL) for(size_t i = 0 ; i != 4 ; i++){ if(this->shapes[this->currShape-1] != NULL){ recycleBlock(this->shapes[this->currShape-1],this->height); this->currShape = this->currShape >= 4 ? 1 : 1 + this->currShape; size_t temp = this->height; this->height = this->width; this->width = temp; } } this->rect = this->getRect(); if(rect != NULL) delete this->rect; delete [] this->shapes; }
/** * Allocate a free DiretoryEntry in the given directory, extending and refreshing the directory block if necessary. * * @param directory The directory to add a DirectoryEntry to * @return A pointer to the new DirectoryEntry for the given file, or NULL if it was not possible to allocated resources. */ DirectoryEntry* MicroBitFileSystem::createDirectoryEntry(DirectoryEntry *directory) { Directory *dir; uint16_t block; DirectoryEntry *dirent; DirectoryEntry *empty = NULL; DirectoryEntry *invalid = NULL; // Try to find an unused entry in the directory. block = directory->first_block; dir = (Directory *)getBlock(block); dirent = &dir->entry[0]; // Iterate through the directory entries until we find and unused entry, or run out of space. while (1) { // Scan through each of the blocks in the directory if ((uint32_t)(dirent+1) > (uint32_t)dir + MBFS_BLOCK_SIZE) { block = getNextFileBlock(block); if (block == MBFS_EOF) break; dir = (Directory *)getBlock(block); dirent = &dir->entry[0]; } // If we find an empty slot, use that. if (dirent->flags & MBFS_DIRECTORY_ENTRY_FREE) { empty = dirent; break; } // Record the first invalid block we find (used, but then deleted). if ((dirent->flags & MBFS_DIRECTORY_ENTRY_VALID) == 0 && invalid == NULL) invalid = dirent; // Move onto the next entry. dirent++; } // Now choose the best available slot, giving preference to entries that would avoid a FLASH page erase opreation. dirent = NULL; // Ideally, choose an unused entry within an existing block. if (empty) { dirent = empty; } // if not possible, try to re-use a second-hand block that has been freed. This will result in an erase operation of the block, // but will not consume any more resources. else if (invalid) { dirent = invalid; uint16_t b = getBlockNumber(dirent); recycleBlock(b, MBFS_BLOCK_TYPE_DIRECTORY); } // If nothing is available, extend the directory with a new block. else { // Allocate a new logical block uint16_t newBlock = getFreeBlock(); if (newBlock == 0) return NULL; // Append this to the directory uint16_t lastBlock = directory->first_block; while (getNextFileBlock(lastBlock) != MBFS_EOF) lastBlock = getNextFileBlock(lastBlock); // Append the block. fileTableWrite(lastBlock, newBlock); fileTableWrite(newBlock, MBFS_EOF); dirent = (DirectoryEntry *)getBlock(newBlock); } return dirent; }