1/* 2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "mem/ruby/structures/PersistentTable.hh" 30 31using namespace std; 32 33 34PersistentTable::PersistentTable() 35{ 36} 37 38PersistentTable::~PersistentTable() 39{ 40} 41 42void 43PersistentTable::persistentRequestLock(Addr address, 44 MachineID locker, 45 AccessType type) 46{ 47 assert(address == makeLineAddress(address)); 48 49 static const PersistentTableEntry dflt; 50 pair<AddressMap::iterator, bool> r = 51 m_map.insert(AddressMap::value_type(address, dflt)); 52 bool present = !r.second; 53 AddressMap::iterator i = r.first; 54 PersistentTableEntry &entry = i->second; 55 56 if (present) { 57 // Make sure we're not already in the locked set 58 assert(!(entry.m_starving.isElement(locker))); 59 } 60 61 entry.m_starving.add(locker); 62 if (type == AccessType_Write) 63 entry.m_request_to_write.add(locker); 64 65 if (present) 66 assert(entry.m_marked.isSubset(entry.m_starving)); 67} 68 69void 70PersistentTable::persistentRequestUnlock(Addr address, 71 MachineID unlocker) 72{ 73 assert(address == makeLineAddress(address)); 74 assert(m_map.count(address)); 75 PersistentTableEntry& entry = m_map[address]; 76 77 // 78 // Make sure we're in the locked set 79 // 80 assert(entry.m_starving.isElement(unlocker)); 81 assert(entry.m_marked.isSubset(entry.m_starving)); 82 entry.m_starving.remove(unlocker); 83 entry.m_marked.remove(unlocker); 84 entry.m_request_to_write.remove(unlocker); 85 assert(entry.m_marked.isSubset(entry.m_starving)); 86 87 // Deallocate if empty 88 if (entry.m_starving.isEmpty()) { 89 assert(entry.m_marked.isEmpty()); 90 m_map.erase(address); 91 } 92} 93 94bool 95PersistentTable::okToIssueStarving(Addr address, 96 MachineID machId) const 97{ 98 assert(address == makeLineAddress(address)); 99 100 AddressMap::const_iterator i = m_map.find(address); 101 if (i == m_map.end()) { 102 // No entry present 103 return true; 104 } 105 106 const PersistentTableEntry &entry = i->second; 107 108 if (entry.m_starving.isElement(machId)) { 109 // We can't issue another lockdown until are previous unlock 110 // has occurred 111 return false; 112 } 113 114 return entry.m_marked.isEmpty(); 115} 116 117MachineID 118PersistentTable::findSmallest(Addr address) const 119{ 120 assert(address == makeLineAddress(address)); 121 AddressMap::const_iterator i = m_map.find(address); 122 assert(i != m_map.end()); 123 const PersistentTableEntry& entry = i->second; 124 return entry.m_starving.smallestElement(); 125} 126 127AccessType 128PersistentTable::typeOfSmallest(Addr address) const 129{ 130 assert(address == makeLineAddress(address)); 131 AddressMap::const_iterator i = m_map.find(address); 132 assert(i != m_map.end()); 133 const PersistentTableEntry& entry = i->second; 134 if (entry.m_request_to_write. 135 isElement(entry.m_starving.smallestElement())) { 136 return AccessType_Write; 137 } else { 138 return AccessType_Read; 139 } 140} 141 142void 143PersistentTable::markEntries(Addr address) 144{ 145 assert(address == makeLineAddress(address)); 146 AddressMap::iterator i = m_map.find(address); 147 if (i == m_map.end()) 148 return; 149 150 PersistentTableEntry& entry = i->second; 151 152 // None should be marked 153 assert(entry.m_marked.isEmpty()); 154 155 // Mark all the nodes currently in the table 156 entry.m_marked = entry.m_starving; 157} 158 159bool 160PersistentTable::isLocked(Addr address) const 161{ 162 assert(address == makeLineAddress(address)); 163 164 // If an entry is present, it must be locked 165 return m_map.count(address) > 0; 166} 167 168int 169PersistentTable::countStarvingForAddress(Addr address) const 170{ 171 assert(address == makeLineAddress(address)); 172 AddressMap::const_iterator i = m_map.find(address); 173 if (i == m_map.end()) 174 return 0; 175 176 const PersistentTableEntry& entry = i->second; 177 return entry.m_starving.count(); 178} 179 180int 181PersistentTable::countReadStarvingForAddress(Addr address) const 182{ 183 assert(address == makeLineAddress(address)); 184 AddressMap::const_iterator i = m_map.find(address); 185 if (i == m_map.end()) 186 return 0; 187 188 const PersistentTableEntry& entry = i->second; 189 return entry.m_starving.count() - entry.m_request_to_write.count(); 190} 191 192void 193PersistentTable::print(ostream& out) const 194{ 195} 196 197