1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/mapping/flexpage.cc Thu Apr 01 00:57:43 2021 +0200
1.3 @@ -0,0 +1,137 @@
1.4 +#include <algorithm>
1.5 +
1.6 +#include "flexpage.h"
1.7 +
1.8 +
1.9 +
1.10 +/* Reset the flexpage using 'offset', being the file offset. */
1.11 +
1.12 +void Flexpage::reset(offset_t offset)
1.13 +{
1.14 + _counter = 0;
1.15 +
1.16 + /* By definition (see "Flexible-Sized Page Objects - Object-Orientation
1.17 + in Operation Systems"), flexpages are aligned to multiples of their
1.18 + size.
1.19 +
1.20 + The size of the flexpage depends on the amount of space around the
1.21 + accessed page. It cannot exceed the size of the memory region. */
1.22 +
1.23 + size = max_multiple(region->start, region->end, PAGE_SIZE);
1.24 +
1.25 + /* The base address of the flexpage is computed from the region start
1.26 + and flexpage size. It will be no lower than the region start.
1.27 +
1.28 + Sent flexpages may use higher bases due to receive window constraints,
1.29 + these being communicated by the "hot spot". */
1.30 +
1.31 + base_addr = round(region->start, size);
1.32 +
1.33 + /* Get the file offset for the base of the flexpage. This will be a
1.34 + multiple of the flexpage size for alignment purposes. */
1.35 +
1.36 + base_offset = trunc(offset, size);
1.37 +
1.38 + /* The page being accessed is relative to the base.
1.39 + (This is transient information recording the initialising access
1.40 + details.) */
1.41 +
1.42 + page_offset = trunc(offset - base_offset, PAGE_SIZE);
1.43 + page_addr = base_addr + page_offset;
1.44 +}
1.45 +
1.46 +bool Flexpage::decrement()
1.47 +{
1.48 + if (_counter)
1.49 + {
1.50 + _counter--;
1.51 + return _counter == 0;
1.52 + }
1.53 + else
1.54 + return 0;
1.55 +}
1.56 +
1.57 +void Flexpage::increment()
1.58 +{
1.59 + _counter++;
1.60 +}
1.61 +
1.62 +void Flexpage::invalidate()
1.63 +{
1.64 + _counter = 0;
1.65 +}
1.66 +
1.67 +bool Flexpage::valid()
1.68 +{
1.69 + return _counter != 0;
1.70 +}
1.71 +
1.72 +/* Return whether the flexpage supports the given file 'position'. */
1.73 +
1.74 +bool Flexpage::supports_position(offset_t position)
1.75 +{
1.76 + return (base_offset <= position) && (position < (base_offset + size));
1.77 +}
1.78 +
1.79 +void Flexpage::upgrade(flags_t flags)
1.80 +{
1.81 + if (flags && (flags != _flags))
1.82 + _flags |= flags;
1.83 +}
1.84 +
1.85 +/* Return a "send" flexpage for an access to 'offset' by positioning it relative
1.86 + to 'hot_spot' for the receive flexpage window. */
1.87 +
1.88 +SendFlexpage Flexpage::to_send(offset_t offset, offset_t hot_spot, offset_t max_offset)
1.89 +{
1.90 + /* The dataspace offset of the flexpage base is a multiple of the flexpage
1.91 + size. */
1.92 +
1.93 + offset_t receive_base_offset = trunc(offset, size);
1.94 +
1.95 + /* The offset of the accessed page within the flexpage is constrained by the
1.96 + current flexpage size. */
1.97 +
1.98 + offset_t page_offset = trunc(offset - receive_base_offset, PAGE_SIZE);
1.99 +
1.100 + /* The receive flexpage offset (hot spot) must be constrained to the
1.101 + flexpage, both the size and the start. */
1.102 +
1.103 + offset_t receive_size;
1.104 +
1.105 + if (max_offset)
1.106 + {
1.107 + receive_size = trunc_multiple(max_offset - receive_base_offset, PAGE_SIZE);
1.108 + receive_size = std::min(size, receive_size);
1.109 + }
1.110 + else
1.111 + receive_size = size;
1.112 +
1.113 + if (!receive_size)
1.114 + return SendFlexpage(base_addr, page_order(0), _flags);
1.115 +
1.116 + offset_t receive_page_offset = hot_spot % receive_size;
1.117 +
1.118 + while ((receive_size > PAGE_SIZE) && (receive_page_offset != page_offset))
1.119 + {
1.120 + receive_size /= 2;
1.121 + receive_page_offset = hot_spot % receive_size;
1.122 + }
1.123 +
1.124 + /* The flexpage base address is adjusted using the difference in page
1.125 + offsets. Where the receive flexpage offset is constained further, the
1.126 + base address will be raised to become closer to the accessed page. */
1.127 +
1.128 + offset_t adjustment = page_offset - receive_page_offset;
1.129 +
1.130 + return SendFlexpage(base_addr + adjustment, page_order(receive_size), _flags);
1.131 +}
1.132 +
1.133 +/* Return a representation of the flexpage for unmapping. */
1.134 +
1.135 +SendFlexpage Flexpage::to_unmap()
1.136 +{
1.137 + return SendFlexpage(base_addr, page_order(size), _flags);
1.138 +}
1.139 +
1.140 +// vim: tabstop=4 expandtab shiftwidth=4