mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-23 09:46:04 -05:00
60d25f0f4a
The scheduler now operates on threads, rather than on processes. Each process has a main thread, and can have any number of additional threads. The process exits when the main thread exits. This patch doesn't actually spawn any additional threads, it merely does all the plumbing needed to make it possible. :^)
140 lines
4.2 KiB
C++
140 lines
4.2 KiB
C++
#include "DiskBackedFileSystem.h"
|
|
#include "i386.h"
|
|
#include <AK/InlineLRUCache.h>
|
|
#include <Kernel/Process.h>
|
|
|
|
//#define DBFS_DEBUG
|
|
|
|
struct BlockIdentifier {
|
|
unsigned fsid { 0 };
|
|
unsigned index { 0 };
|
|
|
|
bool operator==(const BlockIdentifier& other) const { return fsid == other.fsid && index == other.index; }
|
|
};
|
|
|
|
namespace AK {
|
|
|
|
template<>
|
|
struct Traits<BlockIdentifier> {
|
|
static unsigned hash(const BlockIdentifier& block_id) { return pair_int_hash(block_id.fsid, block_id.index); }
|
|
static void dump(const BlockIdentifier& block_id) { kprintf("[block %02u:%08u]", block_id.fsid, block_id.index); }
|
|
};
|
|
|
|
}
|
|
|
|
class CachedBlock : public InlineLinkedListNode<CachedBlock> {
|
|
public:
|
|
CachedBlock(const BlockIdentifier& block_id, const ByteBuffer& buffer)
|
|
: m_key(block_id)
|
|
, m_buffer(buffer)
|
|
{
|
|
}
|
|
|
|
BlockIdentifier m_key;
|
|
CachedBlock* m_next { nullptr };
|
|
CachedBlock* m_prev { nullptr };
|
|
|
|
ByteBuffer m_buffer;
|
|
};
|
|
|
|
Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>& block_cache()
|
|
{
|
|
static Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>* s_cache;
|
|
if (!s_cache)
|
|
s_cache = new Lockable<InlineLRUCache<BlockIdentifier, CachedBlock>>;
|
|
return *s_cache;
|
|
}
|
|
|
|
DiskBackedFS::DiskBackedFS(Retained<DiskDevice>&& device)
|
|
: m_device(move(device))
|
|
{
|
|
}
|
|
|
|
DiskBackedFS::~DiskBackedFS()
|
|
{
|
|
}
|
|
|
|
bool DiskBackedFS::write_block(unsigned index, const ByteBuffer& data)
|
|
{
|
|
#ifdef DBFS_DEBUG
|
|
kprintf("DiskBackedFileSystem::write_block %u, size=%u\n", index, data.size());
|
|
#endif
|
|
ASSERT(data.size() == block_size());
|
|
|
|
{
|
|
LOCKER(block_cache().lock());
|
|
if (auto* cached_block = block_cache().resource().get({ fsid(), index }))
|
|
cached_block->m_buffer = data;
|
|
}
|
|
DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
|
|
return device().write(base_offset, block_size(), data.pointer());
|
|
}
|
|
|
|
bool DiskBackedFS::write_blocks(unsigned index, unsigned count, const ByteBuffer& data)
|
|
{
|
|
#ifdef DBFS_DEBUG
|
|
kprintf("DiskBackedFileSystem::write_blocks %u x%u\n", index, count);
|
|
#endif
|
|
// FIXME: Maybe reorder this so we send out the write commands before updating cache?
|
|
{
|
|
LOCKER(block_cache().lock());
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
if (auto* cached_block = block_cache().resource().get({ fsid(), index + i }))
|
|
cached_block->m_buffer = data.slice(i * block_size(), block_size());
|
|
}
|
|
}
|
|
DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
|
|
return device().write(base_offset, count * block_size(), data.pointer());
|
|
}
|
|
|
|
ByteBuffer DiskBackedFS::read_block(unsigned index) const
|
|
{
|
|
#ifdef DBFS_DEBUG
|
|
kprintf("DiskBackedFileSystem::read_block %u\n", index);
|
|
#endif
|
|
{
|
|
LOCKER(block_cache().lock());
|
|
if (auto* cached_block = block_cache().resource().get({ fsid(), index }))
|
|
return cached_block->m_buffer;
|
|
}
|
|
|
|
auto buffer = ByteBuffer::create_uninitialized(block_size());
|
|
//kprintf("created block buffer with size %u\n", block_size());
|
|
DiskOffset base_offset = static_cast<DiskOffset>(index) * static_cast<DiskOffset>(block_size());
|
|
auto* buffer_pointer = buffer.pointer();
|
|
bool success = device().read(base_offset, block_size(), buffer_pointer);
|
|
ASSERT(success);
|
|
ASSERT(buffer.size() == block_size());
|
|
{
|
|
LOCKER(block_cache().lock());
|
|
block_cache().resource().put({ fsid(), index }, CachedBlock({ fsid(), index }, buffer));
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
ByteBuffer DiskBackedFS::read_blocks(unsigned index, unsigned count) const
|
|
{
|
|
if (!count)
|
|
return nullptr;
|
|
if (count == 1)
|
|
return read_block(index);
|
|
auto blocks = ByteBuffer::create_uninitialized(count * block_size());
|
|
byte* out = blocks.pointer();
|
|
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
auto block = read_block(index + i);
|
|
if (!block)
|
|
return nullptr;
|
|
memcpy(out, block.pointer(), block.size());
|
|
out += block_size();
|
|
}
|
|
|
|
return blocks;
|
|
}
|
|
|
|
void DiskBackedFS::set_block_size(unsigned block_size)
|
|
{
|
|
if (block_size == m_block_size)
|
|
return;
|
|
m_block_size = block_size;
|
|
}
|