1 /* 2 * A page queue retaining two internal collections of memory pages. 3 * 4 * Copyright (C) 2021 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 discard(_available, memory); 31 discard(_issued, memory); 32 } 33 34 /* Keep waiting for a potential queue non-empty condition. 35 Then, attempt to pop an entry from the queue. */ 36 37 void PageQueuePartitioned::pop(PageOwner **owner, Flexpage **flexpage) 38 { 39 std::unique_lock<std::mutex> guard(_lock); 40 QueueEntry entry; 41 42 while (1) 43 { 44 if (_pop(&entry)) 45 { 46 *owner = entry.owner; 47 *flexpage = entry.flexpage; 48 return; 49 } 50 else 51 _counter.wait(guard); 52 } 53 } 54 55 /* Check the available pages queue for entries, returning false if no entries 56 are available, returning true and providing the details if an entry can be 57 removed from the front of the queue. */ 58 59 bool PageQueuePartitioned::_pop(QueueEntry *entry) 60 { 61 if (_available.empty()) 62 return false; 63 64 *entry = _available.front(); 65 _available.pop_front(); 66 67 return true; 68 } 69 70 /* Push an entry for the given owner and flexpage to the appropriate queue. */ 71 72 void PageQueuePartitioned::push(PageOwner *owner, Flexpage *flexpage) 73 { 74 std::lock_guard<std::mutex> guard(_lock); 75 76 /* Record the entry and a position reference for the flexpage. */ 77 78 Queue *queue; 79 Positions *positions = NULL; 80 81 if (owner == NULL) 82 queue = &_available; 83 else 84 { 85 queue = &_issued; 86 positions = &_positions; 87 } 88 89 queue->push_back((QueueEntry) {flexpage, owner}); 90 91 if (positions != NULL) 92 { 93 Queue::iterator last = queue->end(); 94 last--; 95 positions->insert(Position(flexpage, last)); 96 } 97 98 _counter.notify_one(); 99 } 100 101 /* Push an entry to the front of the appropriate queue. */ 102 103 void PageQueuePartitioned::push_front(PageOwner *owner, Flexpage *flexpage) 104 { 105 std::lock_guard<std::mutex> guard(_lock); 106 107 Queue *queue; 108 Positions *positions = NULL; 109 110 if (owner == NULL) 111 queue = &_available; 112 else 113 { 114 queue = &_issued; 115 positions = &_positions; 116 } 117 118 queue->push_back((QueueEntry) {flexpage, owner}); 119 120 if (positions != NULL) 121 positions->insert(Position(flexpage, queue->begin())); 122 123 _counter.notify_one(); 124 } 125 126 /* Remove an entry for the given owner and flexpage from the queue. */ 127 128 bool PageQueuePartitioned::remove(PageOwner *owner, Flexpage *flexpage) 129 { 130 return PageQueue::remove(_issued, _positions, owner, flexpage); 131 } 132 133 // vim: tabstop=4 expandtab shiftwidth=4