diff options
author | Alexis211 <alexis211@gmail.com> | 2009-11-28 12:36:01 +0100 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2009-11-28 12:36:01 +0100 |
commit | 4d0939e2853ffd9d49b83524923351f9776866d7 (patch) | |
tree | cbaf59ee30e60f268a03ea28f9cbdf2b278f2fcf /Source/Kernel/VFS/BlockCache.class.cpp | |
parent | bcb8807209f4aa7da4d7fec54857599b60c87947 (diff) | |
download | Melon-4d0939e2853ffd9d49b83524923351f9776866d7.tar.gz Melon-4d0939e2853ffd9d49b83524923351f9776866d7.zip |
Caching mechanism added and floppy driver fixed on qemu/vbox
Diffstat (limited to 'Source/Kernel/VFS/BlockCache.class.cpp')
-rw-r--r-- | Source/Kernel/VFS/BlockCache.class.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/Source/Kernel/VFS/BlockCache.class.cpp b/Source/Kernel/VFS/BlockCache.class.cpp new file mode 100644 index 0000000..458faf6 --- /dev/null +++ b/Source/Kernel/VFS/BlockCache.class.cpp @@ -0,0 +1,89 @@ +#include <DeviceManager/Time.ns.h> + +template <typename T> +BlockCache<T>::BlockCache(T* dev) { + m_dev = dev; + m_count = 0; +} + +template <typename T> +BlockCache<T>::~BlockCache() { + sync(); + m_count = 0; + delete m_cache; + delete m_cacheInfo; +} + +template <typename T> +void BlockCache<T>::sync() { + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].dirty) m_dev->writeBlocks(m_cacheInfo[i].id, 1, m_cache + (i * m_dev->getBlockSize())); + } +} + +template <typename T> +void BlockCache<T>::init(u32int count) { + m_count = count; + m_cacheInfo = new cached_block_t[count]; + for (u32int i = 0; i < m_count; i++) { + m_cacheInfo[i].id = 0; + m_cacheInfo[i].lastuse = 0; + m_cacheInfo[i].dirty = false; + } + m_cache = (u8int*)Mem::alloc(m_count * m_dev->getBlockSize()); +} + +template <typename T> +bool BlockCache<T>::setCache(u64int block, u8int* data, bool dirty) { + u32int best = 0; + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].id == block) { + best = i; + break; + } + if (m_cacheInfo[i].lastuse < m_cacheInfo[best].lastuse) best = i; + } + if (best >= m_count) return false; + if (m_cacheInfo[best].dirty && (m_cacheInfo[best].id != block or !dirty)) + m_dev->writeBlocks(m_cacheInfo[best].id, 1, m_cache + (best * m_dev->getBlockSize())); + m_cacheInfo[best].id = block; + m_cacheInfo[best].lastuse = Time::uptime(); + m_cacheInfo[best].dirty = dirty; + memcpy(m_cache + (best * m_dev->getBlockSize()), data, m_dev->getBlockSize()); + return true; +} + +template <typename T> +bool BlockCache<T>::getCache(u64int block, u8int* data) { + for (u32int i = 0; i < m_count; i++) { + if (m_cacheInfo[i].id == block && m_cacheInfo[i].lastuse != 0) { + m_cacheInfo[i].lastuse = Time::uptime(); + memcpy(data, m_cache + (i * m_dev->getBlockSize()), m_dev->getBlockSize()); + return true; + } + } + return false; +} + +template <typename T> +bool BlockCache<T>::readBlocks(u64int startblock, u32int count, u8int* data) { + if (count == 1) { + if (getCache(startblock, data)) return true; + if (!m_dev->readBlocks(startblock, count, data)) return false; + setCache(startblock, data); + return true; + } else { + return m_dev->readBlocks(startblock, count, data); + } +} + +template <typename T> +bool BlockCache<T>::writeBlocks(u64int startblock, u32int count, u8int* data) { + if (m_dev->readOnly()) return false; + if (count == 1) { + if (!setCache(startblock, data, true)) return m_dev->writeBlocks(startblock, count, data); + return true; + } else { + return m_dev->writeBlocks(startblock, count, data); + } +} |