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