1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pipes/pipe_pager.cc Sat Mar 27 01:42:25 2021 +0100
1.3 @@ -0,0 +1,129 @@
1.4 +#include "pipe_pager.h"
1.5 +#include "pipe_object_server.h"
1.6 +
1.7 +/* Initialise a pager for a pipe with a shared page mapper for moderating
1.8 + access to loaded pages. At first, no mapper will be configured: this must be
1.9 + done by requesting a region. */
1.10 +
1.11 +PipePager::PipePager(PipePaging *paging, bool writing)
1.12 +: Pager(NULL, writing ? L4_FPAGE_RW : L4_FPAGE_RO),
1.13 + _paging(paging), _writing(writing)
1.14 +{
1.15 + /* Initialise the size of the paged region. */
1.16 +
1.17 + _size = _paging->region_size();
1.18 +}
1.19 +
1.20 +int PipePager::expected_items()
1.21 +{
1.22 + return PipeObject_expected_items;
1.23 +}
1.24 +
1.25 +ipc_server_handler_type PipePager::handler()
1.26 +{
1.27 + return (ipc_server_handler_type) handle_PipeObject;
1.28 +}
1.29 +
1.30 +
1.31 +
1.32 +/* Close the pager, releasing the paging coordinator for the pipe. This will
1.33 + release all active page mappers. */
1.34 +
1.35 +void PipePager::close()
1.36 +{
1.37 + _paging->detach();
1.38 +}
1.39 +
1.40 +/* Support paging. */
1.41 +
1.42 +long PipePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region)
1.43 +{
1.44 + return Pager::map(offset, hot_spot, flags, region);
1.45 +}
1.46 +
1.47 +
1.48 +
1.49 +/* Return details of the current region. */
1.50 +
1.51 +long PipePager::current_region(offset_t *populated_size, offset_t *size)
1.52 +{
1.53 + if (_mapper != NULL)
1.54 + {
1.55 + *populated_size = _mapper->get_data_size();
1.56 + *size = _size;
1.57 + return L4_EOK;
1.58 + }
1.59 + else
1.60 + return -L4_EIO;
1.61 +}
1.62 +
1.63 +/* Obtain the next region and its details. */
1.64 +
1.65 +long PipePager::next_region(offset_t *populated_size, offset_t *size)
1.66 +{
1.67 + /* Obtain a new region if writing. */
1.68 +
1.69 + if (_writing)
1.70 + return next_region_for_writer(populated_size, size);
1.71 + else
1.72 + return next_region_for_reader(populated_size, size);
1.73 +}
1.74 +
1.75 +long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size)
1.76 +{
1.77 + /* Obtain the next region if a current region is defined. */
1.78 +
1.79 + if (_mapper != NULL)
1.80 + {
1.81 + PageMapper *mapper = _paging->next_region();
1.82 +
1.83 + /* Return an error if no next region currently exists. */
1.84 +
1.85 + if (mapper == NULL)
1.86 + return -L4_EIO;
1.87 +
1.88 + _mapper = mapper;
1.89 + }
1.90 +
1.91 + /* Obtain the first region if no mapper is defined. */
1.92 +
1.93 + else
1.94 + _mapper = _paging->first_region();
1.95 +
1.96 + /* Return the details of the now-current region. */
1.97 +
1.98 + return current_region(populated_size, size);
1.99 +}
1.100 +
1.101 +long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size)
1.102 +{
1.103 + /* Set the populated size before moving on. */
1.104 +
1.105 + if (_mapper != NULL)
1.106 + _mapper->set_data_size(*populated_size);
1.107 +
1.108 + /* A guaranteed amount of memory is reserved for the pipe. */
1.109 +
1.110 + PagesConserving *pages = _paging->pages();
1.111 +
1.112 + if (!pages->increase(_size))
1.113 + return -L4_ENOMEM;
1.114 +
1.115 + /* Set the page mapper for the region. */
1.116 +
1.117 + _mapper = new PageMapper(_paging->accessor(), pages);
1.118 + _mapper->attach();
1.119 +
1.120 + /* Record the mapper as the latest region in the accessor. */
1.121 +
1.122 + _paging->add_region(_mapper);
1.123 +
1.124 + /* Set the region size to the allocated amount. */
1.125 +
1.126 + *size = _size;
1.127 + *populated_size = 0;
1.128 +
1.129 + return L4_EOK;
1.130 +}
1.131 +
1.132 +// vim: tabstop=4 expandtab shiftwidth=4