1 /* 2 * A page queue retaining two internal collections of memory pages. 3 * 4 * Copyright (C) 2021, 2024 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include "page_queue_partitioned.h" 23 24 25 26 /* Discard all queued flexpages. */ 27 28 void PageQueuePartitioned::close(Memory *memory) 29 { 30 std::lock_guard<std::mutex> guard(_lock); 31 32 discard(_available, memory); 33 discard(_issued, memory); 34 } 35 36 /* Keep waiting for a potential queue non-empty condition. 37 Then, attempt to pop an entry from the queue. */ 38 39 void PageQueuePartitioned::pop(PageOwner **owner, Flexpage **flexpage) 40 { 41 std::unique_lock<std::mutex> guard(_lock); 42 QueueEntry entry; 43 44 while (1) 45 { 46 if (_pop(&entry)) 47 { 48 *owner = entry.owner; 49 *flexpage = entry.flexpage; 50 return; 51 } 52 else 53 _counter.wait(guard); 54 } 55 } 56 57 /* Check the available pages queue for entries, returning false if no entries 58 are available, returning true and providing the details if an entry can be 59 removed from the front of the queue. */ 60 61 bool PageQueuePartitioned::_pop(QueueEntry *entry) 62 { 63 if (_available.empty()) 64 return false; 65 66 *entry = _available.front(); 67 _available.pop_front(); 68 69 return true; 70 } 71 72 /* Push an entry for the given owner and flexpage to the appropriate queue. */ 73 74 void PageQueuePartitioned::push(PageOwner *owner, Flexpage *flexpage) 75 { 76 std::lock_guard<std::mutex> guard(_lock); 77 78 /* Record the entry and a position reference for the flexpage. */ 79 80 Queue *queue; 81 Positions *positions = NULL; 82 83 if (owner == NULL) 84 queue = &_available; 85 else 86 { 87 queue = &_issued; 88 positions = &_positions; 89 } 90 91 queue->push_back((QueueEntry) {flexpage, owner}); 92 93 if (positions != NULL) 94 { 95 Queue::iterator last = queue->end(); 96 last--; 97 positions->insert(Position(flexpage, last)); 98 } 99 100 _counter.notify_one(); 101 } 102 103 /* Push an entry to the front of the appropriate queue. */ 104 105 void PageQueuePartitioned::push_front(PageOwner *owner, Flexpage *flexpage) 106 { 107 std::lock_guard<std::mutex> guard(_lock); 108 109 Queue *queue; 110 Positions *positions = NULL; 111 112 if (owner == NULL) 113 queue = &_available; 114 else 115 { 116 queue = &_issued; 117 positions = &_positions; 118 } 119 120 queue->push_back((QueueEntry) {flexpage, owner}); 121 122 if (positions != NULL) 123 positions->insert(Position(flexpage, queue->begin())); 124 125 _counter.notify_one(); 126 } 127 128 /* Remove an entry for the given owner and flexpage from the queue. */ 129 130 bool PageQueuePartitioned::remove(PageOwner *owner, Flexpage *flexpage) 131 { 132 std::lock_guard<std::mutex> guard(_lock); 133 134 return PageQueue::remove(_issued, _positions, owner, flexpage); 135 } 136 137 // vim: tabstop=4 expandtab shiftwidth=4