1.1 --- a/Makefile Sun Mar 28 22:41:12 2021 +0200
1.2 +++ b/Makefile Sun Mar 28 23:16:12 2021 +0200
1.3 @@ -56,9 +56,9 @@
1.4 flexpage.cc ipc.cc \
1.5 memory/memory_incremental.cc memory/memory_preallocated.cc \
1.6 opener_resource.cc opener_context_resource.cc \
1.7 - page_mapper.cc \
1.8 - page_queue.cc page_queue_partitioned.cc page_queue_shared.cc \
1.9 - pager.cc paging.cc pages.cc \
1.10 + page_mapper.cc pager.cc paging.cc \
1.11 + pages/page_queue.cc pages/page_queue_partitioned.cc pages/page_queue_shared.cc \
1.12 + pages/pages.cc \
1.13 region.cc resource_server.cc simple_pager.cc
1.14
1.15 PLAIN_SRC_CC_dstest_block_server = \
1.16 @@ -130,7 +130,8 @@
1.17
1.18 REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes
1.19
1.20 -PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/files $(PKGDIR)/memory $(PKGDIR)/pipes \
1.21 +PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/files $(PKGDIR)/memory \
1.22 + $(PKGDIR)/pages $(PKGDIR)/pipes \
1.23 $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)
1.24
1.25 include $(L4DIR)/mk/prog.mk
2.1 --- a/page_queue.cc Sun Mar 28 22:41:12 2021 +0200
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,39 +0,0 @@
2.4 -#include "page_queue.h"
2.5 -
2.6 -
2.7 -
2.8 -void PageQueue::discard(Queue &queue, Memory *memory)
2.9 -{
2.10 - while (!queue.empty())
2.11 - {
2.12 - Flexpage *flexpage = queue.front().flexpage;
2.13 -
2.14 - queue.pop_front();
2.15 - memory->release(flexpage->region);
2.16 - delete flexpage;
2.17 - }
2.18 -}
2.19 -
2.20 -bool PageQueue::remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage)
2.21 -{
2.22 - Positions::iterator position = positions.find(flexpage);
2.23 -
2.24 - if (position == positions.end())
2.25 - return false;
2.26 -
2.27 - /* The found owner may be different from the requesting owner or even NULL
2.28 - if another owner has acquired and then purged its pages. Such a purged
2.29 - flexpage is not immediately usable, however. */
2.30 -
2.31 - Queue::iterator entry = position->second;
2.32 -
2.33 - if ((entry->owner == NULL) || (entry->owner != owner))
2.34 - return false;
2.35 -
2.36 - queue.erase(entry);
2.37 - positions.erase(position);
2.38 -
2.39 - return true;
2.40 -}
2.41 -
2.42 -// vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/page_queue.h Sun Mar 28 22:41:12 2021 +0200
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,50 +0,0 @@
3.4 -#pragma once
3.5 -
3.6 -#include <list>
3.7 -#include <map>
3.8 -
3.9 -#include "flexpage.h"
3.10 -#include "memory.h"
3.11 -#include "page_owner.h"
3.12 -
3.13 -
3.14 -
3.15 -/* Collection types. */
3.16 -
3.17 -typedef struct { Flexpage *flexpage; PageOwner *owner; } QueueEntry;
3.18 -typedef std::list<QueueEntry> Queue;
3.19 -
3.20 -typedef std::pair<Flexpage *, Queue::iterator> Position;
3.21 -typedef std::map<Flexpage *, Queue::iterator> Positions;
3.22 -
3.23 -
3.24 -
3.25 -/* A queue of managed pages. */
3.26 -
3.27 -class PageQueue
3.28 -{
3.29 -protected:
3.30 -
3.31 - /* Helper methods. */
3.32 -
3.33 - virtual void discard(Queue &queue, Memory *memory);
3.34 -
3.35 - virtual bool remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage);
3.36 -
3.37 -public:
3.38 - virtual ~PageQueue()
3.39 - {
3.40 - }
3.41 -
3.42 - virtual void close(Memory *memory) = 0;
3.43 -
3.44 - virtual void pop(PageOwner **owner, Flexpage **flexpage) = 0;
3.45 -
3.46 - virtual void push(PageOwner *owner, Flexpage *flexpage) = 0;
3.47 -
3.48 - virtual void push_front(PageOwner *owner, Flexpage *flexpage) = 0;
3.49 -
3.50 - virtual bool remove(PageOwner *owner, Flexpage *flexpage) = 0;
3.51 -};
3.52 -
3.53 -// vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/page_queue_partitioned.cc Sun Mar 28 22:41:12 2021 +0200
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,112 +0,0 @@
4.4 -#include "page_queue_partitioned.h"
4.5 -
4.6 -
4.7 -
4.8 -/* Discard all queued flexpages. */
4.9 -
4.10 -void PageQueuePartitioned::close(Memory *memory)
4.11 -{
4.12 - discard(_available, memory);
4.13 - discard(_issued, memory);
4.14 -}
4.15 -
4.16 -/* Keep waiting for a potential queue non-empty condition.
4.17 - Then, attempt to pop an entry from the queue. */
4.18 -
4.19 -void PageQueuePartitioned::pop(PageOwner **owner, Flexpage **flexpage)
4.20 -{
4.21 - std::unique_lock<std::mutex> guard(_lock);
4.22 - QueueEntry entry;
4.23 -
4.24 - while (1)
4.25 - {
4.26 - if (_pop(&entry))
4.27 - {
4.28 - *owner = entry.owner;
4.29 - *flexpage = entry.flexpage;
4.30 - return;
4.31 - }
4.32 - else
4.33 - _counter.wait(guard);
4.34 - }
4.35 -}
4.36 -
4.37 -/* Check the available pages queue for entries, returning false if no entries
4.38 - are available, returning true and providing the details if an entry can be
4.39 - removed from the front of the queue. */
4.40 -
4.41 -bool PageQueuePartitioned::_pop(QueueEntry *entry)
4.42 -{
4.43 - if (_available.empty())
4.44 - return false;
4.45 -
4.46 - *entry = _available.front();
4.47 - _available.pop_front();
4.48 -
4.49 - return true;
4.50 -}
4.51 -
4.52 -/* Push an entry for the given owner and flexpage to the appropriate queue. */
4.53 -
4.54 -void PageQueuePartitioned::push(PageOwner *owner, Flexpage *flexpage)
4.55 -{
4.56 - std::lock_guard<std::mutex> guard(_lock);
4.57 -
4.58 - /* Record the entry and a position reference for the flexpage. */
4.59 -
4.60 - Queue *queue;
4.61 - Positions *positions = NULL;
4.62 -
4.63 - if (owner == NULL)
4.64 - queue = &_available;
4.65 - else
4.66 - {
4.67 - queue = &_issued;
4.68 - positions = &_positions;
4.69 - }
4.70 -
4.71 - queue->push_back((QueueEntry) {flexpage, owner});
4.72 -
4.73 - if (positions != NULL)
4.74 - {
4.75 - Queue::iterator last = queue->end();
4.76 - last--;
4.77 - positions->insert(Position(flexpage, last));
4.78 - }
4.79 -
4.80 - _counter.notify_one();
4.81 -}
4.82 -
4.83 -/* Push an entry to the front of the appropriate queue. */
4.84 -
4.85 -void PageQueuePartitioned::push_front(PageOwner *owner, Flexpage *flexpage)
4.86 -{
4.87 - std::lock_guard<std::mutex> guard(_lock);
4.88 -
4.89 - Queue *queue;
4.90 - Positions *positions = NULL;
4.91 -
4.92 - if (owner == NULL)
4.93 - queue = &_available;
4.94 - else
4.95 - {
4.96 - queue = &_issued;
4.97 - positions = &_positions;
4.98 - }
4.99 -
4.100 - queue->push_back((QueueEntry) {flexpage, owner});
4.101 -
4.102 - if (positions != NULL)
4.103 - positions->insert(Position(flexpage, queue->begin()));
4.104 -
4.105 - _counter.notify_one();
4.106 -}
4.107 -
4.108 -/* Remove an entry for the given owner and flexpage from the queue. */
4.109 -
4.110 -bool PageQueuePartitioned::remove(PageOwner *owner, Flexpage *flexpage)
4.111 -{
4.112 - return PageQueue::remove(_issued, _positions, owner, flexpage);
4.113 -}
4.114 -
4.115 -// vim: tabstop=4 expandtab shiftwidth=4
5.1 --- a/page_queue_partitioned.h Sun Mar 28 22:41:12 2021 +0200
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,35 +0,0 @@
5.4 -#pragma once
5.5 -
5.6 -#include <condition_variable>
5.7 -#include <mutex>
5.8 -
5.9 -#include "page_queue.h"
5.10 -
5.11 -
5.12 -
5.13 -/* Queues of issued and available pages. */
5.14 -
5.15 -class PageQueuePartitioned : public PageQueue
5.16 -{
5.17 -protected:
5.18 - Queue _issued, _available;
5.19 - Positions _positions;
5.20 -
5.21 - std::mutex _lock;
5.22 - std::condition_variable _counter;
5.23 -
5.24 - virtual bool _pop(QueueEntry *entry);
5.25 -
5.26 -public:
5.27 - virtual void close(Memory *memory);
5.28 -
5.29 - virtual void pop(PageOwner **owner, Flexpage **flexpage);
5.30 -
5.31 - virtual void push(PageOwner *owner, Flexpage *flexpage);
5.32 -
5.33 - virtual void push_front(PageOwner *owner, Flexpage *flexpage);
5.34 -
5.35 - virtual bool remove(PageOwner *owner, Flexpage *flexpage);
5.36 -};
5.37 -
5.38 -// vim: tabstop=4 expandtab shiftwidth=4
6.1 --- a/page_queue_shared.cc Sun Mar 28 22:41:12 2021 +0200
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,91 +0,0 @@
6.4 -#include "page_queue_shared.h"
6.5 -
6.6 -
6.7 -
6.8 -/* Discard all queued flexpages. */
6.9 -
6.10 -void PageQueueShared::close(Memory *memory)
6.11 -{
6.12 - discard(_queue, memory);
6.13 -}
6.14 -
6.15 -/* Keep waiting for a potential queue non-empty condition.
6.16 - Then, attempt to pop an entry from the queue. */
6.17 -
6.18 -void PageQueueShared::pop(PageOwner **owner, Flexpage **flexpage)
6.19 -{
6.20 - std::unique_lock<std::mutex> guard(_lock);
6.21 - QueueEntry entry;
6.22 -
6.23 - while (1)
6.24 - {
6.25 - if (_pop(&entry))
6.26 - {
6.27 - *owner = entry.owner;
6.28 - *flexpage = entry.flexpage;
6.29 - return;
6.30 - }
6.31 - else
6.32 - _counter.wait(guard);
6.33 - }
6.34 -}
6.35 -
6.36 -/* Check the queue for entries, returning false if no entries are available,
6.37 - returning true and providing the details if an entry can be removed from the
6.38 - front of the queue. */
6.39 -
6.40 -bool PageQueueShared::_pop(QueueEntry *entry)
6.41 -{
6.42 - if (_queue.empty())
6.43 - return false;
6.44 -
6.45 - *entry = _queue.front();
6.46 - _queue.pop_front();
6.47 -
6.48 - /* Remove any position reference for the flexpage. */
6.49 -
6.50 - Positions::iterator position = _positions.find(entry->flexpage);
6.51 -
6.52 - if (position != _positions.end())
6.53 - _positions.erase(position);
6.54 -
6.55 - return true;
6.56 -}
6.57 -
6.58 -/* Push an entry for the given owner and flexpage to the queue. */
6.59 -
6.60 -void PageQueueShared::push(PageOwner *owner, Flexpage *flexpage)
6.61 -{
6.62 - std::lock_guard<std::mutex> guard(_lock);
6.63 -
6.64 - /* Record the entry and a position reference for the flexpage. */
6.65 -
6.66 - _queue.push_back((QueueEntry) {flexpage, owner});
6.67 -
6.68 - Queue::iterator last = _queue.end();
6.69 - last--;
6.70 - _positions.insert(Position(flexpage, last));
6.71 -
6.72 - _counter.notify_one();
6.73 -}
6.74 -
6.75 -/* Push an entry to the front of the queue. */
6.76 -
6.77 -void PageQueueShared::push_front(PageOwner *owner, Flexpage *flexpage)
6.78 -{
6.79 - std::lock_guard<std::mutex> guard(_lock);
6.80 -
6.81 - _queue.push_back((QueueEntry) {flexpage, owner});
6.82 - _positions.insert(Position(flexpage, _queue.begin()));
6.83 -
6.84 - _counter.notify_one();
6.85 -}
6.86 -
6.87 -/* Remove an entry for the given owner and flexpage from the queue. */
6.88 -
6.89 -bool PageQueueShared::remove(PageOwner *owner, Flexpage *flexpage)
6.90 -{
6.91 - return PageQueue::remove(_queue, _positions, owner, flexpage);
6.92 -}
6.93 -
6.94 -// vim: tabstop=4 expandtab shiftwidth=4
7.1 --- a/page_queue_shared.h Sun Mar 28 22:41:12 2021 +0200
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,35 +0,0 @@
7.4 -#pragma once
7.5 -
7.6 -#include <condition_variable>
7.7 -#include <mutex>
7.8 -
7.9 -#include "page_queue.h"
7.10 -
7.11 -
7.12 -
7.13 -/* A queue of issued pages. */
7.14 -
7.15 -class PageQueueShared : public PageQueue
7.16 -{
7.17 -protected:
7.18 - Queue _queue;
7.19 - Positions _positions;
7.20 -
7.21 - std::mutex _lock;
7.22 - std::condition_variable _counter;
7.23 -
7.24 - virtual bool _pop(QueueEntry *entry);
7.25 -
7.26 -public:
7.27 - virtual void close(Memory *memory);
7.28 -
7.29 - virtual void pop(PageOwner **owner, Flexpage **flexpage);
7.30 -
7.31 - virtual void push(PageOwner *owner, Flexpage *flexpage);
7.32 -
7.33 - virtual void push_front(PageOwner *owner, Flexpage *flexpage);
7.34 -
7.35 - virtual bool remove(PageOwner *owner, Flexpage *flexpage);
7.36 -};
7.37 -
7.38 -// vim: tabstop=4 expandtab shiftwidth=4
8.1 --- a/pages.cc Sun Mar 28 22:41:12 2021 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,73 +0,0 @@
8.4 -#include "memory_incremental.h"
8.5 -#include "pages.h"
8.6 -
8.7 -
8.8 -
8.9 -Pages::Pages(Memory *memory, PageQueue *queue)
8.10 -: _memory(memory), _queue(queue)
8.11 -{
8.12 -}
8.13 -
8.14 -Pages::Pages(PageQueue *queue)
8.15 -: _queue(queue)
8.16 -{
8.17 - _memory = new MemoryIncremental();
8.18 -}
8.19 -
8.20 -Pages::~Pages()
8.21 -{
8.22 - _queue->close(_memory);
8.23 -}
8.24 -
8.25 -/* Remove the first flexpage in the queue. If its owner exists, remove it from
8.26 - the owner (retiring the content). Return the flexpage for reuse. */
8.27 -
8.28 -Flexpage *Pages::remove()
8.29 -{
8.30 - PageOwner *owner;
8.31 - Flexpage *flexpage;
8.32 -
8.33 - _queue->pop(&owner, &flexpage);
8.34 -
8.35 - if (owner != NULL)
8.36 - owner->remove(flexpage);
8.37 -
8.38 - return flexpage;
8.39 -}
8.40 -
8.41 -/* Reserve 'flexpage' by removing it from this collection. */
8.42 -
8.43 -bool Pages::reserve(PageOwner *owner, Flexpage *flexpage)
8.44 -{
8.45 - return _queue->remove(owner, flexpage);
8.46 -}
8.47 -
8.48 -/* Obtain a new flexpage. Return the flexpage or None if no new flexpage could
8.49 - be created. */
8.50 -
8.51 -Flexpage *Pages::flexpage()
8.52 -{
8.53 - Region *region = _memory->region();
8.54 -
8.55 - if (region != NULL)
8.56 - return new Flexpage(region);
8.57 - else
8.58 - return NULL;
8.59 -}
8.60 -
8.61 -/* Queue an entry associating the given 'owner' and 'flexpage'. */
8.62 -
8.63 -void Pages::queue(PageOwner *owner, Flexpage *flexpage)
8.64 -{
8.65 - _queue->push(owner, flexpage);
8.66 -}
8.67 -
8.68 -/* Push an entry for 'flexpage' without owner association for immediate
8.69 - reuse. */
8.70 -
8.71 -void Pages::release(Flexpage *flexpage)
8.72 -{
8.73 - _queue->push_front(NULL, flexpage);
8.74 -}
8.75 -
8.76 -// vim: tabstop=4 expandtab shiftwidth=4
9.1 --- a/pages.h Sun Mar 28 22:41:12 2021 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,36 +0,0 @@
9.4 -#pragma once
9.5 -
9.6 -#include "flexpage.h"
9.7 -#include "memory.h"
9.8 -#include "page_owner.h"
9.9 -#include "page_queue.h"
9.10 -
9.11 -
9.12 -
9.13 -/* A page collection. */
9.14 -
9.15 -class Pages
9.16 -{
9.17 -protected:
9.18 - Memory *_memory;
9.19 - PageQueue *_queue;
9.20 -
9.21 -public:
9.22 - explicit Pages(Memory *memory, PageQueue *queue);
9.23 -
9.24 - explicit Pages(PageQueue *queue);
9.25 -
9.26 - virtual ~Pages();
9.27 -
9.28 - virtual Flexpage *remove();
9.29 -
9.30 - virtual bool reserve(PageOwner *owner, Flexpage *flexpage);
9.31 -
9.32 - virtual Flexpage *flexpage();
9.33 -
9.34 - virtual void queue(PageOwner *owner, Flexpage *flexpage);
9.35 -
9.36 - virtual void release(Flexpage *flexpage);
9.37 -};
9.38 -
9.39 -// vim: tabstop=4 expandtab shiftwidth=4
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/pages/page_queue.cc Sun Mar 28 23:16:12 2021 +0200
10.3 @@ -0,0 +1,39 @@
10.4 +#include "page_queue.h"
10.5 +
10.6 +
10.7 +
10.8 +void PageQueue::discard(Queue &queue, Memory *memory)
10.9 +{
10.10 + while (!queue.empty())
10.11 + {
10.12 + Flexpage *flexpage = queue.front().flexpage;
10.13 +
10.14 + queue.pop_front();
10.15 + memory->release(flexpage->region);
10.16 + delete flexpage;
10.17 + }
10.18 +}
10.19 +
10.20 +bool PageQueue::remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage)
10.21 +{
10.22 + Positions::iterator position = positions.find(flexpage);
10.23 +
10.24 + if (position == positions.end())
10.25 + return false;
10.26 +
10.27 + /* The found owner may be different from the requesting owner or even NULL
10.28 + if another owner has acquired and then purged its pages. Such a purged
10.29 + flexpage is not immediately usable, however. */
10.30 +
10.31 + Queue::iterator entry = position->second;
10.32 +
10.33 + if ((entry->owner == NULL) || (entry->owner != owner))
10.34 + return false;
10.35 +
10.36 + queue.erase(entry);
10.37 + positions.erase(position);
10.38 +
10.39 + return true;
10.40 +}
10.41 +
10.42 +// vim: tabstop=4 expandtab shiftwidth=4
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/pages/page_queue.h Sun Mar 28 23:16:12 2021 +0200
11.3 @@ -0,0 +1,50 @@
11.4 +#pragma once
11.5 +
11.6 +#include <list>
11.7 +#include <map>
11.8 +
11.9 +#include "flexpage.h"
11.10 +#include "memory.h"
11.11 +#include "page_owner.h"
11.12 +
11.13 +
11.14 +
11.15 +/* Collection types. */
11.16 +
11.17 +typedef struct { Flexpage *flexpage; PageOwner *owner; } QueueEntry;
11.18 +typedef std::list<QueueEntry> Queue;
11.19 +
11.20 +typedef std::pair<Flexpage *, Queue::iterator> Position;
11.21 +typedef std::map<Flexpage *, Queue::iterator> Positions;
11.22 +
11.23 +
11.24 +
11.25 +/* A queue of managed pages. */
11.26 +
11.27 +class PageQueue
11.28 +{
11.29 +protected:
11.30 +
11.31 + /* Helper methods. */
11.32 +
11.33 + virtual void discard(Queue &queue, Memory *memory);
11.34 +
11.35 + virtual bool remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage);
11.36 +
11.37 +public:
11.38 + virtual ~PageQueue()
11.39 + {
11.40 + }
11.41 +
11.42 + virtual void close(Memory *memory) = 0;
11.43 +
11.44 + virtual void pop(PageOwner **owner, Flexpage **flexpage) = 0;
11.45 +
11.46 + virtual void push(PageOwner *owner, Flexpage *flexpage) = 0;
11.47 +
11.48 + virtual void push_front(PageOwner *owner, Flexpage *flexpage) = 0;
11.49 +
11.50 + virtual bool remove(PageOwner *owner, Flexpage *flexpage) = 0;
11.51 +};
11.52 +
11.53 +// vim: tabstop=4 expandtab shiftwidth=4
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/pages/page_queue_partitioned.cc Sun Mar 28 23:16:12 2021 +0200
12.3 @@ -0,0 +1,112 @@
12.4 +#include "page_queue_partitioned.h"
12.5 +
12.6 +
12.7 +
12.8 +/* Discard all queued flexpages. */
12.9 +
12.10 +void PageQueuePartitioned::close(Memory *memory)
12.11 +{
12.12 + discard(_available, memory);
12.13 + discard(_issued, memory);
12.14 +}
12.15 +
12.16 +/* Keep waiting for a potential queue non-empty condition.
12.17 + Then, attempt to pop an entry from the queue. */
12.18 +
12.19 +void PageQueuePartitioned::pop(PageOwner **owner, Flexpage **flexpage)
12.20 +{
12.21 + std::unique_lock<std::mutex> guard(_lock);
12.22 + QueueEntry entry;
12.23 +
12.24 + while (1)
12.25 + {
12.26 + if (_pop(&entry))
12.27 + {
12.28 + *owner = entry.owner;
12.29 + *flexpage = entry.flexpage;
12.30 + return;
12.31 + }
12.32 + else
12.33 + _counter.wait(guard);
12.34 + }
12.35 +}
12.36 +
12.37 +/* Check the available pages queue for entries, returning false if no entries
12.38 + are available, returning true and providing the details if an entry can be
12.39 + removed from the front of the queue. */
12.40 +
12.41 +bool PageQueuePartitioned::_pop(QueueEntry *entry)
12.42 +{
12.43 + if (_available.empty())
12.44 + return false;
12.45 +
12.46 + *entry = _available.front();
12.47 + _available.pop_front();
12.48 +
12.49 + return true;
12.50 +}
12.51 +
12.52 +/* Push an entry for the given owner and flexpage to the appropriate queue. */
12.53 +
12.54 +void PageQueuePartitioned::push(PageOwner *owner, Flexpage *flexpage)
12.55 +{
12.56 + std::lock_guard<std::mutex> guard(_lock);
12.57 +
12.58 + /* Record the entry and a position reference for the flexpage. */
12.59 +
12.60 + Queue *queue;
12.61 + Positions *positions = NULL;
12.62 +
12.63 + if (owner == NULL)
12.64 + queue = &_available;
12.65 + else
12.66 + {
12.67 + queue = &_issued;
12.68 + positions = &_positions;
12.69 + }
12.70 +
12.71 + queue->push_back((QueueEntry) {flexpage, owner});
12.72 +
12.73 + if (positions != NULL)
12.74 + {
12.75 + Queue::iterator last = queue->end();
12.76 + last--;
12.77 + positions->insert(Position(flexpage, last));
12.78 + }
12.79 +
12.80 + _counter.notify_one();
12.81 +}
12.82 +
12.83 +/* Push an entry to the front of the appropriate queue. */
12.84 +
12.85 +void PageQueuePartitioned::push_front(PageOwner *owner, Flexpage *flexpage)
12.86 +{
12.87 + std::lock_guard<std::mutex> guard(_lock);
12.88 +
12.89 + Queue *queue;
12.90 + Positions *positions = NULL;
12.91 +
12.92 + if (owner == NULL)
12.93 + queue = &_available;
12.94 + else
12.95 + {
12.96 + queue = &_issued;
12.97 + positions = &_positions;
12.98 + }
12.99 +
12.100 + queue->push_back((QueueEntry) {flexpage, owner});
12.101 +
12.102 + if (positions != NULL)
12.103 + positions->insert(Position(flexpage, queue->begin()));
12.104 +
12.105 + _counter.notify_one();
12.106 +}
12.107 +
12.108 +/* Remove an entry for the given owner and flexpage from the queue. */
12.109 +
12.110 +bool PageQueuePartitioned::remove(PageOwner *owner, Flexpage *flexpage)
12.111 +{
12.112 + return PageQueue::remove(_issued, _positions, owner, flexpage);
12.113 +}
12.114 +
12.115 +// vim: tabstop=4 expandtab shiftwidth=4
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/pages/page_queue_partitioned.h Sun Mar 28 23:16:12 2021 +0200
13.3 @@ -0,0 +1,35 @@
13.4 +#pragma once
13.5 +
13.6 +#include <condition_variable>
13.7 +#include <mutex>
13.8 +
13.9 +#include "page_queue.h"
13.10 +
13.11 +
13.12 +
13.13 +/* Queues of issued and available pages. */
13.14 +
13.15 +class PageQueuePartitioned : public PageQueue
13.16 +{
13.17 +protected:
13.18 + Queue _issued, _available;
13.19 + Positions _positions;
13.20 +
13.21 + std::mutex _lock;
13.22 + std::condition_variable _counter;
13.23 +
13.24 + virtual bool _pop(QueueEntry *entry);
13.25 +
13.26 +public:
13.27 + virtual void close(Memory *memory);
13.28 +
13.29 + virtual void pop(PageOwner **owner, Flexpage **flexpage);
13.30 +
13.31 + virtual void push(PageOwner *owner, Flexpage *flexpage);
13.32 +
13.33 + virtual void push_front(PageOwner *owner, Flexpage *flexpage);
13.34 +
13.35 + virtual bool remove(PageOwner *owner, Flexpage *flexpage);
13.36 +};
13.37 +
13.38 +// vim: tabstop=4 expandtab shiftwidth=4
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/pages/page_queue_shared.cc Sun Mar 28 23:16:12 2021 +0200
14.3 @@ -0,0 +1,91 @@
14.4 +#include "page_queue_shared.h"
14.5 +
14.6 +
14.7 +
14.8 +/* Discard all queued flexpages. */
14.9 +
14.10 +void PageQueueShared::close(Memory *memory)
14.11 +{
14.12 + discard(_queue, memory);
14.13 +}
14.14 +
14.15 +/* Keep waiting for a potential queue non-empty condition.
14.16 + Then, attempt to pop an entry from the queue. */
14.17 +
14.18 +void PageQueueShared::pop(PageOwner **owner, Flexpage **flexpage)
14.19 +{
14.20 + std::unique_lock<std::mutex> guard(_lock);
14.21 + QueueEntry entry;
14.22 +
14.23 + while (1)
14.24 + {
14.25 + if (_pop(&entry))
14.26 + {
14.27 + *owner = entry.owner;
14.28 + *flexpage = entry.flexpage;
14.29 + return;
14.30 + }
14.31 + else
14.32 + _counter.wait(guard);
14.33 + }
14.34 +}
14.35 +
14.36 +/* Check the queue for entries, returning false if no entries are available,
14.37 + returning true and providing the details if an entry can be removed from the
14.38 + front of the queue. */
14.39 +
14.40 +bool PageQueueShared::_pop(QueueEntry *entry)
14.41 +{
14.42 + if (_queue.empty())
14.43 + return false;
14.44 +
14.45 + *entry = _queue.front();
14.46 + _queue.pop_front();
14.47 +
14.48 + /* Remove any position reference for the flexpage. */
14.49 +
14.50 + Positions::iterator position = _positions.find(entry->flexpage);
14.51 +
14.52 + if (position != _positions.end())
14.53 + _positions.erase(position);
14.54 +
14.55 + return true;
14.56 +}
14.57 +
14.58 +/* Push an entry for the given owner and flexpage to the queue. */
14.59 +
14.60 +void PageQueueShared::push(PageOwner *owner, Flexpage *flexpage)
14.61 +{
14.62 + std::lock_guard<std::mutex> guard(_lock);
14.63 +
14.64 + /* Record the entry and a position reference for the flexpage. */
14.65 +
14.66 + _queue.push_back((QueueEntry) {flexpage, owner});
14.67 +
14.68 + Queue::iterator last = _queue.end();
14.69 + last--;
14.70 + _positions.insert(Position(flexpage, last));
14.71 +
14.72 + _counter.notify_one();
14.73 +}
14.74 +
14.75 +/* Push an entry to the front of the queue. */
14.76 +
14.77 +void PageQueueShared::push_front(PageOwner *owner, Flexpage *flexpage)
14.78 +{
14.79 + std::lock_guard<std::mutex> guard(_lock);
14.80 +
14.81 + _queue.push_back((QueueEntry) {flexpage, owner});
14.82 + _positions.insert(Position(flexpage, _queue.begin()));
14.83 +
14.84 + _counter.notify_one();
14.85 +}
14.86 +
14.87 +/* Remove an entry for the given owner and flexpage from the queue. */
14.88 +
14.89 +bool PageQueueShared::remove(PageOwner *owner, Flexpage *flexpage)
14.90 +{
14.91 + return PageQueue::remove(_queue, _positions, owner, flexpage);
14.92 +}
14.93 +
14.94 +// vim: tabstop=4 expandtab shiftwidth=4
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/pages/page_queue_shared.h Sun Mar 28 23:16:12 2021 +0200
15.3 @@ -0,0 +1,35 @@
15.4 +#pragma once
15.5 +
15.6 +#include <condition_variable>
15.7 +#include <mutex>
15.8 +
15.9 +#include "page_queue.h"
15.10 +
15.11 +
15.12 +
15.13 +/* A queue of issued pages. */
15.14 +
15.15 +class PageQueueShared : public PageQueue
15.16 +{
15.17 +protected:
15.18 + Queue _queue;
15.19 + Positions _positions;
15.20 +
15.21 + std::mutex _lock;
15.22 + std::condition_variable _counter;
15.23 +
15.24 + virtual bool _pop(QueueEntry *entry);
15.25 +
15.26 +public:
15.27 + virtual void close(Memory *memory);
15.28 +
15.29 + virtual void pop(PageOwner **owner, Flexpage **flexpage);
15.30 +
15.31 + virtual void push(PageOwner *owner, Flexpage *flexpage);
15.32 +
15.33 + virtual void push_front(PageOwner *owner, Flexpage *flexpage);
15.34 +
15.35 + virtual bool remove(PageOwner *owner, Flexpage *flexpage);
15.36 +};
15.37 +
15.38 +// vim: tabstop=4 expandtab shiftwidth=4
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/pages/pages.cc Sun Mar 28 23:16:12 2021 +0200
16.3 @@ -0,0 +1,73 @@
16.4 +#include "memory_incremental.h"
16.5 +#include "pages.h"
16.6 +
16.7 +
16.8 +
16.9 +Pages::Pages(Memory *memory, PageQueue *queue)
16.10 +: _memory(memory), _queue(queue)
16.11 +{
16.12 +}
16.13 +
16.14 +Pages::Pages(PageQueue *queue)
16.15 +: _queue(queue)
16.16 +{
16.17 + _memory = new MemoryIncremental();
16.18 +}
16.19 +
16.20 +Pages::~Pages()
16.21 +{
16.22 + _queue->close(_memory);
16.23 +}
16.24 +
16.25 +/* Remove the first flexpage in the queue. If its owner exists, remove it from
16.26 + the owner (retiring the content). Return the flexpage for reuse. */
16.27 +
16.28 +Flexpage *Pages::remove()
16.29 +{
16.30 + PageOwner *owner;
16.31 + Flexpage *flexpage;
16.32 +
16.33 + _queue->pop(&owner, &flexpage);
16.34 +
16.35 + if (owner != NULL)
16.36 + owner->remove(flexpage);
16.37 +
16.38 + return flexpage;
16.39 +}
16.40 +
16.41 +/* Reserve 'flexpage' by removing it from this collection. */
16.42 +
16.43 +bool Pages::reserve(PageOwner *owner, Flexpage *flexpage)
16.44 +{
16.45 + return _queue->remove(owner, flexpage);
16.46 +}
16.47 +
16.48 +/* Obtain a new flexpage. Return the flexpage or None if no new flexpage could
16.49 + be created. */
16.50 +
16.51 +Flexpage *Pages::flexpage()
16.52 +{
16.53 + Region *region = _memory->region();
16.54 +
16.55 + if (region != NULL)
16.56 + return new Flexpage(region);
16.57 + else
16.58 + return NULL;
16.59 +}
16.60 +
16.61 +/* Queue an entry associating the given 'owner' and 'flexpage'. */
16.62 +
16.63 +void Pages::queue(PageOwner *owner, Flexpage *flexpage)
16.64 +{
16.65 + _queue->push(owner, flexpage);
16.66 +}
16.67 +
16.68 +/* Push an entry for 'flexpage' without owner association for immediate
16.69 + reuse. */
16.70 +
16.71 +void Pages::release(Flexpage *flexpage)
16.72 +{
16.73 + _queue->push_front(NULL, flexpage);
16.74 +}
16.75 +
16.76 +// vim: tabstop=4 expandtab shiftwidth=4
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/pages/pages.h Sun Mar 28 23:16:12 2021 +0200
17.3 @@ -0,0 +1,36 @@
17.4 +#pragma once
17.5 +
17.6 +#include "flexpage.h"
17.7 +#include "memory.h"
17.8 +#include "page_owner.h"
17.9 +#include "page_queue.h"
17.10 +
17.11 +
17.12 +
17.13 +/* A page collection. */
17.14 +
17.15 +class Pages
17.16 +{
17.17 +protected:
17.18 + Memory *_memory;
17.19 + PageQueue *_queue;
17.20 +
17.21 +public:
17.22 + explicit Pages(Memory *memory, PageQueue *queue);
17.23 +
17.24 + explicit Pages(PageQueue *queue);
17.25 +
17.26 + virtual ~Pages();
17.27 +
17.28 + virtual Flexpage *remove();
17.29 +
17.30 + virtual bool reserve(PageOwner *owner, Flexpage *flexpage);
17.31 +
17.32 + virtual Flexpage *flexpage();
17.33 +
17.34 + virtual void queue(PageOwner *owner, Flexpage *flexpage);
17.35 +
17.36 + virtual void release(Flexpage *flexpage);
17.37 +};
17.38 +
17.39 +// vim: tabstop=4 expandtab shiftwidth=4