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