# HG changeset patch # User Paul Boddie # Date 1616879532 -3600 # Node ID f8ab10de2f5ec25369e373f372d9a541368800c0 # Parent d526f5334b42771fa4807a27e76964919c235260 Introduced a preallocated memory object alongside the existing incremental allocation object (which has been renamed), both employing a common interface, thus permitting the use of a generic page collection with different page queue types to support both files and pipes. Changed the pipe paging to employ just two pipe regions in order to limit the amount of memory that would be used by each pipe. diff -r d526f5334b42 -r f8ab10de2f5e Makefile --- a/Makefile Sat Mar 27 01:42:25 2021 +0100 +++ b/Makefile Sat Mar 27 22:12:12 2021 +0100 @@ -53,22 +53,25 @@ PLAIN_SRC_CC_common_server = \ access_map.cc accessing.cc accessor.cc \ - flexpage.cc files/file_pager.cc ipc.cc memory.cc \ + flexpage.cc ipc.cc \ + memory/memory_incremental.cc memory/memory_preallocated.cc \ opener_resource.cc opener_context_resource.cc \ - page_mapper.cc page_queue_partitioned.cc page_queue_shared.cc \ - pager.cc paging.cc \ - page_collection.cc pages.cc pages_conserving.cc \ + page_mapper.cc \ + page_queue_partitioned.cc page_queue_shared.cc \ + pager.cc paging.cc pages.cc \ region.cc resource_server.cc simple_pager.cc PLAIN_SRC_CC_dstest_block_server = \ $(PLAIN_SRC_CC_common_server) \ dstest_block_server.cc \ + files/file_pager.cc \ files/block_file_accessor.cc files/block_file_opener.cc \ files/host_file_accessor.cc files/host_file_opener.cc PLAIN_SRC_CC_dstest_host_server = \ $(PLAIN_SRC_CC_common_server) \ dstest_host_server.cc \ + files/file_pager.cc \ files/host_file_accessor.cc files/host_file_opener.cc PLAIN_SRC_CC_dstest_pipe_server = \ @@ -80,6 +83,7 @@ PLAIN_SRC_CC_dstest_test_server = \ $(PLAIN_SRC_CC_common_server) \ dstest_test_server.cc \ + files/file_pager.cc \ files/test_file_accessor.cc files/test_file_opener.cc # Normal definitions. @@ -126,7 +130,7 @@ REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes -PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/files $(PKGDIR)/pipes \ +PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/files $(PKGDIR)/memory $(PKGDIR)/pipes \ $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) include $(L4DIR)/mk/prog.mk diff -r d526f5334b42 -r f8ab10de2f5e access_map.cc --- a/access_map.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/access_map.cc Sat Mar 27 22:12:12 2021 +0100 @@ -55,7 +55,7 @@ /* 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, PageCollection *pages) +void AccessMap::purge(PageOwner *owner, Pages *pages) { std::lock_guard guard(_lock); @@ -84,7 +84,7 @@ /* 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, PageCollection *pages) +void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages) { offset_t end = start + size; diff -r d526f5334b42 -r f8ab10de2f5e access_map.h --- a/access_map.h Sat Mar 27 01:42:25 2021 +0100 +++ b/access_map.h Sat Mar 27 22:12:12 2021 +0100 @@ -27,9 +27,9 @@ bool remove(PageOwner *owner, Flexpage *flexpage); - void purge(PageOwner *owner, PageCollection *pages); + void purge(PageOwner *owner, Pages *pages); - void flush_all(offset_t start, offset_t size, PageOwner *owner, PageCollection *pages); + void flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages); }; // vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e dstest_block_server.cc --- a/dstest_block_server.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/dstest_block_server.cc Sat Mar 27 22:12:12 2021 +0100 @@ -27,8 +27,9 @@ #include #include "accessing.h" -#include "memory.h" +#include "memory_incremental.h" #include "memory_utils.h" +#include "page_queue_shared.h" #include "pages.h" #include "paging.h" #include "resource_server.h" @@ -42,10 +43,11 @@ { /* Some memory plus infrastructure. */ - Memory mem(MEMORY_PAGES); + MemoryIncremental mem(MEMORY_PAGES); Accessing accessing; Paging paging; - Pages pages(&mem); + PageQueueShared queue; + Pages pages(&mem, &queue); BlockFileOpener opener(&accessing, &paging, &pages); /* Register a server associating it with the given object. */ @@ -63,3 +65,5 @@ server.start(); return 0; } + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r d526f5334b42 -r f8ab10de2f5e dstest_host_server.cc --- a/dstest_host_server.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/dstest_host_server.cc Sat Mar 27 22:12:12 2021 +0100 @@ -27,8 +27,9 @@ #include #include "accessing.h" -#include "memory.h" +#include "memory_incremental.h" #include "memory_utils.h" +#include "page_queue_shared.h" #include "pages.h" #include "paging.h" #include "resource_server.h" @@ -42,10 +43,11 @@ { /* Some memory plus infrastructure. */ - Memory mem(MEMORY_PAGES); + MemoryIncremental mem(MEMORY_PAGES); Accessing accessing; Paging paging; - Pages pages(&mem); + PageQueueShared queue; + Pages pages(&mem, &queue); HostFileOpener opener(&accessing, &paging, &pages); /* Register a server associating it with the given object. */ diff -r d526f5334b42 -r f8ab10de2f5e dstest_pipe_client.cc --- a/dstest_pipe_client.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/dstest_pipe_client.cc Sat Mar 27 22:12:12 2021 +0100 @@ -94,8 +94,8 @@ if (err) { - printf("Region traversal error: %s\n", l4sys_errtostr(err)); - return 1; + printf("Region traversal error at region %d: %s\n", region, l4sys_errtostr(err)); + break; } } diff -r d526f5334b42 -r f8ab10de2f5e dstest_pipe_server.cc --- a/dstest_pipe_server.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/dstest_pipe_server.cc Sat Mar 27 22:12:12 2021 +0100 @@ -23,7 +23,7 @@ #include -#include "memory.h" +#include "memory_incremental.h" #include "pipe_opener_resource.h" #include "resource_server.h" @@ -35,7 +35,7 @@ { /* Some memory plus infrastructure. */ - Memory mem(MEMORY_PAGES); + MemoryIncremental mem(MEMORY_PAGES); PipeOpenerResource opener(&mem); /* Register a server associating it with the given object. */ diff -r d526f5334b42 -r f8ab10de2f5e dstest_test_server.cc --- a/dstest_test_server.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/dstest_test_server.cc Sat Mar 27 22:12:12 2021 +0100 @@ -29,8 +29,9 @@ #include #include "accessing.h" -#include "memory.h" +#include "memory_incremental.h" #include "memory_utils.h" +#include "page_queue_shared.h" #include "pages.h" #include "paging.h" #include "resource_server.h" @@ -65,10 +66,11 @@ /* Some memory plus infrastructure. */ - Memory mem(memory_pages, page(REGION_PAGES)); + MemoryIncremental mem(memory_pages, page(REGION_PAGES)); Accessing accessing; Paging paging; - Pages pages(&mem); + PageQueueShared queue; + Pages pages(&mem, &queue); TestFileOpener opener(&accessing, &paging, &pages, page(FILE_PAGES)); /* Register a server associating it with the given object. */ diff -r d526f5334b42 -r f8ab10de2f5e memory.cc --- a/memory.cc Sat Mar 27 01:42:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -#include "memory.h" - -#include - - -/* Initialise the memory pool with an optional 'limit' in pages. */ - -Memory::Memory(unsigned int limit, offset_t region_size) -: _limit(limit), _region_size(region_size) -{ - _limited = true; -} - -Memory::Memory() -: _region_size(PAGE_SIZE) -{ - _limited = false; -} - -/* Allocate a block of the given 'size'. */ - -Region *Memory::allocate(offset_t size) -{ - /* Attempt to allocate aligned memory. */ - - void *current; - - /* Make the size appropriate for the invocation. */ - - size = round_multiple(size, PAGE_SIZE); - - if (posix_memalign(¤t, size, size)) - return NULL; - - return new Region((offset_t) current, (offset_t) current + size); -} - -/* Allocate a new region of the given 'size' rounded to the nearest page. */ - -Region *Memory::region(offset_t size) -{ - std::lock_guard guard(_lock); - - offset_t rounded = round(size, PAGE_SIZE); - offset_t pages = rounded / PAGE_SIZE; - - /* Check for sufficient pages. */ - - if (!_limited || (_limit >= pages)) - { - /* Attempt to allocate aligned memory. */ - - Region *region = allocate(rounded); - - if (region == NULL) - return NULL; - - if (_limited) - _limit -= pages; - - return region; - } - - /* Return no region without sufficient pages. */ - - else - return NULL; -} - -Region *Memory::region() -{ - return region(_region_size); -} - -/* Release the allocated 'region'. */ - -void Memory::release(Region *region) -{ - std::lock_guard guard(_lock); - - offset_t rounded = round(region->size(), PAGE_SIZE); - offset_t pages = rounded / PAGE_SIZE; - - if (_limited) - _limit += pages; - - delete region; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e memory.h --- a/memory.h Sat Mar 27 01:42:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include "memory_utils.h" -#include "region.h" - - - -/* A memory pool abstraction. */ - -class Memory -{ -protected: - std::mutex _lock; - - unsigned int _limit; - offset_t _region_size; - bool _limited; - - Region *allocate(offset_t size); - -public: - explicit Memory(unsigned int limit, offset_t region_size=PAGE_SIZE); - - explicit Memory(); - - offset_t region_size() - { return _region_size; } - - Region *region(offset_t size); - - Region *region(); - - void release(Region *region); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e memory/memory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory/memory.h Sat Mar 27 22:12:12 2021 +0100 @@ -0,0 +1,23 @@ +#pragma once + +#include "region.h" + + + +/* A memory pool interface. */ + +class Memory +{ +public: + virtual ~Memory() + { + } + + virtual Region *region() = 0; + + virtual offset_t region_size() = 0; + + virtual void release(Region *region) = 0; +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e memory/memory_incremental.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory/memory_incremental.cc Sat Mar 27 22:12:12 2021 +0100 @@ -0,0 +1,90 @@ +#include "memory_incremental.h" + +#include + + +/* Initialise the memory pool with an optional 'limit' in pages. */ + +MemoryIncremental::MemoryIncremental(unsigned int limit, offset_t region_size) +: _limit(limit), _region_size(region_size) +{ + _limited = true; +} + +MemoryIncremental::MemoryIncremental() +: _region_size(PAGE_SIZE) +{ + _limited = false; +} + +/* Allocate a block of the given 'size'. */ + +Region *MemoryIncremental::allocate(offset_t size) +{ + /* Attempt to allocate aligned memory. */ + + void *current; + + /* Make the size appropriate for the invocation. */ + + size = round_multiple(size, PAGE_SIZE); + + if (posix_memalign(¤t, size, size)) + return NULL; + + return new Region((offset_t) current, (offset_t) current + size); +} + +/* Allocate a new region of the given 'size' rounded to the nearest page. */ + +Region *MemoryIncremental::region(offset_t size) +{ + std::lock_guard guard(_lock); + + offset_t rounded = round(size, PAGE_SIZE); + offset_t pages = rounded / PAGE_SIZE; + + /* Check for sufficient pages. */ + + if (!_limited || (_limit >= pages)) + { + /* Attempt to allocate aligned memory. */ + + Region *region = allocate(rounded); + + if (region == NULL) + return NULL; + + if (_limited) + _limit -= pages; + + return region; + } + + /* Return no region without sufficient pages. */ + + else + return NULL; +} + +Region *MemoryIncremental::region() +{ + return region(_region_size); +} + +/* Release the allocated 'region'. */ + +void MemoryIncremental::release(Region *region) +{ + std::lock_guard guard(_lock); + + offset_t rounded = round(region->size(), PAGE_SIZE); + offset_t pages = rounded / PAGE_SIZE; + + if (_limited) + _limit += pages; + + delete region; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e memory/memory_incremental.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory/memory_incremental.h Sat Mar 27 22:12:12 2021 +0100 @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include + +#include "memory.h" +#include "memory_utils.h" + + + +/* A memory pool abstraction. */ + +class MemoryIncremental : public Memory +{ +protected: + std::mutex _lock; + + unsigned int _limit; + offset_t _region_size; + bool _limited; + + Region *allocate(offset_t size); + +public: + explicit MemoryIncremental(unsigned int limit, offset_t region_size=PAGE_SIZE); + + explicit MemoryIncremental(); + + virtual Region *region(offset_t size); + + virtual Region *region(); + + virtual offset_t region_size() + { return _region_size; } + + virtual void release(Region *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e memory/memory_preallocated.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory/memory_preallocated.cc Sat Mar 27 22:12:12 2021 +0100 @@ -0,0 +1,46 @@ +#include "memory_preallocated.h" + + + +/* Initialise the memory pool with the given amount in bytes. */ + +MemoryPreallocated::MemoryPreallocated(Memory *memory, offset_t amount) +: _memory(memory), _amount(amount) +{ + // NOTE: Handle allocation failure. + + offset_t remaining = amount; + + while (remaining) + { + _regions.push_back(memory->region()); + + if (memory->region_size() >= remaining) + break; + + remaining -= memory->region_size(); + } +} + +/* Obtain an allocated region. */ + +Region *MemoryPreallocated::region() +{ + std::lock_guard guard(_lock); + + Region *region = _regions.front(); + + _regions.pop_front(); + return region; +} + +/* Release the allocated 'region'. */ + +void MemoryPreallocated::release(Region *region) +{ + std::lock_guard guard(_lock); + + _regions.push_back(region); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e memory/memory_preallocated.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory/memory_preallocated.h Sat Mar 27 22:12:12 2021 +0100 @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include +#include + +#include "memory.h" + + + +/* A memory pool abstraction. */ + +class MemoryPreallocated : public Memory +{ +protected: + std::mutex _lock; + std::list _regions; + + Memory *_memory; + offset_t _amount; + +public: + explicit MemoryPreallocated(Memory *memory, offset_t amount); + + explicit MemoryPreallocated(); + + virtual Region *region(); + + virtual offset_t region_size() + { return _memory->region_size(); } + + virtual void release(Region *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e page_collection.cc --- a/page_collection.cc Sat Mar 27 01:42:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -#include "pages.h" - -PageCollection::PageCollection(Memory *memory) -: _memory(memory) -{ -} - -PageCollection::PageCollection() -{ - _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 *PageCollection::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 PageCollection::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 *PageCollection::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 PageCollection::queue(PageOwner *owner, Flexpage *flexpage) -{ - _queue->push(owner, flexpage); -} - -/* Push an entry for 'flexpage' without owner association for immediate - reuse. */ - -void PageCollection::release(Flexpage *flexpage) -{ - _queue->push_front(NULL, flexpage); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e page_collection.h --- a/page_collection.h Sat Mar 27 01:42:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#pragma once - -#include "flexpage.h" -#include "memory.h" -#include "page_owner.h" -#include "page_queue.h" - - - -/* A page collection. */ - -class PageCollection -{ -protected: - PageQueue *_queue; - Memory *_memory; - -public: - explicit PageCollection(Memory *memory); - - explicit PageCollection(); - - virtual ~PageCollection() - { - } - - virtual Flexpage *remove(); - - virtual bool reserve(PageOwner *owner, Flexpage *flexpage); - - virtual Flexpage *flexpage(); - - virtual void queue(PageOwner *owner, Flexpage *flexpage); - - virtual void release(Flexpage *flexpage); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e page_mapper.cc --- a/page_mapper.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/page_mapper.cc Sat Mar 27 22:12:12 2021 +0100 @@ -3,7 +3,7 @@ -PageMapper::PageMapper(Accessor *accessor, PageCollection *pages) +PageMapper::PageMapper(Accessor *accessor, Pages *pages) : _accessor(accessor), _pages(pages), _attached(0) { } diff -r d526f5334b42 -r f8ab10de2f5e page_mapper.h --- a/page_mapper.h Sat Mar 27 01:42:25 2021 +0100 +++ b/page_mapper.h Sat Mar 27 22:12:12 2021 +0100 @@ -13,7 +13,7 @@ protected: AccessMap _map; Accessor *_accessor; - PageCollection *_pages; + Pages *_pages; unsigned int _attached; std::mutex _lock; @@ -24,7 +24,7 @@ Flexpage *flexpage(offset_t offset); public: - explicit PageMapper(Accessor *accessor, PageCollection *pages); + explicit PageMapper(Accessor *accessor, Pages *pages); /* Accounting methods. */ diff -r d526f5334b42 -r f8ab10de2f5e page_queue.h --- a/page_queue.h Sat Mar 27 01:42:25 2021 +0100 +++ b/page_queue.h Sat Mar 27 22:12:12 2021 +0100 @@ -23,6 +23,10 @@ class PageQueue { public: + virtual ~PageQueue() + { + } + virtual void pop(PageOwner **owner, Flexpage **flexpage) = 0; virtual void push(PageOwner *owner, Flexpage *flexpage) = 0; diff -r d526f5334b42 -r f8ab10de2f5e pages.cc --- a/pages.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/pages.cc Sat Mar 27 22:12:12 2021 +0100 @@ -1,15 +1,68 @@ +#include "memory_incremental.h" #include "pages.h" -Pages::Pages(Memory *memory) -: PageCollection(memory) + + +Pages::Pages(Memory *memory, PageQueue *queue) +: _memory(memory), _queue(queue) +{ +} + +Pages::Pages(PageQueue *queue) +: _queue(queue) { - _queue = &_page_queue; + _memory = new MemoryIncremental(); +} + +/* 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; } -Pages::Pages() -: PageCollection() +/* 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() { - _queue = &_page_queue; + 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 d526f5334b42 -r f8ab10de2f5e pages.h --- a/pages.h Sat Mar 27 01:42:25 2021 +0100 +++ b/pages.h Sat Mar 27 22:12:12 2021 +0100 @@ -1,21 +1,38 @@ #pragma once -#include "page_collection.h" -#include "page_queue_shared.h" +#include "flexpage.h" +#include "memory.h" +#include "page_owner.h" +#include "page_queue.h" /* A page collection. */ -class Pages : public PageCollection +class Pages { protected: - PageQueueShared _page_queue; + Memory *_memory; + PageQueue *_queue; public: - explicit Pages(Memory *memory); + explicit Pages(Memory *memory, PageQueue *queue); + + explicit Pages(PageQueue *queue); + + virtual ~Pages() + { + } - explicit Pages(); + virtual Flexpage *remove(); + + virtual bool reserve(PageOwner *owner, Flexpage *flexpage); + + virtual Flexpage *flexpage(); + + virtual void queue(PageOwner *owner, Flexpage *flexpage); + + virtual void release(Flexpage *flexpage); }; // vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e pages_conserving.cc --- a/pages_conserving.cc Sat Mar 27 01:42:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -#include "pages_conserving.h" - -PagesConserving::PagesConserving(Memory *memory) -: PageCollection(memory) -{ - _queue = &_page_queue; -} - -PagesConserving::PagesConserving() -: PageCollection() -{ - _queue = &_page_queue; -} - - - -/* Refuse to obtain a new flexpage directly. All flexpages must be obtained from - the page queue. */ - -Flexpage *PagesConserving::flexpage() -{ - return NULL; -} - - - -/* Decrease the provision of flexpages to pipes. */ - -bool PagesConserving::decrease(offset_t size) -{ - // NOTE: Need to remove flexpages from the queue. - // NOTE: This might need to happen incrementally in case some pages are not - // NOTE: back in the queue for whatever reason. - - return true; -} - -/* Increase the provision of flexpages to pipes, returning whether allocation - succeeded. */ - -bool PagesConserving::increase(offset_t size) -{ - offset_t allocated_size = 0; - std::list allocated; - std::list::iterator it; - - /* Allocate regions for the defined increment value. */ - - while (allocated_size < size) - { - Region *r = _memory->region(); - - /* Free all allocated regions if not all regions can be allocated. */ - - if (r == NULL) - { - for (it = allocated.begin(); it != allocated.end(); it++) - _memory->release(r); - - return false; - } - - allocated.push_back(r); - allocated_size += r->size(); - } - - /* Queue flexpages for the regions. */ - - for (it = allocated.begin(); it != allocated.end(); it++) - _queue->push(NULL, new Flexpage(*it)); - - return true; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e pages_conserving.h --- a/pages_conserving.h Sat Mar 27 01:42:25 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -#pragma once - -#include "page_collection.h" -#include "page_queue_partitioned.h" - - - -/* A page collection where the pages are "conserved", meaning that they are not - queued for reuse unless they are completely unused. */ - -class PagesConserving : public PageCollection -{ -protected: - PageQueuePartitioned _page_queue; - -public: - explicit PagesConserving(Memory *memory); - - explicit PagesConserving(); - - /* Specialised methods. */ - - virtual Flexpage *flexpage(); - - /* Memory control methods. */ - - virtual bool decrease(offset_t size); - - virtual bool increase(offset_t size); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e pipes/pipe_opener_resource.cc --- a/pipes/pipe_opener_resource.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/pipes/pipe_opener_resource.cc Sat Mar 27 22:12:12 2021 +0100 @@ -1,3 +1,4 @@ +#include "memory_incremental.h" #include "pipe_opener_resource.h" #include "pipe_opener_server.h" #include "pipe_pager.h" @@ -14,7 +15,7 @@ PipeOpenerResource::PipeOpenerResource() { - _memory = new Memory(); + _memory = new MemoryIncremental(); } int PipeOpenerResource::expected_items() diff -r d526f5334b42 -r f8ab10de2f5e pipes/pipe_pager.cc --- a/pipes/pipe_pager.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/pipes/pipe_pager.cc Sat Mar 27 22:12:12 2021 +0100 @@ -1,6 +1,8 @@ #include "pipe_pager.h" #include "pipe_object_server.h" + + /* Initialise a pager for a pipe with a shared page mapper for moderating access to loaded pages. At first, no mapper will be configured: this must be done by requesting a region. */ @@ -71,26 +73,12 @@ long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size) { - /* Obtain the next region if a current region is defined. */ - - if (_mapper != NULL) - { - PageMapper *mapper = _paging->next_region(); - - /* Return an error if no next region currently exists. */ + PageMapper *mapper = _paging->next_region(); - if (mapper == NULL) - return -L4_EIO; - - _mapper = mapper; - } + if (mapper == NULL) + return -L4_EIO; - /* Obtain the first region if no mapper is defined. */ - - else - _mapper = _paging->first_region(); - - /* Return the details of the now-current region. */ + _mapper = mapper; return current_region(populated_size, size); } @@ -102,28 +90,16 @@ if (_mapper != NULL) _mapper->set_data_size(*populated_size); - /* A guaranteed amount of memory is reserved for the pipe. */ - - PagesConserving *pages = _paging->pages(); + /* Obtain the page mapper for the region. */ - if (!pages->increase(_size)) - return -L4_ENOMEM; - - /* Set the page mapper for the region. */ + PageMapper *mapper = _paging->add_region(); - _mapper = new PageMapper(_paging->accessor(), pages); - _mapper->attach(); - - /* Record the mapper as the latest region in the accessor. */ - - _paging->add_region(_mapper); + if (mapper == NULL) + return -L4_EIO; - /* Set the region size to the allocated amount. */ + _mapper = mapper; - *size = _size; - *populated_size = 0; - - return L4_EOK; + return current_region(populated_size, size); } // vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e pipes/pipe_paging.cc --- a/pipes/pipe_paging.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/pipes/pipe_paging.cc Sat Mar 27 22:12:12 2021 +0100 @@ -1,16 +1,35 @@ +#include "memory_incremental.h" +#include "memory_preallocated.h" +#include "page_queue_partitioned.h" #include "pipe_paging.h" + + PipePaging::PipePaging(Memory *memory, offset_t size) : _memory(NULL), _size(size) { - _pages = new PagesConserving(memory); + /* Reserve space for two pipe regions. */ + + _memory = new MemoryPreallocated(memory, size * 2); + _queue = new PageQueuePartitioned(); + _pages = new Pages(_memory, _queue); + + for (unsigned int i = 0; i < 2; i++) + _regions[i] = NULL; } PipePaging::PipePaging(offset_t size) : _size(size) { - _memory = new Memory(); - _pages = new PagesConserving(_memory); + /* Reserve space for two pipe regions. */ + + _memory_base = new MemoryIncremental(); + _memory = new MemoryPreallocated(_memory_base, size * 2); + _queue = new PageQueuePartitioned(); + _pages = new Pages(_memory, _queue); + + for (unsigned int i = 0; i < 2; i++) + _regions[i] = NULL; } /* Detach one endpoint. */ @@ -29,73 +48,90 @@ /* Discard all regions from the pipe. */ - while (!_regions.empty()) + for (unsigned int i = 0; i < 2; i++) { - PageMapper *mapper = _regions.front(); + PageMapper *mapper = _regions[i]; - _regions.pop_front(); - mapper->detach(); - delete mapper; + if (mapper != NULL) + { + mapper->detach(); + _regions[i] = NULL; + delete mapper; + } } - /* Delete the page collection and memory object. */ + /* Delete the page collection and related objects. */ delete _pages; + delete _queue; + delete _memory; - if (_memory != NULL) - delete _memory; + /* Delete any underlying memory object. */ + + if (_memory_base != NULL) + delete _memory_base; } /* Add a region to the sequence. */ -void PipePaging::add_region(PageMapper *mapper) +PageMapper *PipePaging::add_region() { - _regions.push_back(mapper); + /* If the writer already accesses a different region to the reader, no new + region is added. */ + + if (_writing != _reading) + return NULL; + + /* Select the other region of the pair being maintained. */ + + _writing = 1 - _writing; + + /* Make a new mapper for the region. */ + + PageMapper *mapper = new PageMapper(&_accessors[_writing], _pages); + + /* Initialise and record the mapper. */ + + mapper->attach(); + mapper->set_data_size(0); + + _regions[_writing] = mapper; + return mapper; } -/* Return the first region in the sequence. */ +/* Return the current region for reading. */ -PageMapper *PipePaging::first_region() +PageMapper *PipePaging::current_region() { - return _regions.front(); + return _regions[_reading]; } -/* Return the next region for the reader. If only a single region remains, with - the reader wishing to move to the next, return NULL. */ +/* Return the next region for the reader if the writer is using a different one. + Otherwise, return NULL. */ PageMapper *PipePaging::next_region() { - if (_regions.size() > 1) - { - /* Discard the accessor from the current region. */ - - if (_accessors.size() > _regions.size()) - _accessors.pop_front(); + /* If the reader already accesses the same region to the writer, no next + region can be obtained. */ - /* Detach and discard the current page mapper. */ - - PageMapper *mapper = _regions.front(); + if (_reading == _writing) + return NULL; - _regions.pop_front(); - mapper->detach(); - delete mapper; + /* Detach and discard the current page mapper. */ + + PageMapper *mapper = _regions[_reading]; - /* Return the next region. */ - - return _regions.front(); + if (mapper != NULL) + { + mapper->detach(); + _regions[_reading] = NULL; + delete mapper; } - else - return NULL; -} -/* Initialise an accessor for a region. */ + /* Return the next region. */ -PipeAccessor *PipePaging::accessor() -{ - PipeAccessor accessor; - - _accessors.push_back(accessor); - return &_accessors.back(); + _reading = 1 - _reading; + return _regions[_reading]; } // vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e pipes/pipe_paging.h --- a/pipes/pipe_paging.h Sat Mar 27 01:42:25 2021 +0100 +++ b/pipes/pipe_paging.h Sat Mar 27 22:12:12 2021 +0100 @@ -1,9 +1,7 @@ #pragma once -#include - #include "page_mapper.h" -#include "pages_conserving.h" +#include "pages.h" #include "pipe_accessor.h" /* Pipe paging support, maintaining the sequence of active regions or sections @@ -12,13 +10,18 @@ class PipePaging { protected: - Memory *_memory; - PagesConserving *_pages; + Memory *_memory, *_memory_base; + Pages *_pages; + PageQueue *_queue; /* Regions acting as files with their own accessors. */ - std::list _regions; - std::list _accessors; + PageMapper *_regions[2]; + PipeAccessor _accessors[2]; + + /* The first region is initially exposed to both reader and writer. */ + + int _reading = 0, _writing = 0; /* Pipe section/region size. */ @@ -35,21 +38,16 @@ virtual void detach(); - virtual PagesConserving *pages() - { return _pages; } - virtual offset_t region_size() { return _size; } /* Region management. */ - virtual void add_region(PageMapper *mapper); + virtual PageMapper *add_region(); - virtual PageMapper *first_region(); + virtual PageMapper *current_region(); virtual PageMapper *next_region(); - - virtual PipeAccessor *accessor(); }; // vim: tabstop=4 expandtab shiftwidth=4 diff -r d526f5334b42 -r f8ab10de2f5e simple_pager.cc --- a/simple_pager.cc Sat Mar 27 01:42:25 2021 +0100 +++ b/simple_pager.cc Sat Mar 27 22:12:12 2021 +0100 @@ -1,6 +1,7 @@ #include #include "dataspace_server.h" +#include "memory_incremental.h" #include "ipc.h" #include "simple_pager.h" @@ -9,7 +10,7 @@ SimplePager::SimplePager(Memory *memory) { if (memory == NULL) - _memory = new Memory(); + _memory = new MemoryIncremental(); else _memory = memory;