1 #include "pipe_pager.h" 2 #include "pipe_object_server.h" 3 4 /* Initialise a pager for a pipe with a shared page mapper for moderating 5 access to loaded pages. At first, no mapper will be configured: this must be 6 done by requesting a region. */ 7 8 PipePager::PipePager(PagesConserving *pages, PipePaging *paging, bool writer) 9 : Pager(NULL, writer ? L4_FPAGE_RW : L4_FPAGE_RO), 10 _pages(pages), _paging(paging), _writer(writer) 11 { 12 /* Set the size of each paged region to the amount allocation for such 13 regions. */ 14 15 _size = _pages->allocation(); 16 } 17 18 int PipePager::expected_items() 19 { 20 return PipeObject_expected_items; 21 } 22 23 ipc_server_handler_type PipePager::handler() 24 { 25 return (ipc_server_handler_type) handle_PipeObject; 26 } 27 28 29 30 /* Support paging. */ 31 32 long PipePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region) 33 { 34 return Pager::map(offset, hot_spot, flags, region); 35 } 36 37 38 39 /* Return details of the current region. */ 40 41 long PipePager::current_region(offset_t *populated_size, offset_t *size) 42 { 43 if (_mapper != NULL) 44 { 45 *populated_size = _mapper->get_data_size(); 46 *size = _size; 47 return L4_EOK; 48 } 49 else 50 return -L4_EIO; 51 } 52 53 /* Obtain the next region and its details. */ 54 55 long PipePager::next_region(offset_t *populated_size, offset_t *size) 56 { 57 /* Obtain a new region if writing. */ 58 59 if (_writer) 60 return next_region_for_writer(populated_size, size); 61 else 62 return next_region_for_reader(populated_size, size); 63 } 64 65 long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size) 66 { 67 /* Obtain the next region if a current region is defined. */ 68 69 if (_mapper != NULL) 70 { 71 PageMapper *mapper = _paging->next_region(); 72 73 /* Return an error if no next region currently exists. */ 74 75 if (mapper == NULL) 76 return -L4_EIO; 77 78 /* Detach and discard the current page mapper. */ 79 80 _mapper->detach(); 81 delete _mapper; 82 83 _mapper = mapper; 84 } 85 86 /* Obtain the first region if no mapper is defined. */ 87 88 else 89 _mapper = _paging->first_region(); 90 91 /* Return the details of the now-current region. */ 92 93 return current_region(populated_size, size); 94 } 95 96 long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) 97 { 98 /* Set the populated size before moving on. */ 99 100 if (_mapper != NULL) 101 _mapper->set_data_size(*populated_size); 102 103 /* A guaranteed amount of memory is reserved for the pipe. */ 104 105 if (!_pages->increase()) 106 return -L4_ENOMEM; 107 108 /* Set the page mapper for the region. */ 109 110 _mapper = new PageMapper(&_accessor, _pages); 111 _mapper->attach(); 112 113 /* Record the mapper as the latest region in the accessor. */ 114 115 _paging->add_region(_mapper); 116 117 /* Set the region size to the allocated amount. */ 118 119 *size = _size; 120 *populated_size = 0; 121 122 return L4_EOK; 123 } 124 125 // vim: tabstop=4 expandtab shiftwidth=4