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