global_event.cc revision 9983
1/* 2 * Copyright (c) 2011-2013 Advanced Micro Devices, Inc. 3 * Copyright (c) 2013 Mark D. Hill and David A. Wood 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Steve Reinhardt 30 */ 31 32#include "sim/global_event.hh" 33 34std::mutex BaseGlobalEvent::globalQMutex; 35 36BaseGlobalEvent::BaseGlobalEvent(Priority p, Flags f) 37{ 38 barrierEvent.resize(numMainEventQueues); 39 barrier = new Barrier(numMainEventQueues); 40} 41 42 43BaseGlobalEvent::~BaseGlobalEvent() 44{ 45 // see GlobalEvent::BarrierEvent::~BarrierEvent() comments 46 if (barrierEvent[0] != NULL) { 47 for (int i = 0; i < numMainEventQueues; ++i) 48 delete barrierEvent[i]; 49 } 50} 51 52 53void BaseGlobalEvent::schedule(Tick when) 54{ 55 // This function is scheduling a global event, which actually is a 56 // set of local events, one event on each eventq. Global events need 57 // to have a total order. A thread cannot start executing events that 58 // follow a global event till all other threads have executed that global 59 // event as well. If global events were not in a total order, a deadlock 60 // would occur for there will be two threads who would be waiting for 61 // each other to execute the global events they themselves have executed. 62 // 63 // To ensure this total order, we do two things. 64 // First, before scheduling any global event, a thread needs to acquire 65 // the lock globalQMutex. This ensures that only one thread can schedule 66 // global events at any given time. 67 // Second, the local events corresponding to a global event are always 68 // first inserted in to the asyncq, irrespective of whether or not the 69 // thread scheduling the event owns the eventq on which the event is 70 // being scheduled. Thus global events have the same order in the asyncq 71 // of each thread. When they are inserted in the actual eventq, the 72 // comparators in the Event class ensure that the total order is 73 // maintained. 74 75 globalQMutex.lock(); 76 77 for (int i = 0; i < numMainEventQueues; ++i) { 78 mainEventQueue[i]->schedule(barrierEvent[i], when, true); 79 } 80 81 globalQMutex.unlock(); 82} 83 84void BaseGlobalEvent::deschedule() 85{ 86 EventQueue *q = curEventQueue(); 87 for (uint32_t i = 0; i < numMainEventQueues; ++i) { 88 if (barrierEvent[i]->scheduled()) { 89 curEventQueue(mainEventQueue[i]); 90 mainEventQueue[i]->deschedule(barrierEvent[i]); 91 } 92 } 93 94 curEventQueue(q); 95} 96 97void BaseGlobalEvent::reschedule(Tick when) 98{ 99 // Read the comment in the schedule() function above. 100 globalQMutex.lock(); 101 102 for (uint32_t i = 0; i < numMainEventQueues; ++i) { 103 if (barrierEvent[i]->scheduled()) 104 mainEventQueue[i]->reschedule(barrierEvent[i], when); 105 else 106 mainEventQueue[i]->schedule(barrierEvent[i], when, true); 107 } 108 109 globalQMutex.unlock(); 110} 111 112BaseGlobalEvent::BarrierEvent::~BarrierEvent() 113{ 114 // if AutoDelete is set, local events will get deleted in event 115 // loop, but we need to delete GlobalEvent object too... so let 116 // the local event in slot 0 do it 117 if (isFlagSet(AutoDelete) && _globalEvent->barrierEvent[0] == this) { 118 // set backpointer to NULL so that global event knows not to 119 // turn around and recursively delete local events 120 _globalEvent->barrierEvent[0] = NULL; 121 delete _globalEvent; 122 } 123} 124 125 126void 127GlobalEvent::BarrierEvent::process() 128{ 129 // wait for all queues to arrive at barrier, then process event 130 if (globalBarrier()) { 131 _globalEvent->process(); 132 } 133 134 // second barrier to force all queues to wait for event processing 135 // to finish before continuing 136 globalBarrier(); 137} 138 139 140void 141GlobalSyncEvent::BarrierEvent::process() 142{ 143 // wait for all queues to arrive at barrier, then process event 144 if (globalBarrier()) { 145 _globalEvent->process(); 146 } 147 148 // second barrier to force all queues to wait for event processing 149 // to finish before continuing 150 globalBarrier(); 151 curEventQueue()->handleAsyncInsertions(); 152} 153 154void 155GlobalSyncEvent::process() 156{ 157 if (repeat) { 158 schedule(curTick() + repeat); 159 } 160} 161 162const char * 163GlobalSyncEvent::description() const 164{ 165 return "GlobalSyncEvent"; 166} 167