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