global_event.hh revision 10361
19983Sstever@gmail.com/* 29983Sstever@gmail.com * Copyright (c) 2011-2013 Advanced Micro Devices, Inc. 39983Sstever@gmail.com * Copyright (c) 2013 Mark D. Hill and David A. Wood 49983Sstever@gmail.com * All rights reserved. 59983Sstever@gmail.com * 69983Sstever@gmail.com * Redistribution and use in source and binary forms, with or without 79983Sstever@gmail.com * modification, are permitted provided that the following conditions are 89983Sstever@gmail.com * met: redistributions of source code must retain the above copyright 99983Sstever@gmail.com * notice, this list of conditions and the following disclaimer; 109983Sstever@gmail.com * redistributions in binary form must reproduce the above copyright 119983Sstever@gmail.com * notice, this list of conditions and the following disclaimer in the 129983Sstever@gmail.com * documentation and/or other materials provided with the distribution; 139983Sstever@gmail.com * neither the name of the copyright holders nor the names of its 149983Sstever@gmail.com * contributors may be used to endorse or promote products derived from 159983Sstever@gmail.com * this software without specific prior written permission. 169983Sstever@gmail.com * 179983Sstever@gmail.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 189983Sstever@gmail.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 199983Sstever@gmail.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 209983Sstever@gmail.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 219983Sstever@gmail.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 229983Sstever@gmail.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 239983Sstever@gmail.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 249983Sstever@gmail.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 259983Sstever@gmail.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 269983Sstever@gmail.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 279983Sstever@gmail.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 289983Sstever@gmail.com * 299983Sstever@gmail.com * Authors: Steve Reinhardt 309983Sstever@gmail.com */ 319983Sstever@gmail.com 329983Sstever@gmail.com#ifndef __SIM_GLOBAL_EVENT_HH__ 339983Sstever@gmail.com#define __SIM_GLOBAL_EVENT_HH__ 349983Sstever@gmail.com 359983Sstever@gmail.com#include <mutex> 369983Sstever@gmail.com#include <vector> 379983Sstever@gmail.com 389983Sstever@gmail.com#include "base/barrier.hh" 399983Sstever@gmail.com#include "sim/eventq_impl.hh" 409983Sstever@gmail.com 419983Sstever@gmail.com/** 429983Sstever@gmail.com * @file sim/global_event.hh 439983Sstever@gmail.com * Global events and related declarations. 449983Sstever@gmail.com * 459983Sstever@gmail.com * A global event is an event that occurs across all threads, i.e., 469983Sstever@gmail.com * globally. It consists of a set of "local" (regular) Events, one 479983Sstever@gmail.com * per thread/event queue, a barrier object, and common state. The 489983Sstever@gmail.com * local events are scheduled for the same tick. The local event 499983Sstever@gmail.com * process() method enters the barrier to wait for other threads; once 509983Sstever@gmail.com * all threads reach that tick (and enter the associated barrier), the 519983Sstever@gmail.com * global event is triggered and its associated activity is performed. 529983Sstever@gmail.com * 539983Sstever@gmail.com * There are two basic global event patterns, GlobalEvent and 549983Sstever@gmail.com * GlobalSyncEvent. GlobalEvent is the base class for typical global 559983Sstever@gmail.com * events, while GlobalSyncEvent is optimized for global 569983Sstever@gmail.com * synchronization operations. 579983Sstever@gmail.com */ 589983Sstever@gmail.com 599983Sstever@gmail.com/** 609983Sstever@gmail.com * Common base class for GlobalEvent and GlobalSyncEvent. 619983Sstever@gmail.com */ 629983Sstever@gmail.comclass BaseGlobalEvent : public EventBase 639983Sstever@gmail.com{ 649983Sstever@gmail.com private: 659983Sstever@gmail.com //! Mutex variable for providing exculsive right to schedule global 669983Sstever@gmail.com //! events. This is necessary so that a total order can be maintained 679983Sstever@gmail.com //! amongst the global events. Without ensuring the total order, it is 689983Sstever@gmail.com //! possible that threads execute global events in different orders, 699983Sstever@gmail.com //! which can result in a deadlock. 709983Sstever@gmail.com static std::mutex globalQMutex; 719983Sstever@gmail.com 729983Sstever@gmail.com protected: 739983Sstever@gmail.com 749983Sstever@gmail.com /// The base class for the local events that will synchronize 759983Sstever@gmail.com /// threads to perform the global event. This class is abstract, 769983Sstever@gmail.com /// since it derives from the abstract Event class but still does 779983Sstever@gmail.com /// not define the required process() method. 789983Sstever@gmail.com class BarrierEvent : public Event 799983Sstever@gmail.com { 809983Sstever@gmail.com protected: 819983Sstever@gmail.com BaseGlobalEvent *_globalEvent; 829983Sstever@gmail.com 839983Sstever@gmail.com BarrierEvent(BaseGlobalEvent *global_event, Priority p, Flags f) 849983Sstever@gmail.com : Event(p, f), _globalEvent(global_event) 859983Sstever@gmail.com { 869983Sstever@gmail.com } 879983Sstever@gmail.com 889983Sstever@gmail.com ~BarrierEvent(); 899983Sstever@gmail.com 909983Sstever@gmail.com friend class BaseGlobalEvent; 919983Sstever@gmail.com 929983Sstever@gmail.com bool globalBarrier() 939983Sstever@gmail.com { 9410153Sandreas@sandberg.pp.se // This method will be called from the process() method in 9510153Sandreas@sandberg.pp.se // the local barrier events 9610153Sandreas@sandberg.pp.se // (GlobalSyncEvent::BarrierEvent). The local event 9710153Sandreas@sandberg.pp.se // queues are always locked when servicing events (calling 9810153Sandreas@sandberg.pp.se // the process() method), which means that it will be 9910153Sandreas@sandberg.pp.se // locked when entering this method. We need to unlock it 10010153Sandreas@sandberg.pp.se // while waiting on the barrier to prevent deadlocks if 10110153Sandreas@sandberg.pp.se // another thread wants to lock the event queue. 10210153Sandreas@sandberg.pp.se EventQueue::ScopedRelease release(curEventQueue()); 10310361SAndreas.Sandberg@ARM.com return _globalEvent->barrier.wait(); 1049983Sstever@gmail.com } 1059983Sstever@gmail.com 1069983Sstever@gmail.com public: 1079983Sstever@gmail.com virtual BaseGlobalEvent *globalEvent() { return _globalEvent; } 1089983Sstever@gmail.com }; 1099983Sstever@gmail.com 1109983Sstever@gmail.com //! The barrier that all threads wait on before performing the 1119983Sstever@gmail.com //! global event. 11210361SAndreas.Sandberg@ARM.com Barrier barrier; 1139983Sstever@gmail.com 1149983Sstever@gmail.com //! The individual local event instances (one per thread/event queue). 1159983Sstever@gmail.com std::vector<BarrierEvent *> barrierEvent; 1169983Sstever@gmail.com 1179983Sstever@gmail.com public: 1189983Sstever@gmail.com BaseGlobalEvent(Priority p, Flags f); 1199983Sstever@gmail.com 1209983Sstever@gmail.com virtual ~BaseGlobalEvent(); 1219983Sstever@gmail.com 1229983Sstever@gmail.com virtual void process() = 0; 1239983Sstever@gmail.com 1249983Sstever@gmail.com virtual const char *description() const = 0; 1259983Sstever@gmail.com 1269983Sstever@gmail.com void schedule(Tick when); 1279983Sstever@gmail.com 1289983Sstever@gmail.com bool scheduled() const 1299983Sstever@gmail.com { 1309983Sstever@gmail.com bool sched = false; 1319983Sstever@gmail.com for (uint32_t i = 0; i < numMainEventQueues; ++i) { 1329983Sstever@gmail.com sched = sched || barrierEvent[i]->scheduled(); 1339983Sstever@gmail.com } 1349983Sstever@gmail.com 1359983Sstever@gmail.com return sched; 1369983Sstever@gmail.com } 1379983Sstever@gmail.com 1389983Sstever@gmail.com Tick when() const 1399983Sstever@gmail.com { 1409983Sstever@gmail.com assert(numMainEventQueues > 0); 1419983Sstever@gmail.com return barrierEvent[0]->when(); 1429983Sstever@gmail.com } 1439983Sstever@gmail.com 1449983Sstever@gmail.com void deschedule(); 1459983Sstever@gmail.com void reschedule(Tick when); 1469983Sstever@gmail.com}; 1479983Sstever@gmail.com 1489983Sstever@gmail.com 1499983Sstever@gmail.com/** 1509983Sstever@gmail.com * Funky intermediate class to support CRTP so that we can have a 1519983Sstever@gmail.com * common constructor to create the local events, even though the 1529983Sstever@gmail.com * types of the local events are defined in the derived classes. 1539983Sstever@gmail.com */ 1549983Sstever@gmail.comtemplate <class Derived> 1559983Sstever@gmail.comclass BaseGlobalEventTemplate : public BaseGlobalEvent 1569983Sstever@gmail.com{ 1579983Sstever@gmail.com protected: 1589983Sstever@gmail.com BaseGlobalEventTemplate(Priority p, Flags f) 1599983Sstever@gmail.com : BaseGlobalEvent(p, f) 1609983Sstever@gmail.com { 1619983Sstever@gmail.com for (int i = 0; i < numMainEventQueues; ++i) 1629983Sstever@gmail.com barrierEvent[i] = new typename Derived::BarrierEvent(this, p, f); 1639983Sstever@gmail.com } 1649983Sstever@gmail.com}; 1659983Sstever@gmail.com 1669983Sstever@gmail.com 1679983Sstever@gmail.com/** 1689983Sstever@gmail.com * The main global event class. Ordinary global events should derive 1699983Sstever@gmail.com * from this class, and define process() to specify the action to be 1709983Sstever@gmail.com * taken when the event is reached. All threads will synchronize at a 1719983Sstever@gmail.com * barrier, exactly one of the threads will execute the process() 1729983Sstever@gmail.com * method, then the threads will synchronize again so that none of 1739983Sstever@gmail.com * them continue until process() is complete. 1749983Sstever@gmail.com */ 1759983Sstever@gmail.comclass GlobalEvent : public BaseGlobalEventTemplate<GlobalEvent> 1769983Sstever@gmail.com{ 1779983Sstever@gmail.com public: 1789983Sstever@gmail.com typedef BaseGlobalEventTemplate<GlobalEvent> Base; 1799983Sstever@gmail.com 1809983Sstever@gmail.com class BarrierEvent : public Base::BarrierEvent 1819983Sstever@gmail.com { 1829983Sstever@gmail.com public: 1839983Sstever@gmail.com void process(); 1849983Sstever@gmail.com BarrierEvent(Base *global_event, Priority p, Flags f) 1859983Sstever@gmail.com : Base::BarrierEvent(global_event, p, f) 1869983Sstever@gmail.com { } 1879983Sstever@gmail.com }; 1889983Sstever@gmail.com 1899983Sstever@gmail.com GlobalEvent(Priority p, Flags f) 1909983Sstever@gmail.com : Base(p, f) 1919983Sstever@gmail.com { } 1929983Sstever@gmail.com 1939983Sstever@gmail.com GlobalEvent(Tick when, Priority p, Flags f) 1949983Sstever@gmail.com : Base(p, f) 1959983Sstever@gmail.com { 1969983Sstever@gmail.com schedule(when); 1979983Sstever@gmail.com } 1989983Sstever@gmail.com 1999983Sstever@gmail.com virtual void process() = 0; 2009983Sstever@gmail.com}; 2019983Sstever@gmail.com 2029983Sstever@gmail.com/** 2039983Sstever@gmail.com * A special global event that synchronizes all threads and forces 2049983Sstever@gmail.com * them to process asynchronously enqueued events. Useful for 2059983Sstever@gmail.com * separating quanta in a quantum-based parallel simulation. 2069983Sstever@gmail.com */ 2079983Sstever@gmail.comclass GlobalSyncEvent : public BaseGlobalEventTemplate<GlobalSyncEvent> 2089983Sstever@gmail.com{ 2099983Sstever@gmail.com public: 2109983Sstever@gmail.com typedef BaseGlobalEventTemplate<GlobalSyncEvent> Base; 2119983Sstever@gmail.com 2129983Sstever@gmail.com class BarrierEvent : public Base::BarrierEvent 2139983Sstever@gmail.com { 2149983Sstever@gmail.com public: 2159983Sstever@gmail.com void process(); 2169983Sstever@gmail.com BarrierEvent(Base *global_event, Priority p, Flags f) 2179983Sstever@gmail.com : Base::BarrierEvent(global_event, p, f) 2189983Sstever@gmail.com { } 2199983Sstever@gmail.com }; 2209983Sstever@gmail.com 2219983Sstever@gmail.com GlobalSyncEvent(Priority p, Flags f) 2229983Sstever@gmail.com : Base(p, f) 2239983Sstever@gmail.com { } 2249983Sstever@gmail.com 2259983Sstever@gmail.com GlobalSyncEvent(Tick when, Tick _repeat, Priority p, Flags f) 2269983Sstever@gmail.com : Base(p, f), repeat(_repeat) 2279983Sstever@gmail.com { 2289983Sstever@gmail.com schedule(when); 2299983Sstever@gmail.com } 2309983Sstever@gmail.com 2319983Sstever@gmail.com void process(); 2329983Sstever@gmail.com 2339983Sstever@gmail.com const char *description() const; 2349983Sstever@gmail.com 2359983Sstever@gmail.com Tick repeat; 2369983Sstever@gmail.com}; 2379983Sstever@gmail.com 2389983Sstever@gmail.com 2399983Sstever@gmail.com#endif // __SIM_GLOBAL_EVENT_HH__ 240