# HG changeset patch # User Paul Boddie # Date 1616805745 -3600 # Node ID d526f5334b42771fa4807a27e76964919c235260 # Parent 497f5b44b489609795b59abfed7788d952e86437 Moved file and pipe functionality into separate subdirectories. diff -r 497f5b44b489 -r d526f5334b42 Makefile --- a/Makefile Sat Mar 27 00:55:05 2021 +0100 +++ b/Makefile Sat Mar 27 01:42:25 2021 +0100 @@ -53,7 +53,7 @@ PLAIN_SRC_CC_common_server = \ access_map.cc accessing.cc accessor.cc \ - flexpage.cc file_pager.cc ipc.cc memory.cc \ + flexpage.cc files/file_pager.cc ipc.cc memory.cc \ opener_resource.cc opener_context_resource.cc \ page_mapper.cc page_queue_partitioned.cc page_queue_shared.cc \ pager.cc paging.cc \ @@ -74,8 +74,8 @@ PLAIN_SRC_CC_dstest_pipe_server = \ $(PLAIN_SRC_CC_common_server) \ dstest_pipe_server.cc \ - pipe_opener_resource.cc pipe_pager.cc \ - files/pipe_accessor.cc files/pipe_paging.cc + pipes/pipe_opener_resource.cc pipes/pipe_pager.cc \ + pipes/pipe_accessor.cc pipes/pipe_paging.cc PLAIN_SRC_CC_dstest_test_server = \ $(PLAIN_SRC_CC_common_server) \ @@ -126,7 +126,8 @@ REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes -PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/files $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) +PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/files $(PKGDIR)/pipes \ + $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) include $(L4DIR)/mk/prog.mk include $(IDL_MK_DIR)/interface_rules.mk diff -r 497f5b44b489 -r d526f5334b42 file_pager.cc --- a/file_pager.cc Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -#include "file_pager.h" -#include "mapped_file_object_server.h" - -/* Initialise a pager for a file with a unique file identifier and shared page - mapper for moderating access to loaded pages. */ - -FilePager::FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags) -: Pager(mapper, flags), fileid(fileid) -{ -} - -int FilePager::expected_items() -{ - return MappedFileObject_expected_items; -} - -ipc_server_handler_type FilePager::handler() -{ - return (ipc_server_handler_type) handle_MappedFileObject; -} - -long FilePager::flush(offset_t populated_size, offset_t *size) -{ - return Pager::flush(populated_size, size); -} - -long FilePager::resize(offset_t *size) -{ - return Pager::resize(size); -} - -long FilePager::mmap(offset_t position, offset_t length, offset_t *start_pos, offset_t *end_pos, offset_t *data_end) -{ - /* Set the limits of the paged region. */ - - Pager::mmap(position, length, start_pos, end_pos, data_end); - - /* Obtain the amount of the region that is populated with file data. */ - - *data_end = get_data_size() - _start; - - if (*data_end > _size) - *data_end = _size; - - return L4_EOK; -} - -long FilePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region) -{ - return Pager::map(offset, hot_spot, flags, region); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 file_pager.h --- a/file_pager.h Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -#pragma once - -#include "mapped_file_object_interface.h" -#include "pager.h" - -/* A pager abstraction for a file. */ - -class FilePager : public Pager, public MappedFileObject -{ -public: - fileid_t fileid; - - explicit FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* File methods. */ - - virtual long flush(offset_t populated_size, offset_t *size); - - virtual long resize(offset_t *size); - - /* Pager and mapped file methods. */ - - virtual long map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region); - - virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, offset_t *end_pos, offset_t *data_end); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 files/file_pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/files/file_pager.cc Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,53 @@ +#include "file_pager.h" +#include "mapped_file_object_server.h" + +/* Initialise a pager for a file with a unique file identifier and shared page + mapper for moderating access to loaded pages. */ + +FilePager::FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags) +: Pager(mapper, flags), fileid(fileid) +{ +} + +int FilePager::expected_items() +{ + return MappedFileObject_expected_items; +} + +ipc_server_handler_type FilePager::handler() +{ + return (ipc_server_handler_type) handle_MappedFileObject; +} + +long FilePager::flush(offset_t populated_size, offset_t *size) +{ + return Pager::flush(populated_size, size); +} + +long FilePager::resize(offset_t *size) +{ + return Pager::resize(size); +} + +long FilePager::mmap(offset_t position, offset_t length, offset_t *start_pos, offset_t *end_pos, offset_t *data_end) +{ + /* Set the limits of the paged region. */ + + Pager::mmap(position, length, start_pos, end_pos, data_end); + + /* Obtain the amount of the region that is populated with file data. */ + + *data_end = get_data_size() - _start; + + if (*data_end > _size) + *data_end = _size; + + return L4_EOK; +} + +long FilePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region) +{ + return Pager::map(offset, hot_spot, flags, region); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 files/file_pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/files/file_pager.h Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,37 @@ +#pragma once + +#include "mapped_file_object_interface.h" +#include "pager.h" + +/* A pager abstraction for a file. */ + +class FilePager : public Pager, public MappedFileObject +{ +public: + fileid_t fileid; + + explicit FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* File methods. */ + + virtual long flush(offset_t populated_size, offset_t *size); + + virtual long resize(offset_t *size); + + /* Pager and mapped file methods. */ + + virtual long map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region); + + virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, offset_t *end_pos, offset_t *data_end); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 files/pipe_accessor.cc --- a/files/pipe_accessor.cc Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -#include "pipe_accessor.h" - -#include - -PipeAccessor::PipeAccessor() -: Accessor(0) -{ -} - -/* Perform any closing operation on the file. */ - -void PipeAccessor::close() -{ -} - -/* Perform any opening operation on the file. */ - -void PipeAccessor::open() -{ -} - -/* Data transfer helper methods. */ - -void PipeAccessor::fill_populated(Flexpage *flexpage) -{ - offset_t filepos = flexpage->base_offset; - offset_t addr = flexpage->base_addr; - - /* Tag the region with file state. */ - - flexpage->region->fill(fileid, filepos); - - /* File the flexpage with zero. */ - - memset((void *) addr, 0, flexpage->size); -} - -void PipeAccessor::flush_populated(Flexpage *flexpage) -{ - flexpage->region->flush(); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 files/pipe_accessor.h --- a/files/pipe_accessor.h Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -#pragma once - -#include "accessor.h" - -/* A pipe accessor, providing flexpages for pipe sections. */ - -class PipeAccessor : public Accessor -{ -protected: - - /* Data transfer helper methods. */ - - virtual void fill_populated(Flexpage *flexpage); - - virtual void flush_populated(Flexpage *flexpage); - -public: - explicit PipeAccessor(); - - virtual void close(); - - virtual void open(); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 files/pipe_paging.cc --- a/files/pipe_paging.cc Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -#include "pipe_paging.h" - -PipePaging::PipePaging(Memory *memory, offset_t size) -: _memory(NULL), _size(size) -{ - _pages = new PagesConserving(memory); -} - -PipePaging::PipePaging(offset_t size) -: _size(size) -{ - _memory = new Memory(); - _pages = new PagesConserving(_memory); -} - -/* Detach one endpoint. */ - -void PipePaging::detach() -{ - if (!_endpoints) - return; - else - _endpoints--; - - /* Return if the other endpoint is attached. */ - - if (_endpoints) - return; - - /* Discard all regions from the pipe. */ - - while (!_regions.empty()) - { - PageMapper *mapper = _regions.front(); - - _regions.pop_front(); - mapper->detach(); - delete mapper; - } - - /* Delete the page collection and memory object. */ - - delete _pages; - - if (_memory != NULL) - delete _memory; -} - -/* Add a region to the sequence. */ - -void PipePaging::add_region(PageMapper *mapper) -{ - _regions.push_back(mapper); -} - -/* Return the first region in the sequence. */ - -PageMapper *PipePaging::first_region() -{ - return _regions.front(); -} - -/* Return the next region for the reader. If only a single region remains, with - the reader wishing to move to the next, 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(); - - /* Detach and discard the current page mapper. */ - - PageMapper *mapper = _regions.front(); - - _regions.pop_front(); - mapper->detach(); - delete mapper; - - /* Return the next region. */ - - return _regions.front(); - } - else - return NULL; -} - -/* Initialise an accessor for a region. */ - -PipeAccessor *PipePaging::accessor() -{ - PipeAccessor accessor; - - _accessors.push_back(accessor); - return &_accessors.back(); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 files/pipe_paging.h --- a/files/pipe_paging.h Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -#pragma once - -#include - -#include "page_mapper.h" -#include "pages_conserving.h" -#include "pipe_accessor.h" - -/* Pipe paging support, maintaining the sequence of active regions or sections - in a pipe. */ - -class PipePaging -{ -protected: - Memory *_memory; - PagesConserving *_pages; - - /* Regions acting as files with their own accessors. */ - - std::list _regions; - std::list _accessors; - - /* Pipe section/region size. */ - - offset_t _size; - - /* Endpoint status. */ - - unsigned int _endpoints = 2; - -public: - explicit PipePaging(Memory *memory, offset_t size); - - explicit PipePaging(offset_t size); - - 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 *first_region(); - - virtual PageMapper *next_region(); - - virtual PipeAccessor *accessor(); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipe_opener_resource.cc --- a/pipe_opener_resource.cc Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -#include "pipe_opener_resource.h" -#include "pipe_opener_server.h" -#include "pipe_pager.h" -#include "resource_server.h" - - - -/* Support for providing access to pipes. */ - -PipeOpenerResource::PipeOpenerResource(Memory *memory) -: _memory(memory) -{ -} - -PipeOpenerResource::PipeOpenerResource() -{ - _memory = new Memory(); -} - -int PipeOpenerResource::expected_items() -{ - return PipeOpener_expected_items; -} - -ipc_server_handler_type PipeOpenerResource::handler() -{ - return (ipc_server_handler_type) handle_PipeOpener; -} - - - -/* Pipe opener interface methods. */ - -long PipeOpenerResource::pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer) -{ - /* Both endpoints will employ a common paging coordinator. */ - - PipePaging *paging = new PipePaging(_memory, size); - - /* Each endpoint will have its own pager. */ - - /* NOTE: Failure to open an endpoint should invalidate both, plus the - paging object. Also, any active server thread would need to be - cancelled. */ - - return open_endpoint(paging, false, reader) || open_endpoint(paging, true, writer); -} - -long PipeOpenerResource::open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint) -{ - PipePager *pager = new PipePager(paging, writing); - - /* Start the endpoint server in a new thread. - If the thread does not start, the resource should be finalised. */ - - ResourceServer server(pager); - long err = server.start_thread(); - - /* Return the server capability to the caller. */ - - if (!err) - *endpoint = server.config()->server; - - return err; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipe_opener_resource.h --- a/pipe_opener_resource.h Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#pragma once - -#include "memory.h" -#include "pipe_opener_interface.h" -#include "pipe_paging.h" -#include "resource.h" - -/* Support for providing access to pipes. */ - -class PipeOpenerResource : public Resource, public PipeOpener -{ -protected: - Memory *_memory; - - long open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint); - -public: - explicit PipeOpenerResource(Memory *memory); - - explicit PipeOpenerResource(); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* PipeOpener interface methods. */ - - long pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipe_pager.cc --- a/pipe_pager.cc Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -#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. */ - -PipePager::PipePager(PipePaging *paging, bool writing) -: Pager(NULL, writing ? L4_FPAGE_RW : L4_FPAGE_RO), - _paging(paging), _writing(writing) -{ - /* Initialise the size of the paged region. */ - - _size = _paging->region_size(); -} - -int PipePager::expected_items() -{ - return PipeObject_expected_items; -} - -ipc_server_handler_type PipePager::handler() -{ - return (ipc_server_handler_type) handle_PipeObject; -} - - - -/* Close the pager, releasing the paging coordinator for the pipe. This will - release all active page mappers. */ - -void PipePager::close() -{ - _paging->detach(); -} - -/* Support paging. */ - -long PipePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region) -{ - return Pager::map(offset, hot_spot, flags, region); -} - - - -/* Return details of the current region. */ - -long PipePager::current_region(offset_t *populated_size, offset_t *size) -{ - if (_mapper != NULL) - { - *populated_size = _mapper->get_data_size(); - *size = _size; - return L4_EOK; - } - else - return -L4_EIO; -} - -/* Obtain the next region and its details. */ - -long PipePager::next_region(offset_t *populated_size, offset_t *size) -{ - /* Obtain a new region if writing. */ - - if (_writing) - return next_region_for_writer(populated_size, size); - else - return next_region_for_reader(populated_size, size); -} - -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. */ - - if (mapper == NULL) - return -L4_EIO; - - _mapper = mapper; - } - - /* Obtain the first region if no mapper is defined. */ - - else - _mapper = _paging->first_region(); - - /* Return the details of the now-current region. */ - - return current_region(populated_size, size); -} - -long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) -{ - /* Set the populated size before moving on. */ - - if (_mapper != NULL) - _mapper->set_data_size(*populated_size); - - /* A guaranteed amount of memory is reserved for the pipe. */ - - PagesConserving *pages = _paging->pages(); - - if (!pages->increase(_size)) - return -L4_ENOMEM; - - /* Set the page mapper for the region. */ - - _mapper = new PageMapper(_paging->accessor(), pages); - _mapper->attach(); - - /* Record the mapper as the latest region in the accessor. */ - - _paging->add_region(_mapper); - - /* Set the region size to the allocated amount. */ - - *size = _size; - *populated_size = 0; - - return L4_EOK; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipe_pager.h --- a/pipe_pager.h Sat Mar 27 00:55:05 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -#pragma once - -#include "pipe_accessor.h" -#include "pipe_object_interface.h" -#include "pipe_paging.h" -#include "pager.h" - -/* A pager abstraction for a pipe. */ - -class PipePager : public Pager, public PipeObject -{ -protected: - PipePaging *_paging; - bool _writing; - - /* Helper methods. */ - - virtual long next_region_for_reader(offset_t *populated_size, offset_t *size); - - virtual long next_region_for_writer(offset_t *populated_size, offset_t *size); - -public: - explicit PipePager(PipePaging *paging, bool writer); - - virtual void close(); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* Pager methods. */ - - virtual long map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region); - - /* Pipe methods. */ - - virtual long current_region(offset_t *populated_size, offset_t *size); - - virtual long next_region(offset_t *populated_size, offset_t *size); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_accessor.cc Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,43 @@ +#include "pipe_accessor.h" + +#include + +PipeAccessor::PipeAccessor() +: Accessor(0) +{ +} + +/* Perform any closing operation on the file. */ + +void PipeAccessor::close() +{ +} + +/* Perform any opening operation on the file. */ + +void PipeAccessor::open() +{ +} + +/* Data transfer helper methods. */ + +void PipeAccessor::fill_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t addr = flexpage->base_addr; + + /* Tag the region with file state. */ + + flexpage->region->fill(fileid, filepos); + + /* File the flexpage with zero. */ + + memset((void *) addr, 0, flexpage->size); +} + +void PipeAccessor::flush_populated(Flexpage *flexpage) +{ + flexpage->region->flush(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_accessor.h Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,25 @@ +#pragma once + +#include "accessor.h" + +/* A pipe accessor, providing flexpages for pipe sections. */ + +class PipeAccessor : public Accessor +{ +protected: + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + explicit PipeAccessor(); + + virtual void close(); + + virtual void open(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_opener_resource.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_opener_resource.cc Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,67 @@ +#include "pipe_opener_resource.h" +#include "pipe_opener_server.h" +#include "pipe_pager.h" +#include "resource_server.h" + + + +/* Support for providing access to pipes. */ + +PipeOpenerResource::PipeOpenerResource(Memory *memory) +: _memory(memory) +{ +} + +PipeOpenerResource::PipeOpenerResource() +{ + _memory = new Memory(); +} + +int PipeOpenerResource::expected_items() +{ + return PipeOpener_expected_items; +} + +ipc_server_handler_type PipeOpenerResource::handler() +{ + return (ipc_server_handler_type) handle_PipeOpener; +} + + + +/* Pipe opener interface methods. */ + +long PipeOpenerResource::pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer) +{ + /* Both endpoints will employ a common paging coordinator. */ + + PipePaging *paging = new PipePaging(_memory, size); + + /* Each endpoint will have its own pager. */ + + /* NOTE: Failure to open an endpoint should invalidate both, plus the + paging object. Also, any active server thread would need to be + cancelled. */ + + return open_endpoint(paging, false, reader) || open_endpoint(paging, true, writer); +} + +long PipeOpenerResource::open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint) +{ + PipePager *pager = new PipePager(paging, writing); + + /* Start the endpoint server in a new thread. + If the thread does not start, the resource should be finalised. */ + + ResourceServer server(pager); + long err = server.start_thread(); + + /* Return the server capability to the caller. */ + + if (!err) + *endpoint = server.config()->server; + + return err; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_opener_resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_opener_resource.h Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,36 @@ +#pragma once + +#include "memory.h" +#include "pipe_opener_interface.h" +#include "pipe_paging.h" +#include "resource.h" + +/* Support for providing access to pipes. */ + +class PipeOpenerResource : public Resource, public PipeOpener +{ +protected: + Memory *_memory; + + long open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint); + +public: + explicit PipeOpenerResource(Memory *memory); + + explicit PipeOpenerResource(); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* PipeOpener interface methods. */ + + long pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_pager.cc Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,129 @@ +#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. */ + +PipePager::PipePager(PipePaging *paging, bool writing) +: Pager(NULL, writing ? L4_FPAGE_RW : L4_FPAGE_RO), + _paging(paging), _writing(writing) +{ + /* Initialise the size of the paged region. */ + + _size = _paging->region_size(); +} + +int PipePager::expected_items() +{ + return PipeObject_expected_items; +} + +ipc_server_handler_type PipePager::handler() +{ + return (ipc_server_handler_type) handle_PipeObject; +} + + + +/* Close the pager, releasing the paging coordinator for the pipe. This will + release all active page mappers. */ + +void PipePager::close() +{ + _paging->detach(); +} + +/* Support paging. */ + +long PipePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region) +{ + return Pager::map(offset, hot_spot, flags, region); +} + + + +/* Return details of the current region. */ + +long PipePager::current_region(offset_t *populated_size, offset_t *size) +{ + if (_mapper != NULL) + { + *populated_size = _mapper->get_data_size(); + *size = _size; + return L4_EOK; + } + else + return -L4_EIO; +} + +/* Obtain the next region and its details. */ + +long PipePager::next_region(offset_t *populated_size, offset_t *size) +{ + /* Obtain a new region if writing. */ + + if (_writing) + return next_region_for_writer(populated_size, size); + else + return next_region_for_reader(populated_size, size); +} + +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. */ + + if (mapper == NULL) + return -L4_EIO; + + _mapper = mapper; + } + + /* Obtain the first region if no mapper is defined. */ + + else + _mapper = _paging->first_region(); + + /* Return the details of the now-current region. */ + + return current_region(populated_size, size); +} + +long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) +{ + /* Set the populated size before moving on. */ + + if (_mapper != NULL) + _mapper->set_data_size(*populated_size); + + /* A guaranteed amount of memory is reserved for the pipe. */ + + PagesConserving *pages = _paging->pages(); + + if (!pages->increase(_size)) + return -L4_ENOMEM; + + /* Set the page mapper for the region. */ + + _mapper = new PageMapper(_paging->accessor(), pages); + _mapper->attach(); + + /* Record the mapper as the latest region in the accessor. */ + + _paging->add_region(_mapper); + + /* Set the region size to the allocated amount. */ + + *size = _size; + *populated_size = 0; + + return L4_EOK; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_pager.h Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,47 @@ +#pragma once + +#include "pipe_accessor.h" +#include "pipe_object_interface.h" +#include "pipe_paging.h" +#include "pager.h" + +/* A pager abstraction for a pipe. */ + +class PipePager : public Pager, public PipeObject +{ +protected: + PipePaging *_paging; + bool _writing; + + /* Helper methods. */ + + virtual long next_region_for_reader(offset_t *populated_size, offset_t *size); + + virtual long next_region_for_writer(offset_t *populated_size, offset_t *size); + +public: + explicit PipePager(PipePaging *paging, bool writer); + + virtual void close(); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* Pager methods. */ + + virtual long map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region); + + /* Pipe methods. */ + + virtual long current_region(offset_t *populated_size, offset_t *size); + + virtual long next_region(offset_t *populated_size, offset_t *size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_paging.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_paging.cc Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,101 @@ +#include "pipe_paging.h" + +PipePaging::PipePaging(Memory *memory, offset_t size) +: _memory(NULL), _size(size) +{ + _pages = new PagesConserving(memory); +} + +PipePaging::PipePaging(offset_t size) +: _size(size) +{ + _memory = new Memory(); + _pages = new PagesConserving(_memory); +} + +/* Detach one endpoint. */ + +void PipePaging::detach() +{ + if (!_endpoints) + return; + else + _endpoints--; + + /* Return if the other endpoint is attached. */ + + if (_endpoints) + return; + + /* Discard all regions from the pipe. */ + + while (!_regions.empty()) + { + PageMapper *mapper = _regions.front(); + + _regions.pop_front(); + mapper->detach(); + delete mapper; + } + + /* Delete the page collection and memory object. */ + + delete _pages; + + if (_memory != NULL) + delete _memory; +} + +/* Add a region to the sequence. */ + +void PipePaging::add_region(PageMapper *mapper) +{ + _regions.push_back(mapper); +} + +/* Return the first region in the sequence. */ + +PageMapper *PipePaging::first_region() +{ + return _regions.front(); +} + +/* Return the next region for the reader. If only a single region remains, with + the reader wishing to move to the next, 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(); + + /* Detach and discard the current page mapper. */ + + PageMapper *mapper = _regions.front(); + + _regions.pop_front(); + mapper->detach(); + delete mapper; + + /* Return the next region. */ + + return _regions.front(); + } + else + return NULL; +} + +/* Initialise an accessor for a region. */ + +PipeAccessor *PipePaging::accessor() +{ + PipeAccessor accessor; + + _accessors.push_back(accessor); + return &_accessors.back(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 497f5b44b489 -r d526f5334b42 pipes/pipe_paging.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pipes/pipe_paging.h Sat Mar 27 01:42:25 2021 +0100 @@ -0,0 +1,55 @@ +#pragma once + +#include + +#include "page_mapper.h" +#include "pages_conserving.h" +#include "pipe_accessor.h" + +/* Pipe paging support, maintaining the sequence of active regions or sections + in a pipe. */ + +class PipePaging +{ +protected: + Memory *_memory; + PagesConserving *_pages; + + /* Regions acting as files with their own accessors. */ + + std::list _regions; + std::list _accessors; + + /* Pipe section/region size. */ + + offset_t _size; + + /* Endpoint status. */ + + unsigned int _endpoints = 2; + +public: + explicit PipePaging(Memory *memory, offset_t size); + + explicit PipePaging(offset_t size); + + 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 *first_region(); + + virtual PageMapper *next_region(); + + virtual PipeAccessor *accessor(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4