L4Re/departure

Annotated libfsserver/lib/pages/page_queue_partitioned.cc

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