L4Re/departure

libfsserver/lib/mapping/access_map.cc

618:7123a7307a82
8 months ago Paul Boddie Introduced some debugging output control.
     1 /*     2  * An access map providing memory corresponding to file regions.     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 "access_map.h"    23     24 /* Return the flexpage supporting 'position'. */    25     26 Flexpage *AccessMap::find(offset_t position)    27 {    28     std::lock_guard<std::mutex> guard(_lock);    29     30     _AccessMap::iterator it = _flexpages.upper_bound(position);    31     32     if ((_flexpages.size() > 0) && (it != _flexpages.begin()))    33     {    34         it--;    35     36         if (it->second->supports_position(position))    37             return it->second;    38     }    39     40     return NULL;    41 }    42     43 /* Insert a mapping for 'flexpage'. */    44     45 void AccessMap::insert(Flexpage *flexpage)    46 {    47     std::lock_guard<std::mutex> guard(_lock);    48     49     _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage));    50 }    51     52 /* Remove the mapping supported by 'flexpage'.    53     54    The flexpage may have obtained by another mapper before being purged from    55    this object's mapping and before being purged from the queue (and thus    56    disassociated from this mapper), leaving an opportunity for another mapper to    57    now be removing it here. In such a situation, flushing has already occurred    58    and will not be performed again. */    59     60 bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage)    61 {    62     std::lock_guard<std::mutex> guard(_lock);    63     64     _AccessMap::iterator it = _flexpages.find(flexpage->base_offset);    65     66     if (it != _flexpages.end())    67     {    68         owner->flush(flexpage, true);    69         _flexpages.erase(flexpage->base_offset);    70         return true;    71     }    72     73     return false;    74 }    75     76 /* Purge all flexpages, using the 'owner' to flush their contents and    77    'pages' to make the flexpages available to other accessors. */    78     79 void AccessMap::purge(PageOwner *owner, Pages *pages)    80 {    81     std::lock_guard<std::mutex> guard(_lock);    82     83     _AccessMap::iterator it = _flexpages.begin(), entry;    84     85     while (it != _flexpages.end())    86     {    87         entry = it;    88         it++;    89     90         Flexpage *flexpage = entry->second;    91     92         /* Some flexpages may be unavailable in the queue. Only those    93            that can be reserved should be flushed and made available    94            again. */    95     96         if (pages->reserve(owner, flexpage))    97         {    98             owner->flush(flexpage, true);    99             pages->release(flexpage);   100             _flexpages.erase(entry);   101         }   102     }   103 }   104    105 /* Flush flexpages in the given range from 'start' with 'size', using 'owner'   106    and 'pages'. */   107    108 void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages)   109 {   110     offset_t end = start + size;   111    112     std::lock_guard<std::mutex> guard(_lock);   113    114     /* The start may be within an existing flexpage where the flexpage size is a   115        page multiple. */   116    117     _AccessMap::iterator it = _flexpages.upper_bound(start), entry;   118    119     if ((_flexpages.size() > 0) && (it != _flexpages.begin()))   120         it--;   121    122     /* Inspect flexpages at or after start until end. */   123    124     while (it != _flexpages.end())   125     {   126         entry = it;   127         it++;   128    129         Flexpage *flexpage = entry->second;   130    131         if (flexpage->base_offset >= end)   132             break;   133    134         /* Attempt to flush each flexpage, releasing ones that are no longer   135            needed. */   136    137         if (pages->reserve(owner, flexpage))   138         {   139             owner->flush(flexpage, false);   140    141             /* Where no users of the flexpage persist, release the flexpage for   142                reuse and remove this entry. */   143    144             if (!flexpage->valid())   145             {   146                 pages->release(flexpage);   147                 _flexpages.erase(entry);   148             }   149             else   150                 pages->queue(owner, flexpage);   151         }   152     }   153 }   154    155 // vim: tabstop=4 expandtab shiftwidth=4