L4Re/departure

libfsserver/lib/pages/page_queue_partitioned.cc

702:7201710c7874
4 months ago Paul Boddie Introduced critical sections for the remove and close operations.
     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