1 #include "memory_incremental.h" 2 #include "memory_preallocated.h" 3 #include "page_queue_partitioned.h" 4 #include "pipe_paging.h" 5 6 7 8 PipePaging::PipePaging(Memory *memory, offset_t size) 9 : _memory(NULL), _size(size) 10 { 11 /* Reserve space for two pipe regions. */ 12 13 _memory = new MemoryPreallocated(memory, size * 2); 14 _queue = new PageQueuePartitioned(); 15 _pages = new Pages(_memory, _queue); 16 17 for (unsigned int i = 0; i < 2; i++) 18 _regions[i] = NULL; 19 } 20 21 PipePaging::PipePaging(offset_t size) 22 : _size(size) 23 { 24 /* Reserve space for two pipe regions. */ 25 26 _memory_base = new MemoryIncremental(); 27 _memory = new MemoryPreallocated(_memory_base, size * 2); 28 _queue = new PageQueuePartitioned(); 29 _pages = new Pages(_memory, _queue); 30 31 for (unsigned int i = 0; i < 2; i++) 32 _regions[i] = NULL; 33 } 34 35 /* Detach one endpoint. */ 36 37 void PipePaging::detach() 38 { 39 if (!_endpoints) 40 return; 41 else 42 _endpoints--; 43 44 /* Return if the other endpoint is attached. */ 45 46 if (_endpoints) 47 return; 48 49 /* Discard all regions from the pipe. */ 50 51 for (unsigned int i = 0; i < 2; i++) 52 { 53 PageMapper *mapper = _regions[i]; 54 55 if (mapper != NULL) 56 { 57 mapper->detach(); 58 _regions[i] = NULL; 59 delete mapper; 60 } 61 } 62 63 /* Delete the page collection and related objects. */ 64 65 delete _pages; 66 delete _queue; 67 delete _memory; 68 69 /* Delete any underlying memory object. */ 70 71 if (_memory_base != NULL) 72 delete _memory_base; 73 } 74 75 /* Add a region to the sequence. */ 76 77 PageMapper *PipePaging::add_region() 78 { 79 /* If the writer already accesses a different region to the reader, no new 80 region is added. */ 81 82 if (_writing != _reading) 83 return NULL; 84 85 /* Select the other region of the pair being maintained. */ 86 87 _writing = 1 - _writing; 88 89 /* Make a new mapper for the region. */ 90 91 PageMapper *mapper = new PageMapper(&_accessors[_writing], _pages); 92 93 /* Initialise and record the mapper. */ 94 95 mapper->attach(); 96 mapper->set_data_size(0); 97 98 _regions[_writing] = mapper; 99 return mapper; 100 } 101 102 /* Return the current region for reading. */ 103 104 PageMapper *PipePaging::current_region() 105 { 106 return _regions[_reading]; 107 } 108 109 /* Return the next region for the reader if the writer is using a different one. 110 Otherwise, return NULL. */ 111 112 PageMapper *PipePaging::next_region() 113 { 114 /* If the reader already accesses the same region to the writer, no next 115 region can be obtained. */ 116 117 if (_reading == _writing) 118 return NULL; 119 120 /* Detach and discard the current page mapper. */ 121 122 PageMapper *mapper = _regions[_reading]; 123 124 if (mapper != NULL) 125 { 126 mapper->detach(); 127 _regions[_reading] = NULL; 128 delete mapper; 129 } 130 131 /* Return the next region. */ 132 133 _reading = 1 - _reading; 134 return _regions[_reading]; 135 } 136 137 // vim: tabstop=4 expandtab shiftwidth=4