1 #include <algorithm> 2 3 #include "flexpage.h" 4 5 6 7 /* Reset the flexpage using 'offset', being the file offset. */ 8 9 void Flexpage::reset(offset_t offset) 10 { 11 _counter = 0; 12 13 /* By definition (see "Flexible-Sized Page Objects - Object-Orientation 14 in Operation Systems"), flexpages are aligned to multiples of their 15 size. 16 17 The size of the flexpage depends on the amount of space around the 18 accessed page. It cannot exceed the size of the memory region. */ 19 20 size = max_multiple(region->start, region->end, PAGE_SIZE); 21 22 /* The base address of the flexpage is computed from the region start 23 and flexpage size. It will be no lower than the region start. 24 25 Sent flexpages may use higher bases due to receive window constraints, 26 these being communicated by the "hot spot". */ 27 28 base_addr = round(region->start, size); 29 30 /* Get the file offset for the base of the flexpage. This will be a 31 multiple of the flexpage size for alignment purposes. */ 32 33 base_offset = trunc_offset(offset, size); 34 35 /* The page being accessed is relative to the base. 36 (This is transient information recording the initialising access 37 details.) */ 38 39 page_offset = trunc(offset - base_offset, PAGE_SIZE); 40 page_addr = base_addr + page_offset; 41 } 42 43 bool Flexpage::decrement() 44 { 45 if (_counter) 46 { 47 _counter--; 48 return _counter == 0; 49 } 50 else 51 return 0; 52 } 53 54 void Flexpage::increment() 55 { 56 _counter++; 57 } 58 59 void Flexpage::invalidate() 60 { 61 _counter = 0; 62 } 63 64 bool Flexpage::valid() 65 { 66 return _counter != 0; 67 } 68 69 /* Return whether the flexpage supports the given file 'position'. */ 70 71 bool Flexpage::supports_position(offset_t position) 72 { 73 return (base_offset <= position) && (position < (base_offset + size)); 74 } 75 76 /* Upgrade the flags involved with this flexpage. This is used to track the 77 maximal flags employed by the different pagers, with the result being used in 78 unmap operations. */ 79 80 void Flexpage::upgrade(flags_t flags) 81 { 82 if (flags && (flags != _flags)) 83 _flags |= flags; 84 } 85 86 /* Return a "send" flexpage for an access to 'offset' by positioning it relative 87 to 'hot_spot' for the receive flexpage window. */ 88 89 SendFlexpage Flexpage::to_send(offset_t offset, address_t hot_spot, 90 flags_t flags, offset_t max_offset) 91 { 92 /* The dataspace offset of the flexpage base is a multiple of the flexpage 93 size. */ 94 95 offset_t receive_base_offset = trunc_offset(offset, size); 96 97 /* The offset of the accessed page within the flexpage is constrained by the 98 current flexpage size. */ 99 100 length_t page_offset = trunc(offset - receive_base_offset, PAGE_SIZE); 101 102 /* The receive flexpage offset (hot spot) must be constrained to the 103 flexpage, both the size and the start. */ 104 105 length_t receive_size; 106 107 if (max_offset) 108 { 109 receive_size = trunc_multiple(max_offset - receive_base_offset, PAGE_SIZE); 110 receive_size = std::min(size, receive_size); 111 } 112 else 113 receive_size = size; 114 115 if (!receive_size) 116 return SendFlexpage(base_addr, page_order(0), flags); 117 118 length_t receive_page_offset = hot_spot % receive_size; 119 120 while ((receive_size > PAGE_SIZE) && (receive_page_offset != page_offset)) 121 { 122 receive_size /= 2; 123 receive_page_offset = hot_spot % receive_size; 124 } 125 126 /* The flexpage base address is adjusted using the difference in page 127 offsets. Where the receive flexpage offset is constained further, the 128 base address will be raised to become closer to the accessed page. */ 129 130 length_t adjustment = page_offset - receive_page_offset; 131 132 return SendFlexpage(base_addr + adjustment, page_order(receive_size), flags); 133 } 134 135 /* Return a representation of the flexpage for unmapping. */ 136 137 SendFlexpage Flexpage::to_unmap() 138 { 139 return SendFlexpage(base_addr, page_order(size), _flags); 140 } 141 142 // vim: tabstop=4 expandtab shiftwidth=4