# HG changeset patch # User Paul Boddie # Date 1611356482 -3600 # Node ID e28bfa82013bfc14e7075a66ee9d32d2b454933a # Parent 0594350368df428fcd7a02fa637b84127ee9d477 Introduced pager, page mapper, pages (page collection), accessor and access map in order to perform testing of these components. diff -r 0594350368df -r e28bfa82013b Makefile --- a/Makefile Fri Jan 22 23:59:13 2021 +0100 +++ b/Makefile Sat Jan 23 00:01:22 2021 +0100 @@ -22,9 +22,12 @@ SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC)) PLAIN_SRC_CC = \ + access_map.cc accessor.cc \ dstest_server.cc flexpage.cc ipc.cc \ memory.cc memory_map.cc memory_utils.cc \ - region.cc resource.cc simple_pager.cc + page_mapper.cc page_queue.cc pager.cc pages.cc \ + region.cc resource.cc simple_pager.cc \ + test_file_accessor.cc # Normal definitions. diff -r 0594350368df -r e28bfa82013b access_map.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/access_map.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,134 @@ +#include "access_map.h" + +/* Return the flexpage supporting 'position'. */ + +Flexpage *AccessMap::find(offset_t position) +{ + std::lock_guard guard(_lock); + + _AccessMap::iterator it = _flexpages.upper_bound(position); + + if ((_flexpages.size() > 0) && (it != _flexpages.begin())) + { + it--; + + if (it->second->supports_position(position)) + return it->second; + } + + return NULL; +} + +/* Insert a mapping for 'flexpage'. */ + +void AccessMap::insert(Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage)); +} + +/* Remove the mapping supported by 'flexpage'. + + The flexpage may have obtained by another mapper before being purged from + this object's mapping and before being purged from the queue (and thus + disassociated from this mapper), leaving an opportunity for another mapper to + now be removing it here. In such a situation, flushing has already occurred + and will not be performed again. */ + +bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + _AccessMap::iterator it = _flexpages.find(flexpage->base_offset); + + if (it != _flexpages.end()) + { + owner->flush(flexpage, true); + _flexpages.erase(flexpage->base_offset); + return true; + } + + return false; +} + +/* Purge all flexpages, using the 'owner' to flush their contents and + 'pages' to make the flexpages available to other accessors. */ + +void AccessMap::purge(PageOwner *owner, Pages *pages) +{ + std::lock_guard guard(_lock); + + _AccessMap::iterator it = _flexpages.begin(), entry; + + while (it != _flexpages.end()) + { + entry = it; + it++; + + Flexpage *flexpage = entry->second; + + /* Some flexpages may be unavailable in the queue. Only those + that can be reserved should be flushed and made available + again. */ + + if (pages->reserve(owner, flexpage)) + { + owner->flush(flexpage, true); + pages->release(flexpage); + _flexpages.erase(entry); + } + } +} + +/* Flush flexpages in the given range from 'start' with 'size', using 'owner' + and 'pages'. */ + +void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages) +{ + offset_t end = start + size; + + std::lock_guard guard(_lock); + + /* The start may be within an existing flexpage where the flexpage size is a + page multiple. */ + + _AccessMap::iterator it = _flexpages.upper_bound(start), entry; + + if ((_flexpages.size() > 0) && (it != _flexpages.begin())) + it--; + + /* Inspect flexpages at or after start until end. */ + + while (it != _flexpages.end()) + { + entry = it; + it++; + + Flexpage *flexpage = entry->second; + + if (flexpage->base_offset >= end) + break; + + /* Attempt to flush each flexpage, releasing ones that are no longer + needed. */ + + if (pages->reserve(owner, flexpage)) + { + owner->flush(flexpage, false); + + /* Where no users of the flexpage persist, release the flexpage for + reuse and remove this entry. */ + + if (!flexpage->valid()) + { + pages->release(flexpage); + _flexpages.erase(entry); + } + else + pages->queue(owner, flexpage); + } + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b access_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/access_map.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,35 @@ +#pragma once + +#include "flexpage.h" +#include "page_owner.h" +#include "pages.h" + +#include +#include + +/* Collection types. */ + +typedef std::map _AccessMap; +typedef std::pair _AccessMapEntry; + +/* A mapping from file positions to flexpages. */ + +class AccessMap +{ +protected: + _AccessMap _flexpages; + std::mutex _lock; + +public: + Flexpage *find(offset_t position); + + void insert(Flexpage *flexpage); + + bool remove(PageOwner *owner, Flexpage *flexpage); + + void purge(PageOwner *owner, Pages *pages); + + void flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessor.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,27 @@ +#include "accessor.h" + +Accessor::Accessor(fileid_t fileid, offset_t size) +: _size(size), fileid(fileid) +{ +} + +/* Return the size of the file. */ + +offset_t Accessor::get_size() +{ + return _size; +} + +/* Perform any closing operation on the file. */ + +void Accessor::close() +{ +} + +/* Perform any opening operation on the file. */ + +void Accessor::open() +{ +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/accessor.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "flexpage.h" + +/* A file accessor, providing flexpages corresponding to file regions. */ + +class Accessor +{ +protected: + offset_t _size; + +public: + fileid_t fileid; + + explicit Accessor(fileid_t fileid, offset_t size=0); + + virtual offset_t get_size(); + + virtual void close(); + + virtual void open(); + + /* Data transfer methods. */ + + virtual void fill(Flexpage *flexpage) = 0; + + virtual void flush(Flexpage *flexpage) = 0; +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b dstest_client.cc --- a/dstest_client.cc Fri Jan 22 23:59:13 2021 +0100 +++ b/dstest_client.cc Sat Jan 23 00:01:22 2021 +0100 @@ -52,7 +52,7 @@ { printf("10 bytes from %p...\n", (memory + offset)); fwrite((memory + offset), sizeof(char), 10, stdout); - fputs("\n", stdout); + fwrite("\n", sizeof(char), 1, stdout); } return 0; diff -r 0594350368df -r e28bfa82013b dstest_server.cc --- a/dstest_server.cc Fri Jan 22 23:59:13 2021 +0100 +++ b/dstest_server.cc Sat Jan 23 00:01:22 2021 +0100 @@ -29,21 +29,10 @@ #include #include "dataspace_server.h" -#include "simple_pager.h" - - - -/* Component interface. */ - -class DataspaceServer : public SimplePager -{ -public: - explicit DataspaceServer(Memory *memory) - : SimplePager(memory) - { - memset((void *) _region->start, (int) 'a', PAGE_SIZE); - } -}; +#include "page_mapper.h" +#include "pager.h" +#include "pages.h" +#include "test_file_accessor.h" @@ -51,11 +40,13 @@ { /* Some memory. */ - Memory memory(10); + Memory mem(10); + Pages pages(&mem); + TestFileAccessor a(123UL); + PageMapper m(&a, &pages); + Pager pager(&m); - /* Dataspace encapsulation. */ - - DataspaceServer obj(&memory); + pager.mmap(0, page(10)); /* Server capability. */ @@ -63,7 +54,7 @@ /* Register a server associating it with the given object. */ - long err = ipc_server_bind("server", (l4_umword_t) &obj, &server); + long err = ipc_server_bind("server", (l4_umword_t) &pager, &server); if (err) { @@ -73,7 +64,7 @@ /* Wait for messages, dispatching to the handler. */ - ipc_server_loop(Dataspace_expected_items, &obj, + ipc_server_loop(Dataspace_expected_items, &pager, (ipc_server_handler_type) handle_Dataspace); return 0; diff -r 0594350368df -r e28bfa82013b page_mapper.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/page_mapper.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,166 @@ +#include "ipc.h" +#include "page_mapper.h" + + + +PageMapper::PageMapper(Accessor *accessor, Pages *pages) +: _accessor(accessor), _pages(pages), _attached(0) +{ +} + +/* Accounting methods. */ + +/* Attach a pager, opening the accessor if required. */ + +void PageMapper::attach() +{ + std::lock_guard guard(_lock); + + if (!_attached) + _accessor->open(); + + _attached += 1; +} + +/* Detach a pager, purging active pages and closing the accessor if no more + pagers are attached. Return whether any pagers are still attached. */ + +unsigned int PageMapper::detach() +{ + std::lock_guard guard(_lock); + + if (_attached) + { + _attached -= 1; + + if (!_attached) + { + _map.purge(this, _pages); + _accessor->close(); + } + } + + return _attached; +} + +/* Interface for the pager. */ + +/* Return a flexpage providing access to the indicated file 'offset'. + + The returned flexpage will either be an existing, compatible flexpage or a + completely new flexpage. + + This method locks the accessor to prevent concurrent queries with the + same details, with the lock held until the queue or flush_all operations + release the lock. */ + +Flexpage *PageMapper::get(offset_t offset) +{ + _lock.lock(); + + Flexpage *f = find(offset); + + if (f == NULL) + f = flexpage(offset); + + f->increment(); + return f; +} + +/* Queue the given 'flexpage' in the page collection, making it available for + eventual reuse. + + This method unlocks the accessor. */ + +void PageMapper::queue(Flexpage *flexpage) +{ + _pages->queue(this, flexpage); + + _lock.unlock(); +} + +/* Flush pages in the given range from 'start' with 'size'. */ + +void PageMapper::flush_all(offset_t start, offset_t size) +{ + std::lock_guard guard(_lock); + + _map.flush_all(start, size, this, _pages); +} + +/* Return the maximum extent of the mapped resource. */ + +offset_t PageMapper::get_data_size() +{ + return _accessor->get_size(); +} + +/* Internal flexpage retrieval methods. */ + +/* Find an existing flexpage for 'offset'. Where the accessor has registered a + compatible flexpage, an attempt is made to reserve it in the page collection; + if this succeeds, the flexpage is returned. Otherwise, NULL is returned. */ + +Flexpage *PageMapper::find(offset_t offset) +{ + Flexpage *flexpage = _map.find(offset); + + /* Between finding and reserving a flexpage, there is a possibility that + another accessor might acquire the flexpage, issue it, and even purge + it. */ + + if ((flexpage != NULL) && _pages->reserve(this, flexpage)) + return flexpage; + else + return NULL; +} + +/* Obtain a new flexpage for the file 'offset'. If the page collection is unable + to obtain a completely new flexpage, an existing flexpage is requested from + the page collection and recycled. + + The obtained flexpage is filled with content. */ + +Flexpage *PageMapper::flexpage(offset_t offset) +{ + Flexpage *flexpage = _pages->flexpage(); + + /* Obtain an existing flexpage and reuse it. */ + + if (flexpage == NULL) + flexpage = _pages->remove(); + + flexpage->reset(offset); + + fill(flexpage); + _map.insert(flexpage); + return flexpage; +} + +/* Interface for the page collection. */ + +/* Remove the record of 'flexpage' in this accessor, flushing its content. */ + +void PageMapper::remove(Flexpage *flexpage) +{ + _map.remove(this, flexpage); +} + +/* Data transfer methods. */ + +void PageMapper::fill(Flexpage *flexpage) +{ + _accessor->fill(flexpage); +} + +void PageMapper::flush(Flexpage *flexpage, bool purge) +{ + if (flexpage->decrement() || purge) + { + _accessor->flush(flexpage); + ipc_unmap_flexpage(flexpage); + flexpage->invalidate(); + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b page_mapper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/page_mapper.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,56 @@ +#pragma once + +#include "access_map.h" +#include "accessor.h" +#include "page_owner.h" + +#include + +/* A file mapper, associating flexpages with file regions. */ + +class PageMapper : public PageOwner +{ +protected: + AccessMap _map; + Accessor *_accessor; + Pages *_pages; + unsigned int _attached; + std::mutex _lock; + + /* Internal flexpage retrieval methods. */ + + Flexpage *find(offset_t offset); + + Flexpage *flexpage(offset_t offset); + +public: + explicit PageMapper(Accessor *accessor, Pages *pages); + + /* Accounting methods. */ + + void attach(); + + unsigned int detach(); + + /* Interface for the pager. */ + + Flexpage *get(offset_t offset); + + void queue(Flexpage *flexpage); + + void flush_all(offset_t start, offset_t size); + + offset_t get_data_size(); + + /* Data transfer methods, implementing PageOwner. */ + + void fill(Flexpage *flexpage); + + void flush(Flexpage *flexpage, bool purge); + + /* Interface for the page collection, implementing PageOwner. */ + + void remove(Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b page_owner.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/page_owner.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,30 @@ +#pragma once + +#include "flexpage.h" + +/* The owner of a flexpage. */ + +class PageOwner +{ +public: + virtual ~PageOwner() + { + } + + virtual void fill(Flexpage *flexpage) + { + (void) flexpage; + } + + virtual void flush(Flexpage *flexpage, bool purge) + { + (void) flexpage; (void) purge; + } + + virtual void remove(Flexpage *flexpage) + { + (void) flexpage; + } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b page_queue.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/page_queue.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,103 @@ +#include "page_queue.h" + +#include + +/* Keep waiting for a potential queue non-empty condition. + Then, attempt to pop an entry from the queue. */ + +void PageQueue::pop(PageOwner **owner, Flexpage **flexpage) +{ + std::unique_lock guard(_lock); + QueueEntry entry; + + while (1) + { + if (_pop(&entry)) + { + *owner = entry.owner; + *flexpage = entry.flexpage; + return; + } + else + _counter.wait(guard); + } +} + +/* Check the queue for entries, returning false if no entries are available, + returning true and providing the details if an entry can be removed from the + front of the queue. */ + +bool PageQueue::_pop(QueueEntry *entry) +{ + if (_queue.empty()) + return false; + + *entry = _queue.front(); + _queue.pop_front(); + + /* Remove any position reference for the flexpage. */ + + Positions::iterator position = _positions.find(entry->flexpage); + + if (position != _positions.end()) + _positions.erase(position); + + return true; +} + +/* Push an entry for the given owner and flexpage to the queue. */ + +void PageQueue::push(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + /* Record the entry and a position reference for the flexpage. */ + + _queue.push_back((QueueEntry) {flexpage, owner}); + + Queue::iterator last = _queue.end(); + last--; + _positions.insert(Position(flexpage, last)); + + _counter.notify_one(); +} + +/* Push an entry to the front of the queue. */ + +void PageQueue::push_front(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + _queue.push_back((QueueEntry) {flexpage, owner}); + _positions.insert(Position(flexpage, _queue.begin())); + + _counter.notify_one(); +} + +/* Remove an entry for the given owner and flexpage from the queue. */ + +bool PageQueue::remove(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + Positions::iterator position = _positions.find(flexpage); + + if (position == _positions.end()) + return false; + + /* The found owner may be different from the requesting owner or even NULL + if another owner has acquired and then purged its pages. Such a purged + flexpage is not immediately usable, however. */ + + Queue::iterator entry = position->second; + + if ((entry->owner == NULL) || (entry->owner != owner)) + return false; + + _queue.erase(entry); + _positions.erase(position); + + return true; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b page_queue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/page_queue.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include + +#include "flexpage.h" +#include "page_owner.h" + + + +/* Collection types. */ + +typedef struct { Flexpage *flexpage; PageOwner *owner; } QueueEntry; +typedef std::list Queue; + +typedef std::pair Position; +typedef std::map Positions; + + + +/* A queue of issued pages. */ + +class PageQueue +{ +protected: + Queue _queue; + Positions _positions; + + std::mutex _lock; + std::condition_variable _counter; + + bool _pop(QueueEntry *entry); + +public: + void pop(PageOwner **owner, Flexpage **flexpage); + + void push(PageOwner *owner, Flexpage *flexpage); + + void push_front(PageOwner *owner, Flexpage *flexpage); + + bool remove(PageOwner *owner, Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pager.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,61 @@ +#include "dataspace_server.h" +#include "ipc.h" +#include "pager.h" + + + +Pager::Pager(PageMapper *mapper) +: _start(0), _size(0), _mapper(mapper) +{ + _mapper->attach(); +} + +void Pager::close() +{ + _mapper->detach(); +} + +PagerState Pager::mmap(offset_t start, offset_t size) +{ + _start = trunc(start, PAGE_SIZE); + _size = round(start + size, PAGE_SIZE) - _start; + + return PagerState(_start, _size, 0); +} + +/* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot' + (flexpage offset). */ + +long Pager::map(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region) +{ + offset_t file_offset = _start + offset; + offset_t max_offset = _start + _size; + Flexpage *flexpage = _mapper->get(file_offset); + + /* Issue the flexpage via the IPC system. */ + + long err = ipc_prepare_flexpage(flexpage, file_offset, max_offset, hot_spot, flags, region); + + if (err) + return err; + + err = complete_Dataspace_map(*region); + + if (err) + return err; + + /* After the flexpage is issued, it is queued for future reuse. */ + + _mapper->queue(flexpage); + + return IPC_MESSAGE_SENT; +} + +/* Return the total size of the data. */ + +offset_t Pager::get_data_size() +{ + return _mapper->get_data_size(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pager.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,34 @@ +#pragma once + +#include "dataspace_interface.h" +#include "page_mapper.h" +#include "pager_state.h" +#include "resource.h" + + + +/* A pager exposing a dataspace. */ + +class Pager : public Dataspace, public Resource +{ +protected: + offset_t _start, _size; + PageMapper *_mapper; + +public: + explicit Pager(PageMapper *mapper); + + void close(); + + /* Paging methods. */ + + long map(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region); + + /* Limit methods. */ + + offset_t get_data_size(); + + PagerState mmap(offset_t start, offset_t size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b pager_state.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pager_state.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,18 @@ +#pragma once + +/* A package of resource region details. */ + +class PagerState +{ +public: + offset_t data_start, data_size, populated_size; + + explicit PagerState(offset_t data_start, offset_t data_size, + offset_t populated_size) + : data_start(data_start), data_size(data_size), + populated_size(populated_size) + { + } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b pages.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pages.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,64 @@ +#include "pages.h" + +Pages::Pages(Memory *memory) +: _memory(memory) +{ +} + +Pages::Pages() +{ + _memory = new Memory(); +} + +/* Remove the first flexpage in the queue. If its owner exists, remove it from + the owner (retiring the content). Return the flexpage for reuse. */ + +Flexpage *Pages::remove() +{ + PageOwner *owner; + Flexpage *flexpage; + + _queue.pop(&owner, &flexpage); + + if (owner != NULL) + owner->remove(flexpage); + + return flexpage; +} + +/* Reserve 'flexpage' by removing it from this collection. */ + +bool Pages::reserve(PageOwner *owner, Flexpage *flexpage) +{ + return _queue.remove(owner, flexpage); +} + +/* Obtain a new flexpage. Return the flexpage or None if no new flexpage could + be created. */ + +Flexpage *Pages::flexpage() +{ + Region *region = _memory->region(); + + if (region != NULL) + return new Flexpage(region); + else + return NULL; +} + +/* Queue an entry associating the given 'owner' and 'flexpage'. */ + +void Pages::queue(PageOwner *owner, Flexpage *flexpage) +{ + _queue.push(owner, flexpage); +} + +/* Push an entry for 'flexpage' without owner association for immediate + reuse. */ + +void Pages::release(Flexpage *flexpage) +{ + _queue.push_front(NULL, flexpage); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b pages.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pages.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,34 @@ +#pragma once + +#include "flexpage.h" +#include "memory.h" +#include "page_owner.h" +#include "page_queue.h" + + + +/* A page collection. */ + +class Pages +{ +protected: + PageQueue _queue; + Memory *_memory; + +public: + explicit Pages(Memory *memory); + + explicit Pages(); + + Flexpage *remove(); + + bool reserve(PageOwner *owner, Flexpage *flexpage); + + Flexpage *flexpage(); + + void queue(PageOwner *owner, Flexpage *flexpage); + + void release(Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b test_file_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_file_accessor.cc Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,54 @@ +#include +#include + +#include "test_file_accessor.h" + +TestFileAccessor::TestFileAccessor(fileid_t fileid, offset_t size) +: Accessor(fileid, size) +{ +} + +/* Data transfer methods. */ + +void TestFileAccessor::fill(Flexpage *flexpage) +{ + Region *region = flexpage->region; + offset_t filepos = flexpage->base_offset; + + /* Tag the region with file state. */ + + region->fill(fileid, filepos); + + /* Write some data to each page of the flexpage in each region. This + allows each page to be tested regardless of how large each flexpage + or region is. */ + + offset_t addr = flexpage->base_addr; + offset_t limit = addr + flexpage->size; + + while (addr < limit) + { + /* Overwrite enough of any previous data to make the new data + readable. */ + + char tag[32]; + + sprintf(tag, "%ld:%ld", fileid, filepos); + + memset((void *) addr, 0, strlen(tag) + 1); + strcpy((char *) addr, tag); + + filepos += PAGE_SIZE; + addr += PAGE_SIZE; + } +} + +void TestFileAccessor::flush(Flexpage *flexpage) +{ + /* NOTE: Flushing would not necessarily blank the region as this does. + Also, a real flush operation would store the memory content. */ + + flexpage->region->flush(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 0594350368df -r e28bfa82013b test_file_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_file_accessor.h Sat Jan 23 00:01:22 2021 +0100 @@ -0,0 +1,19 @@ +#pragma once + +#include "accessor.h" + +/* A file accessor, providing flexpages corresponding to file regions. */ + +class TestFileAccessor : public Accessor +{ +public: + explicit TestFileAccessor(fileid_t fileid, offset_t size=0); + + /* Data transfer methods. */ + + virtual void fill(Flexpage *flexpage); + + virtual void flush(Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4