paul@93 | 1 | /* |
paul@93 | 2 | * An access map providing memory corresponding to file regions. |
paul@93 | 3 | * |
paul@93 | 4 | * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk> |
paul@93 | 5 | * |
paul@93 | 6 | * This program is free software; you can redistribute it and/or |
paul@93 | 7 | * modify it under the terms of the GNU General Public License as |
paul@93 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@93 | 9 | * the License, or (at your option) any later version. |
paul@93 | 10 | * |
paul@93 | 11 | * This program is distributed in the hope that it will be useful, |
paul@93 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@93 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@93 | 14 | * GNU General Public License for more details. |
paul@93 | 15 | * |
paul@93 | 16 | * You should have received a copy of the GNU General Public License |
paul@93 | 17 | * along with this program; if not, write to the Free Software |
paul@93 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@93 | 19 | * Boston, MA 02110-1301, USA |
paul@93 | 20 | */ |
paul@93 | 21 | |
paul@6 | 22 | #include "access_map.h" |
paul@6 | 23 | |
paul@6 | 24 | /* Return the flexpage supporting 'position'. */ |
paul@6 | 25 | |
paul@6 | 26 | Flexpage *AccessMap::find(offset_t position) |
paul@6 | 27 | { |
paul@6 | 28 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 29 | |
paul@6 | 30 | _AccessMap::iterator it = _flexpages.upper_bound(position); |
paul@6 | 31 | |
paul@6 | 32 | if ((_flexpages.size() > 0) && (it != _flexpages.begin())) |
paul@6 | 33 | { |
paul@6 | 34 | it--; |
paul@6 | 35 | |
paul@6 | 36 | if (it->second->supports_position(position)) |
paul@6 | 37 | return it->second; |
paul@6 | 38 | } |
paul@6 | 39 | |
paul@6 | 40 | return NULL; |
paul@6 | 41 | } |
paul@6 | 42 | |
paul@6 | 43 | /* Insert a mapping for 'flexpage'. */ |
paul@6 | 44 | |
paul@6 | 45 | void AccessMap::insert(Flexpage *flexpage) |
paul@6 | 46 | { |
paul@6 | 47 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 48 | |
paul@6 | 49 | _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage)); |
paul@6 | 50 | } |
paul@6 | 51 | |
paul@6 | 52 | /* Remove the mapping supported by 'flexpage'. |
paul@6 | 53 | |
paul@6 | 54 | The flexpage may have obtained by another mapper before being purged from |
paul@6 | 55 | this object's mapping and before being purged from the queue (and thus |
paul@6 | 56 | disassociated from this mapper), leaving an opportunity for another mapper to |
paul@6 | 57 | now be removing it here. In such a situation, flushing has already occurred |
paul@6 | 58 | and will not be performed again. */ |
paul@6 | 59 | |
paul@6 | 60 | bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage) |
paul@6 | 61 | { |
paul@6 | 62 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 63 | |
paul@6 | 64 | _AccessMap::iterator it = _flexpages.find(flexpage->base_offset); |
paul@6 | 65 | |
paul@6 | 66 | if (it != _flexpages.end()) |
paul@6 | 67 | { |
paul@6 | 68 | owner->flush(flexpage, true); |
paul@6 | 69 | _flexpages.erase(flexpage->base_offset); |
paul@6 | 70 | return true; |
paul@6 | 71 | } |
paul@6 | 72 | |
paul@6 | 73 | return false; |
paul@6 | 74 | } |
paul@6 | 75 | |
paul@6 | 76 | /* Purge all flexpages, using the 'owner' to flush their contents and |
paul@6 | 77 | 'pages' to make the flexpages available to other accessors. */ |
paul@6 | 78 | |
paul@72 | 79 | void AccessMap::purge(PageOwner *owner, Pages *pages) |
paul@6 | 80 | { |
paul@6 | 81 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 82 | |
paul@6 | 83 | _AccessMap::iterator it = _flexpages.begin(), entry; |
paul@6 | 84 | |
paul@6 | 85 | while (it != _flexpages.end()) |
paul@6 | 86 | { |
paul@6 | 87 | entry = it; |
paul@6 | 88 | it++; |
paul@6 | 89 | |
paul@6 | 90 | Flexpage *flexpage = entry->second; |
paul@6 | 91 | |
paul@6 | 92 | /* Some flexpages may be unavailable in the queue. Only those |
paul@6 | 93 | that can be reserved should be flushed and made available |
paul@6 | 94 | again. */ |
paul@6 | 95 | |
paul@6 | 96 | if (pages->reserve(owner, flexpage)) |
paul@6 | 97 | { |
paul@6 | 98 | owner->flush(flexpage, true); |
paul@6 | 99 | pages->release(flexpage); |
paul@6 | 100 | _flexpages.erase(entry); |
paul@6 | 101 | } |
paul@6 | 102 | } |
paul@6 | 103 | } |
paul@6 | 104 | |
paul@6 | 105 | /* Flush flexpages in the given range from 'start' with 'size', using 'owner' |
paul@6 | 106 | and 'pages'. */ |
paul@6 | 107 | |
paul@72 | 108 | void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages) |
paul@6 | 109 | { |
paul@6 | 110 | offset_t end = start + size; |
paul@6 | 111 | |
paul@6 | 112 | std::lock_guard<std::mutex> guard(_lock); |
paul@6 | 113 | |
paul@6 | 114 | /* The start may be within an existing flexpage where the flexpage size is a |
paul@6 | 115 | page multiple. */ |
paul@6 | 116 | |
paul@6 | 117 | _AccessMap::iterator it = _flexpages.upper_bound(start), entry; |
paul@6 | 118 | |
paul@6 | 119 | if ((_flexpages.size() > 0) && (it != _flexpages.begin())) |
paul@6 | 120 | it--; |
paul@6 | 121 | |
paul@6 | 122 | /* Inspect flexpages at or after start until end. */ |
paul@6 | 123 | |
paul@6 | 124 | while (it != _flexpages.end()) |
paul@6 | 125 | { |
paul@6 | 126 | entry = it; |
paul@6 | 127 | it++; |
paul@6 | 128 | |
paul@6 | 129 | Flexpage *flexpage = entry->second; |
paul@6 | 130 | |
paul@6 | 131 | if (flexpage->base_offset >= end) |
paul@6 | 132 | break; |
paul@6 | 133 | |
paul@6 | 134 | /* Attempt to flush each flexpage, releasing ones that are no longer |
paul@6 | 135 | needed. */ |
paul@6 | 136 | |
paul@6 | 137 | if (pages->reserve(owner, flexpage)) |
paul@6 | 138 | { |
paul@6 | 139 | owner->flush(flexpage, false); |
paul@6 | 140 | |
paul@6 | 141 | /* Where no users of the flexpage persist, release the flexpage for |
paul@6 | 142 | reuse and remove this entry. */ |
paul@6 | 143 | |
paul@6 | 144 | if (!flexpage->valid()) |
paul@6 | 145 | { |
paul@6 | 146 | pages->release(flexpage); |
paul@6 | 147 | _flexpages.erase(entry); |
paul@6 | 148 | } |
paul@6 | 149 | else |
paul@6 | 150 | pages->queue(owner, flexpage); |
paul@6 | 151 | } |
paul@6 | 152 | } |
paul@6 | 153 | } |
paul@6 | 154 | |
paul@6 | 155 | // vim: tabstop=4 expandtab shiftwidth=4 |