1 #include "ipc.h" 2 #include "page_mapper.h" 3 4 5 6 PageMapper::PageMapper(Accessor *accessor, PageCollection *pages) 7 : _accessor(accessor), _pages(pages), _attached(0) 8 { 9 } 10 11 /* Accounting methods. */ 12 13 /* Attach a pager, opening the accessor if required. */ 14 15 void PageMapper::attach() 16 { 17 std::lock_guard<std::mutex> guard(_lock); 18 19 if (!_attached) 20 _accessor->open(); 21 22 _attached += 1; 23 } 24 25 /* Detach a pager, purging active pages and closing the accessor if no more 26 pagers are attached. Return whether any pagers are still attached. */ 27 28 unsigned int PageMapper::detach() 29 { 30 std::lock_guard<std::mutex> guard(_lock); 31 32 if (_attached) 33 { 34 _attached -= 1; 35 36 if (!_attached) 37 { 38 _map.purge(this, _pages); 39 _accessor->close(); 40 } 41 } 42 43 return _attached; 44 } 45 46 /* Interface for the pager. */ 47 48 /* Return a flexpage providing access to the indicated file 'offset'. 49 50 The returned flexpage will either be an existing, compatible flexpage or a 51 completely new flexpage. 52 53 This method locks the mapper to prevent concurrent queries with the same 54 details, with the lock held until the queue operation releases the lock. */ 55 56 Flexpage *PageMapper::get(offset_t offset, flags_t flags) 57 { 58 _lock.lock(); 59 60 Flexpage *f = find(offset); 61 62 if (f == NULL) 63 f = flexpage(offset); 64 65 /* Record a new user of the flexpage and upgrade the access flags. */ 66 67 f->increment(); 68 f->upgrade(flags); 69 return f; 70 } 71 72 /* Queue the given 'flexpage' in the page collection, making it available for 73 eventual reuse. 74 75 This method unlocks the mapper. */ 76 77 void PageMapper::queue(Flexpage *flexpage) 78 { 79 _pages->queue(this, flexpage); 80 81 _lock.unlock(); 82 } 83 84 /* Flush pages in the given range from 'start' with 'size'. */ 85 86 void PageMapper::flush_all(offset_t start, offset_t size) 87 { 88 std::lock_guard<std::mutex> guard(_lock); 89 90 _map.flush_all(start, size, this, _pages); 91 } 92 93 /* Return the maximum extent of the mapped resource. */ 94 95 offset_t PageMapper::get_data_size() 96 { 97 return _accessor->get_size(); 98 } 99 100 /* Set the maximum extent of the mapped resource. */ 101 102 void PageMapper::set_data_size(offset_t size) 103 { 104 _accessor->set_size(size); 105 } 106 107 /* Internal flexpage retrieval methods. */ 108 109 /* Find an existing flexpage for 'offset'. Where the accessor has registered a 110 compatible flexpage, an attempt is made to reserve it in the page collection; 111 if this succeeds, the flexpage is returned. Otherwise, NULL is returned. */ 112 113 Flexpage *PageMapper::find(offset_t offset) 114 { 115 Flexpage *flexpage = _map.find(offset); 116 117 /* Between finding and reserving a flexpage, there is a possibility that 118 another accessor might acquire the flexpage, issue it, and even purge 119 it. */ 120 121 if ((flexpage != NULL) && _pages->reserve(this, flexpage)) 122 return flexpage; 123 else 124 return NULL; 125 } 126 127 /* Obtain a new flexpage for the file 'offset'. If the page collection is unable 128 to obtain a completely new flexpage, an existing flexpage is requested from 129 the page collection and recycled. 130 131 The obtained flexpage is filled with content. */ 132 133 Flexpage *PageMapper::flexpage(offset_t offset) 134 { 135 Flexpage *flexpage = _pages->flexpage(); 136 137 /* Obtain an existing flexpage and reuse it. */ 138 139 if (flexpage == NULL) 140 flexpage = _pages->remove(); 141 142 flexpage->reset(offset); 143 144 fill(flexpage); 145 _map.insert(flexpage); 146 return flexpage; 147 } 148 149 /* Interface for the page collection. */ 150 151 /* Remove the record of 'flexpage' in this accessor, flushing its content. */ 152 153 void PageMapper::remove(Flexpage *flexpage) 154 { 155 _map.remove(this, flexpage); 156 } 157 158 /* Data transfer methods. */ 159 160 void PageMapper::fill(Flexpage *flexpage) 161 { 162 _accessor->fill(flexpage); 163 } 164 165 void PageMapper::flush(Flexpage *flexpage, bool purge) 166 { 167 if (flexpage->decrement() || purge) 168 { 169 _accessor->flush(flexpage); 170 ipc_unmap_flexpage(flexpage); 171 flexpage->invalidate(); 172 } 173 } 174 175 // vim: tabstop=4 expandtab shiftwidth=4