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 /* Support paging. */ 30 31 long PipePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region) 32 { 33 return Pager::map(offset, hot_spot, flags, region); 34 } 35 36 37 38 /* Return details of the current region. */ 39 40 long PipePager::current_region(offset_t *populated_size, offset_t *size) 41 { 42 if (_mapper != NULL) 43 { 44 *populated_size = _mapper->get_data_size(); 45 *size = _size; 46 return L4_EOK; 47 } 48 else 49 return -L4_EIO; 50 } 51 52 /* Obtain the next region and its details. */ 53 54 long PipePager::next_region(offset_t *populated_size, offset_t *size) 55 { 56 /* Obtain a new region if writing. */ 57 58 if (_writing) 59 return next_region_for_writer(populated_size, size); 60 else 61 return next_region_for_reader(populated_size, size); 62 } 63 64 long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size) 65 { 66 /* Obtain the next region if a current region is defined. */ 67 68 if (_mapper != NULL) 69 { 70 PageMapper *mapper = _paging->next_region(); 71 72 /* Return an error if no next region currently exists. */ 73 74 if (mapper == NULL) 75 return -L4_EIO; 76 77 /* Detach and discard the current page mapper. */ 78 79 _mapper->detach(); 80 delete _mapper; 81 82 _mapper = mapper; 83 } 84 85 /* Obtain the first region if no mapper is defined. */ 86 87 else 88 _mapper = _paging->first_region(); 89 90 /* Return the details of the now-current region. */ 91 92 return current_region(populated_size, size); 93 } 94 95 long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) 96 { 97 /* Set the populated size before moving on. */ 98 99 if (_mapper != NULL) 100 _mapper->set_data_size(*populated_size); 101 102 /* A guaranteed amount of memory is reserved for the pipe. */ 103 104 PagesConserving *pages = _paging->pages(); 105 106 if (!pages->increase(_size)) 107 return -L4_ENOMEM; 108 109 /* Set the page mapper for the region. */ 110 111 _mapper = new PageMapper(_paging->accessor(), pages); 112 _mapper->attach(); 113 114 /* Record the mapper as the latest region in the accessor. */ 115 116 _paging->add_region(_mapper); 117 118 /* Set the region size to the allocated amount. */ 119 120 *size = _size; 121 *populated_size = 0; 122 123 return L4_EOK; 124 } 125 126 // vim: tabstop=4 expandtab shiftwidth=4