drain.cc revision 11417
15647Sgblack@eecs.umich.edu/* 25647Sgblack@eecs.umich.edu * Copyright (c) 2012, 2015 ARM Limited 35647Sgblack@eecs.umich.edu * All rights reserved 45647Sgblack@eecs.umich.edu * 55647Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 65647Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 75647Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 85647Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 95647Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 105647Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 115647Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 125647Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 135647Sgblack@eecs.umich.edu * 145647Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 155647Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 165647Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 175647Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 185647Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 195647Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 205647Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 215647Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 225647Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 235647Sgblack@eecs.umich.edu * this software without specific prior written permission. 245647Sgblack@eecs.umich.edu * 255647Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 265647Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 275647Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 285647Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 295647Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 305647Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 315647Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 325647Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 335647Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 345647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 355647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 365647Sgblack@eecs.umich.edu * 375647Sgblack@eecs.umich.edu * Authors: Andreas Sandberg 385647Sgblack@eecs.umich.edu */ 395647Sgblack@eecs.umich.edu 405647Sgblack@eecs.umich.edu#include "sim/drain.hh" 415647Sgblack@eecs.umich.edu 425647Sgblack@eecs.umich.edu#include "base/misc.hh" 435647Sgblack@eecs.umich.edu#include "base/trace.hh" 445647Sgblack@eecs.umich.edu#include "debug/Drain.hh" 455647Sgblack@eecs.umich.edu#include "sim/sim_exit.hh" 465647Sgblack@eecs.umich.edu#include "sim/sim_object.hh" 475647Sgblack@eecs.umich.edu 485647Sgblack@eecs.umich.eduDrainManager DrainManager::_instance; 495647Sgblack@eecs.umich.edu 505647Sgblack@eecs.umich.eduDrainManager::DrainManager() 515647Sgblack@eecs.umich.edu : _count(0), 525647Sgblack@eecs.umich.edu _state(DrainState::Running) 535647Sgblack@eecs.umich.edu{ 545647Sgblack@eecs.umich.edu} 555647Sgblack@eecs.umich.edu 565647Sgblack@eecs.umich.eduDrainManager::~DrainManager() 575647Sgblack@eecs.umich.edu{ 585648Sgblack@eecs.umich.edu} 595647Sgblack@eecs.umich.edu 605654Sgblack@eecs.umich.edubool 615647Sgblack@eecs.umich.eduDrainManager::tryDrain() 625654Sgblack@eecs.umich.edu{ 636046Sgblack@eecs.umich.edu panic_if(_state == DrainState::Drained, 645647Sgblack@eecs.umich.edu "Trying to drain a drained system\n"); 655648Sgblack@eecs.umich.edu 665648Sgblack@eecs.umich.edu panic_if(_count != 0, 675647Sgblack@eecs.umich.edu "Drain counter must be zero at the start of a drain cycle\n"); 685647Sgblack@eecs.umich.edu 695647Sgblack@eecs.umich.edu DPRINTF(Drain, "Trying to drain %u objects.\n", drainableCount()); 705647Sgblack@eecs.umich.edu _state = DrainState::Draining; 715647Sgblack@eecs.umich.edu for (auto *obj : _allDrainable) { 725647Sgblack@eecs.umich.edu DrainState status = obj->dmDrain(); 735647Sgblack@eecs.umich.edu if (DTRACE(Drain) && status != DrainState::Drained) { 745647Sgblack@eecs.umich.edu SimObject *temp = dynamic_cast<SimObject*>(obj); 755647Sgblack@eecs.umich.edu if (temp) 765648Sgblack@eecs.umich.edu DPRINTF(Drain, "Failed to drain %s\n", temp->name()); 775647Sgblack@eecs.umich.edu } 785648Sgblack@eecs.umich.edu _count += status == DrainState::Drained ? 0 : 1; 795648Sgblack@eecs.umich.edu } 805648Sgblack@eecs.umich.edu 815648Sgblack@eecs.umich.edu if (_count == 0) { 825648Sgblack@eecs.umich.edu DPRINTF(Drain, "Drain done.\n"); 835648Sgblack@eecs.umich.edu _state = DrainState::Drained; 845648Sgblack@eecs.umich.edu return true; 855648Sgblack@eecs.umich.edu } else { 865648Sgblack@eecs.umich.edu DPRINTF(Drain, "Need another drain cycle. %u/%u objects not ready.\n", 875648Sgblack@eecs.umich.edu _count, drainableCount()); 885648Sgblack@eecs.umich.edu return false; 895648Sgblack@eecs.umich.edu } 905648Sgblack@eecs.umich.edu} 915648Sgblack@eecs.umich.edu 925648Sgblack@eecs.umich.eduvoid 935648Sgblack@eecs.umich.eduDrainManager::resume() 945648Sgblack@eecs.umich.edu{ 955648Sgblack@eecs.umich.edu panic_if(_state == DrainState::Running, 965648Sgblack@eecs.umich.edu "Trying to resume a system that is already running\n"); 975648Sgblack@eecs.umich.edu 985648Sgblack@eecs.umich.edu warn_if(_state == DrainState::Draining, 995648Sgblack@eecs.umich.edu "Resuming a system that isn't fully drained, this is untested and " 1005648Sgblack@eecs.umich.edu "likely to break\n"); 1015648Sgblack@eecs.umich.edu 1025648Sgblack@eecs.umich.edu panic_if(_count != 0, 1035648Sgblack@eecs.umich.edu "Resume called in the middle of a drain cycle. %u objects " 1045648Sgblack@eecs.umich.edu "left to drain.\n", _count); 1055648Sgblack@eecs.umich.edu 1065648Sgblack@eecs.umich.edu DPRINTF(Drain, "Resuming %u objects.\n", drainableCount()); 1075648Sgblack@eecs.umich.edu _state = DrainState::Running; 1085648Sgblack@eecs.umich.edu for (auto *obj : _allDrainable) 1095648Sgblack@eecs.umich.edu obj->dmDrainResume(); 1105648Sgblack@eecs.umich.edu} 1115648Sgblack@eecs.umich.edu 1125648Sgblack@eecs.umich.eduvoid 1135648Sgblack@eecs.umich.eduDrainManager::preCheckpointRestore() 1145648Sgblack@eecs.umich.edu{ 1155648Sgblack@eecs.umich.edu panic_if(_state != DrainState::Running, 1165648Sgblack@eecs.umich.edu "preCheckpointRestore() called on a system that isn't in the " 1175648Sgblack@eecs.umich.edu "Running state.\n"); 1185648Sgblack@eecs.umich.edu 1195648Sgblack@eecs.umich.edu DPRINTF(Drain, "Applying pre-restore fixes to %u objects.\n", 1205648Sgblack@eecs.umich.edu drainableCount()); 1215648Sgblack@eecs.umich.edu _state = DrainState::Drained; 1225648Sgblack@eecs.umich.edu for (auto *obj : _allDrainable) 1235648Sgblack@eecs.umich.edu obj->_drainState = DrainState::Drained; 1245648Sgblack@eecs.umich.edu} 1255648Sgblack@eecs.umich.edu 1265648Sgblack@eecs.umich.eduvoid 1275648Sgblack@eecs.umich.eduDrainManager::signalDrainDone() 1285648Sgblack@eecs.umich.edu{ 1295648Sgblack@eecs.umich.edu if (--_count == 0) { 1305648Sgblack@eecs.umich.edu DPRINTF(Drain, "All %u objects drained..\n", drainableCount()); 1315648Sgblack@eecs.umich.edu exitSimLoop("Finished drain", 0); 1325648Sgblack@eecs.umich.edu } 1335648Sgblack@eecs.umich.edu} 1345648Sgblack@eecs.umich.edu 1355648Sgblack@eecs.umich.edu 1365648Sgblack@eecs.umich.eduvoid 1375648Sgblack@eecs.umich.eduDrainManager::registerDrainable(Drainable *obj) 1385648Sgblack@eecs.umich.edu{ 1395648Sgblack@eecs.umich.edu std::lock_guard<std::mutex> lock(globalLock); 1405648Sgblack@eecs.umich.edu _allDrainable.insert(obj); 1415648Sgblack@eecs.umich.edu} 1425648Sgblack@eecs.umich.edu 1435648Sgblack@eecs.umich.eduvoid 1445648Sgblack@eecs.umich.eduDrainManager::unregisterDrainable(Drainable *obj) 1455648Sgblack@eecs.umich.edu{ 1465648Sgblack@eecs.umich.edu std::lock_guard<std::mutex> lock(globalLock); 1475648Sgblack@eecs.umich.edu _allDrainable.erase(obj); 1485648Sgblack@eecs.umich.edu} 1495648Sgblack@eecs.umich.edu 1505648Sgblack@eecs.umich.edusize_t 1515648Sgblack@eecs.umich.eduDrainManager::drainableCount() const 1525648Sgblack@eecs.umich.edu{ 1535648Sgblack@eecs.umich.edu std::lock_guard<std::mutex> lock(globalLock); 1545648Sgblack@eecs.umich.edu return _allDrainable.size(); 1555648Sgblack@eecs.umich.edu} 1565648Sgblack@eecs.umich.edu 1575648Sgblack@eecs.umich.edu 1585648Sgblack@eecs.umich.edu 1595648Sgblack@eecs.umich.eduDrainable::Drainable() 1605648Sgblack@eecs.umich.edu : _drainManager(DrainManager::instance()), 1615648Sgblack@eecs.umich.edu _drainState(_drainManager.state()) 1625648Sgblack@eecs.umich.edu{ 1635648Sgblack@eecs.umich.edu _drainManager.registerDrainable(this); 1645648Sgblack@eecs.umich.edu} 1655648Sgblack@eecs.umich.edu 1665648Sgblack@eecs.umich.eduDrainable::~Drainable() 1675648Sgblack@eecs.umich.edu{ 1685648Sgblack@eecs.umich.edu _drainManager.unregisterDrainable(this); 1695648Sgblack@eecs.umich.edu} 1705648Sgblack@eecs.umich.edu 1715648Sgblack@eecs.umich.eduDrainState 1725648Sgblack@eecs.umich.eduDrainable::dmDrain() 1735648Sgblack@eecs.umich.edu{ 1745648Sgblack@eecs.umich.edu _drainState = DrainState::Draining; 1755648Sgblack@eecs.umich.edu _drainState = drain(); 1765648Sgblack@eecs.umich.edu assert(_drainState == DrainState::Draining || 1775648Sgblack@eecs.umich.edu _drainState == DrainState::Drained); 1785648Sgblack@eecs.umich.edu 1795648Sgblack@eecs.umich.edu return _drainState; 1805648Sgblack@eecs.umich.edu} 1815648Sgblack@eecs.umich.edu 1825648Sgblack@eecs.umich.eduvoid 1835648Sgblack@eecs.umich.eduDrainable::dmDrainResume() 1845648Sgblack@eecs.umich.edu{ 1855648Sgblack@eecs.umich.edu panic_if(_drainState != DrainState::Drained, 1865648Sgblack@eecs.umich.edu "Trying to resume an object that hasn't been drained\n"); 1875648Sgblack@eecs.umich.edu 1885648Sgblack@eecs.umich.edu _drainState = DrainState::Running; 1895648Sgblack@eecs.umich.edu drainResume(); 1905648Sgblack@eecs.umich.edu} 1915648Sgblack@eecs.umich.edu