eventq.cc revision 10905:a6ca6831e775
110249Sstephan.diestelhorst@arm.com/*
210249Sstephan.diestelhorst@arm.com * Copyright (c) 2000-2005 The Regents of The University of Michigan
310249Sstephan.diestelhorst@arm.com * Copyright (c) 2008 The Hewlett-Packard Development Company
410249Sstephan.diestelhorst@arm.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
510249Sstephan.diestelhorst@arm.com * All rights reserved.
610249Sstephan.diestelhorst@arm.com *
710249Sstephan.diestelhorst@arm.com * Redistribution and use in source and binary forms, with or without
810249Sstephan.diestelhorst@arm.com * modification, are permitted provided that the following conditions are
910249Sstephan.diestelhorst@arm.com * met: redistributions of source code must retain the above copyright
1010249Sstephan.diestelhorst@arm.com * notice, this list of conditions and the following disclaimer;
1110249Sstephan.diestelhorst@arm.com * redistributions in binary form must reproduce the above copyright
1210249Sstephan.diestelhorst@arm.com * notice, this list of conditions and the following disclaimer in the
1310249Sstephan.diestelhorst@arm.com * documentation and/or other materials provided with the distribution;
1410249Sstephan.diestelhorst@arm.com * neither the name of the copyright holders nor the names of its
1510249Sstephan.diestelhorst@arm.com * contributors may be used to endorse or promote products derived from
1610249Sstephan.diestelhorst@arm.com * this software without specific prior written permission.
1710249Sstephan.diestelhorst@arm.com *
1810249Sstephan.diestelhorst@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1910249Sstephan.diestelhorst@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2010249Sstephan.diestelhorst@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2110249Sstephan.diestelhorst@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2210249Sstephan.diestelhorst@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2310249Sstephan.diestelhorst@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2410249Sstephan.diestelhorst@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2510249Sstephan.diestelhorst@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2610249Sstephan.diestelhorst@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2710249Sstephan.diestelhorst@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2810249Sstephan.diestelhorst@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2910249Sstephan.diestelhorst@arm.com *
3010249Sstephan.diestelhorst@arm.com * Authors: Steve Reinhardt
3110249Sstephan.diestelhorst@arm.com *          Nathan Binkert
3210249Sstephan.diestelhorst@arm.com *          Steve Raasch
3310249Sstephan.diestelhorst@arm.com */
3410249Sstephan.diestelhorst@arm.com
3510249Sstephan.diestelhorst@arm.com#include <cassert>
3610249Sstephan.diestelhorst@arm.com#include <iostream>
3710249Sstephan.diestelhorst@arm.com#include <string>
3810249Sstephan.diestelhorst@arm.com#include <vector>
3910249Sstephan.diestelhorst@arm.com
4010249Sstephan.diestelhorst@arm.com#include "base/hashmap.hh"
4110249Sstephan.diestelhorst@arm.com#include "base/misc.hh"
4210249Sstephan.diestelhorst@arm.com#include "base/trace.hh"
4310249Sstephan.diestelhorst@arm.com#include "cpu/smt.hh"
4410249Sstephan.diestelhorst@arm.com#include "debug/Config.hh"
4510249Sstephan.diestelhorst@arm.com#include "sim/core.hh"
4610249Sstephan.diestelhorst@arm.com#include "sim/eventq_impl.hh"
4710249Sstephan.diestelhorst@arm.com
4810249Sstephan.diestelhorst@arm.comusing namespace std;
4910249Sstephan.diestelhorst@arm.com
5010249Sstephan.diestelhorst@arm.comTick simQuantum = 0;
5110249Sstephan.diestelhorst@arm.com
5210249Sstephan.diestelhorst@arm.com//
5310249Sstephan.diestelhorst@arm.com// Main Event Queues
5410249Sstephan.diestelhorst@arm.com//
5510395Sstephan.diestelhorst@arm.com// Events on these queues are processed at the *beginning* of each
5610249Sstephan.diestelhorst@arm.com// cycle, before the pipeline simulation is performed.
5710249Sstephan.diestelhorst@arm.com//
5810249Sstephan.diestelhorst@arm.comuint32_t numMainEventQueues = 0;
5910249Sstephan.diestelhorst@arm.comvector<EventQueue *> mainEventQueue;
6010249Sstephan.diestelhorst@arm.com__thread EventQueue *_curEventQueue = NULL;
6110249Sstephan.diestelhorst@arm.combool inParallelMode = false;
6210395Sstephan.diestelhorst@arm.com
6310249Sstephan.diestelhorst@arm.comEventQueue *
6410249Sstephan.diestelhorst@arm.comgetEventQueue(uint32_t index)
6510249Sstephan.diestelhorst@arm.com{
6610249Sstephan.diestelhorst@arm.com    while (numMainEventQueues <= index) {
6710249Sstephan.diestelhorst@arm.com        numMainEventQueues++;
6810249Sstephan.diestelhorst@arm.com        mainEventQueue.push_back(
6910249Sstephan.diestelhorst@arm.com            new EventQueue(csprintf("MainEventQueue-%d", index)));
7010249Sstephan.diestelhorst@arm.com    }
7110249Sstephan.diestelhorst@arm.com
7210249Sstephan.diestelhorst@arm.com    return mainEventQueue[index];
7310249Sstephan.diestelhorst@arm.com}
7410249Sstephan.diestelhorst@arm.com
7510249Sstephan.diestelhorst@arm.com#ifndef NDEBUG
7610249Sstephan.diestelhorst@arm.comCounter Event::instanceCounter = 0;
7710249Sstephan.diestelhorst@arm.com#endif
7810249Sstephan.diestelhorst@arm.com
7910249Sstephan.diestelhorst@arm.comEvent::~Event()
8010249Sstephan.diestelhorst@arm.com{
8110249Sstephan.diestelhorst@arm.com    assert(!scheduled());
8210249Sstephan.diestelhorst@arm.com    flags = 0;
8310249Sstephan.diestelhorst@arm.com}
8410395Sstephan.diestelhorst@arm.com
8510395Sstephan.diestelhorst@arm.comconst std::string
8610395Sstephan.diestelhorst@arm.comEvent::name() const
8710395Sstephan.diestelhorst@arm.com{
8810395Sstephan.diestelhorst@arm.com#ifndef NDEBUG
8910395Sstephan.diestelhorst@arm.com    return csprintf("Event_%d", instance);
9010395Sstephan.diestelhorst@arm.com#else
9110395Sstephan.diestelhorst@arm.com    return csprintf("Event_%x", (uintptr_t)this);
9210395Sstephan.diestelhorst@arm.com#endif
9310395Sstephan.diestelhorst@arm.com}
9410395Sstephan.diestelhorst@arm.com
9510395Sstephan.diestelhorst@arm.com
9610249Sstephan.diestelhorst@arm.comEvent *
9710249Sstephan.diestelhorst@arm.comEvent::insertBefore(Event *event, Event *curr)
9810249Sstephan.diestelhorst@arm.com{
9910249Sstephan.diestelhorst@arm.com    // Either way, event will be the top element in the 'in bin' list
10010249Sstephan.diestelhorst@arm.com    // which is the pointer we need in order to look into the list, so
10110249Sstephan.diestelhorst@arm.com    // we need to insert that into the bin list.
10210249Sstephan.diestelhorst@arm.com    if (!curr || *event < *curr) {
10310249Sstephan.diestelhorst@arm.com        // Insert the event before the current list since it is in the future.
10410249Sstephan.diestelhorst@arm.com        event->nextBin = curr;
10510249Sstephan.diestelhorst@arm.com        event->nextInBin = NULL;
10610249Sstephan.diestelhorst@arm.com    } else {
10710249Sstephan.diestelhorst@arm.com        // Since we're on the correct list, we need to point to the next list
10810249Sstephan.diestelhorst@arm.com        event->nextBin = curr->nextBin;  // curr->nextBin can now become stale
10910249Sstephan.diestelhorst@arm.com
11010249Sstephan.diestelhorst@arm.com        // Insert event at the top of the stack
11110249Sstephan.diestelhorst@arm.com        event->nextInBin = curr;
11210249Sstephan.diestelhorst@arm.com    }
11310249Sstephan.diestelhorst@arm.com
11410249Sstephan.diestelhorst@arm.com    return event;
11510249Sstephan.diestelhorst@arm.com}
11610249Sstephan.diestelhorst@arm.com
11710249Sstephan.diestelhorst@arm.comvoid
11810249Sstephan.diestelhorst@arm.comEventQueue::insert(Event *event)
11910249Sstephan.diestelhorst@arm.com{
12010249Sstephan.diestelhorst@arm.com    // Deal with the head case
12110249Sstephan.diestelhorst@arm.com    if (!head || *event <= *head) {
12210249Sstephan.diestelhorst@arm.com        head = Event::insertBefore(event, head);
12310249Sstephan.diestelhorst@arm.com        return;
12410249Sstephan.diestelhorst@arm.com    }
12510249Sstephan.diestelhorst@arm.com
12610249Sstephan.diestelhorst@arm.com    // Figure out either which 'in bin' list we are on, or where a new list
12710249Sstephan.diestelhorst@arm.com    // needs to be inserted
12810249Sstephan.diestelhorst@arm.com    Event *prev = head;
12910249Sstephan.diestelhorst@arm.com    Event *curr = head->nextBin;
13010249Sstephan.diestelhorst@arm.com    while (curr && *curr < *event) {
13110249Sstephan.diestelhorst@arm.com        prev = curr;
13210249Sstephan.diestelhorst@arm.com        curr = curr->nextBin;
13310249Sstephan.diestelhorst@arm.com    }
13410249Sstephan.diestelhorst@arm.com
13510249Sstephan.diestelhorst@arm.com    // Note: this operation may render all nextBin pointers on the
13610249Sstephan.diestelhorst@arm.com    // prev 'in bin' list stale (except for the top one)
13710249Sstephan.diestelhorst@arm.com    prev->nextBin = Event::insertBefore(event, curr);
13810249Sstephan.diestelhorst@arm.com}
13910249Sstephan.diestelhorst@arm.com
14010398Sstephan.diestelhorst@arm.comEvent *
14110398Sstephan.diestelhorst@arm.comEvent::removeItem(Event *event, Event *top)
14210398Sstephan.diestelhorst@arm.com{
14310398Sstephan.diestelhorst@arm.com    Event *curr = top;
14410398Sstephan.diestelhorst@arm.com    Event *next = top->nextInBin;
14510398Sstephan.diestelhorst@arm.com
14610398Sstephan.diestelhorst@arm.com    // if we removed the top item, we need to handle things specially
14710398Sstephan.diestelhorst@arm.com    // and just remove the top item, fixing up the next bin pointer of
14810398Sstephan.diestelhorst@arm.com    // the new top item
14910249Sstephan.diestelhorst@arm.com    if (event == top) {
15010249Sstephan.diestelhorst@arm.com        if (!next)
15110249Sstephan.diestelhorst@arm.com            return top->nextBin;
15210395Sstephan.diestelhorst@arm.com        next->nextBin = top->nextBin;
15310395Sstephan.diestelhorst@arm.com        return next;
15410395Sstephan.diestelhorst@arm.com    }
15510395Sstephan.diestelhorst@arm.com
15610395Sstephan.diestelhorst@arm.com    // Since we already checked the current element, we're going to
15710395Sstephan.diestelhorst@arm.com    // keep checking event against the next element.
15810395Sstephan.diestelhorst@arm.com    while (event != next) {
15910395Sstephan.diestelhorst@arm.com        if (!next)
16010395Sstephan.diestelhorst@arm.com            panic("event not found!");
16110398Sstephan.diestelhorst@arm.com
16210398Sstephan.diestelhorst@arm.com        curr = next;
16310398Sstephan.diestelhorst@arm.com        next = next->nextInBin;
16410398Sstephan.diestelhorst@arm.com    }
16510398Sstephan.diestelhorst@arm.com
16610398Sstephan.diestelhorst@arm.com    // remove next from the 'in bin' list since it's what we're looking for
16710398Sstephan.diestelhorst@arm.com    curr->nextInBin = next->nextInBin;
16810398Sstephan.diestelhorst@arm.com    return top;
16910398Sstephan.diestelhorst@arm.com}
17010398Sstephan.diestelhorst@arm.com
17110398Sstephan.diestelhorst@arm.comvoid
17210398Sstephan.diestelhorst@arm.comEventQueue::remove(Event *event)
17310398Sstephan.diestelhorst@arm.com{
17410398Sstephan.diestelhorst@arm.com    if (head == NULL)
17510398Sstephan.diestelhorst@arm.com        panic("event not found!");
17610398Sstephan.diestelhorst@arm.com
17710398Sstephan.diestelhorst@arm.com    assert(event->queue == this);
17810398Sstephan.diestelhorst@arm.com
17910398Sstephan.diestelhorst@arm.com    // deal with an event on the head's 'in bin' list (event has the same
18010395Sstephan.diestelhorst@arm.com    // time as the head)
18110395Sstephan.diestelhorst@arm.com    if (*head == *event) {
18210395Sstephan.diestelhorst@arm.com        head = Event::removeItem(event, head);
18310249Sstephan.diestelhorst@arm.com        return;
18410249Sstephan.diestelhorst@arm.com    }
18510249Sstephan.diestelhorst@arm.com
18610249Sstephan.diestelhorst@arm.com    // Find the 'in bin' list that this event belongs on
18710249Sstephan.diestelhorst@arm.com    Event *prev = head;
18810249Sstephan.diestelhorst@arm.com    Event *curr = head->nextBin;
18910249Sstephan.diestelhorst@arm.com    while (curr && *curr < *event) {
19010249Sstephan.diestelhorst@arm.com        prev = curr;
19110249Sstephan.diestelhorst@arm.com        curr = curr->nextBin;
19210249Sstephan.diestelhorst@arm.com    }
19310249Sstephan.diestelhorst@arm.com
19410249Sstephan.diestelhorst@arm.com    if (!curr || *curr != *event)
19510249Sstephan.diestelhorst@arm.com        panic("event not found!");
19610249Sstephan.diestelhorst@arm.com
19710249Sstephan.diestelhorst@arm.com    // curr points to the top item of the the correct 'in bin' list, when
19810249Sstephan.diestelhorst@arm.com    // we remove an item, it returns the new top item (which may be
19910249Sstephan.diestelhorst@arm.com    // unchanged)
20010249Sstephan.diestelhorst@arm.com    prev->nextBin = Event::removeItem(event, curr);
20111168Sandreas.hansson@arm.com}
20211168Sandreas.hansson@arm.com
20310249Sstephan.diestelhorst@arm.comEvent *
20410249Sstephan.diestelhorst@arm.comEventQueue::serviceOne()
20510249Sstephan.diestelhorst@arm.com{
20610249Sstephan.diestelhorst@arm.com    std::lock_guard<EventQueue> lock(*this);
20710249Sstephan.diestelhorst@arm.com    Event *event = head;
20810249Sstephan.diestelhorst@arm.com    Event *next = head->nextInBin;
20910395Sstephan.diestelhorst@arm.com    event->flags.clear(Event::Scheduled);
21010395Sstephan.diestelhorst@arm.com
21110395Sstephan.diestelhorst@arm.com    if (next) {
21210395Sstephan.diestelhorst@arm.com        // update the next bin pointer since it could be stale
21310395Sstephan.diestelhorst@arm.com        next->nextBin = head->nextBin;
21410249Sstephan.diestelhorst@arm.com
21510249Sstephan.diestelhorst@arm.com        // pop the stack
21610249Sstephan.diestelhorst@arm.com        head = next;
21710249Sstephan.diestelhorst@arm.com    } else {
21810249Sstephan.diestelhorst@arm.com        // this was the only element on the 'in bin' list, so get rid of
21910249Sstephan.diestelhorst@arm.com        // the 'in bin' list and point to the next bin list
22010249Sstephan.diestelhorst@arm.com        head = head->nextBin;
22110249Sstephan.diestelhorst@arm.com    }
22210249Sstephan.diestelhorst@arm.com
22310249Sstephan.diestelhorst@arm.com    // handle action
22410249Sstephan.diestelhorst@arm.com    if (!event->squashed()) {
22510249Sstephan.diestelhorst@arm.com        // forward current cycle to the time when this event occurs.
22610249Sstephan.diestelhorst@arm.com        setCurTick(event->when());
22710249Sstephan.diestelhorst@arm.com
22810249Sstephan.diestelhorst@arm.com        event->process();
22910249Sstephan.diestelhorst@arm.com        if (event->isExitEvent()) {
23010249Sstephan.diestelhorst@arm.com            assert(!event->flags.isSet(Event::AutoDelete) ||
23110249Sstephan.diestelhorst@arm.com                   !event->flags.isSet(Event::IsMainQueue)); // would be silly
23210249Sstephan.diestelhorst@arm.com            return event;
23310249Sstephan.diestelhorst@arm.com        }
23410249Sstephan.diestelhorst@arm.com    } else {
23510249Sstephan.diestelhorst@arm.com        event->flags.clear(Event::Squashed);
23610249Sstephan.diestelhorst@arm.com    }
23710249Sstephan.diestelhorst@arm.com
23810249Sstephan.diestelhorst@arm.com    if (event->flags.isSet(Event::AutoDelete) && !event->scheduled())
23910249Sstephan.diestelhorst@arm.com        delete event;
24010249Sstephan.diestelhorst@arm.com
24110249Sstephan.diestelhorst@arm.com    return NULL;
24210249Sstephan.diestelhorst@arm.com}
24310249Sstephan.diestelhorst@arm.com
24410249Sstephan.diestelhorst@arm.comvoid
24510249Sstephan.diestelhorst@arm.comEvent::serialize(CheckpointOut &cp) const
24610249Sstephan.diestelhorst@arm.com{
24710249Sstephan.diestelhorst@arm.com    SERIALIZE_SCALAR(_when);
24810249Sstephan.diestelhorst@arm.com    SERIALIZE_SCALAR(_priority);
24910249Sstephan.diestelhorst@arm.com    short _flags = flags;
25010249Sstephan.diestelhorst@arm.com    SERIALIZE_SCALAR(_flags);
25110360Sandreas.hansson@arm.com}
25210360Sandreas.hansson@arm.com
25310249Sstephan.diestelhorst@arm.comvoid
25410249Sstephan.diestelhorst@arm.comEvent::unserialize(CheckpointIn &cp)
25510249Sstephan.diestelhorst@arm.com{
25610249Sstephan.diestelhorst@arm.com}
25710249Sstephan.diestelhorst@arm.com
25810249Sstephan.diestelhorst@arm.comvoid
25910249Sstephan.diestelhorst@arm.comEvent::unserializeEvent(CheckpointIn &cp, EventQueue *eventq)
26010249Sstephan.diestelhorst@arm.com{
26110249Sstephan.diestelhorst@arm.com    if (scheduled())
26210249Sstephan.diestelhorst@arm.com        eventq->deschedule(this);
26310249Sstephan.diestelhorst@arm.com
26410249Sstephan.diestelhorst@arm.com    UNSERIALIZE_SCALAR(_when);
26510249Sstephan.diestelhorst@arm.com    UNSERIALIZE_SCALAR(_priority);
26610249Sstephan.diestelhorst@arm.com
26710249Sstephan.diestelhorst@arm.com    short _flags;
26810249Sstephan.diestelhorst@arm.com    UNSERIALIZE_SCALAR(_flags);
26910249Sstephan.diestelhorst@arm.com
27010249Sstephan.diestelhorst@arm.com    // Old checkpoints had no concept of the Initialized flag
27110249Sstephan.diestelhorst@arm.com    // so restoring from old checkpoints always fail.
27210249Sstephan.diestelhorst@arm.com    // Events are initialized on construction but original code
27310249Sstephan.diestelhorst@arm.com    // "flags = _flags" would just overwrite the initialization.
27410249Sstephan.diestelhorst@arm.com    // So, read in the checkpoint flags, but then set the Initialized
27510249Sstephan.diestelhorst@arm.com    // flag on top of it in order to avoid failures.
27610249Sstephan.diestelhorst@arm.com    assert(initialized());
27710249Sstephan.diestelhorst@arm.com    flags = _flags;
27810249Sstephan.diestelhorst@arm.com    flags.set(Initialized);
27910249Sstephan.diestelhorst@arm.com
28010249Sstephan.diestelhorst@arm.com    // need to see if original event was in a scheduled, unsquashed
28110249Sstephan.diestelhorst@arm.com    // state, but don't want to restore those flags in the current
28210249Sstephan.diestelhorst@arm.com    // object itself (since they aren't immediately true)
28310249Sstephan.diestelhorst@arm.com    bool wasScheduled = flags.isSet(Scheduled) && !flags.isSet(Squashed);
28410249Sstephan.diestelhorst@arm.com    flags.clear(Squashed | Scheduled);
28510249Sstephan.diestelhorst@arm.com
28610249Sstephan.diestelhorst@arm.com    if (wasScheduled) {
28710249Sstephan.diestelhorst@arm.com        DPRINTF(Config, "rescheduling at %d\n", _when);
28810249Sstephan.diestelhorst@arm.com        eventq->schedule(this, _when);
289    }
290}
291
292void
293EventQueue::serialize(CheckpointOut &cp) const
294{
295    std::list<Event *> eventPtrs;
296
297    int numEvents = 0;
298    Event *nextBin = head;
299    while (nextBin) {
300        Event *nextInBin = nextBin;
301
302        while (nextInBin) {
303            if (nextInBin->flags.isSet(Event::AutoSerialize)) {
304                eventPtrs.push_back(nextInBin);
305                paramOut(cp, csprintf("event%d", numEvents++),
306                         nextInBin->name());
307            }
308            nextInBin = nextInBin->nextInBin;
309        }
310
311        nextBin = nextBin->nextBin;
312    }
313
314    SERIALIZE_SCALAR(numEvents);
315
316    for (Event *ev : eventPtrs)
317        ev->serializeSection(cp, ev->name());
318}
319
320void
321EventQueue::unserialize(CheckpointIn &cp)
322{
323    int numEvents;
324    UNSERIALIZE_SCALAR(numEvents);
325
326    std::string eventName;
327    for (int i = 0; i < numEvents; i++) {
328        // get the pointer value associated with the event
329        paramIn(cp, csprintf("event%d", i), eventName);
330
331        // create the event based on its pointer value
332        Serializable::create(cp, eventName);
333    }
334}
335
336void
337EventQueue::dump() const
338{
339    cprintf("============================================================\n");
340    cprintf("EventQueue Dump  (cycle %d)\n", curTick());
341    cprintf("------------------------------------------------------------\n");
342
343    if (empty())
344        cprintf("<No Events>\n");
345    else {
346        Event *nextBin = head;
347        while (nextBin) {
348            Event *nextInBin = nextBin;
349            while (nextInBin) {
350                nextInBin->dump();
351                nextInBin = nextInBin->nextInBin;
352            }
353
354            nextBin = nextBin->nextBin;
355        }
356    }
357
358    cprintf("============================================================\n");
359}
360
361bool
362EventQueue::debugVerify() const
363{
364    m5::hash_map<long, bool> map;
365
366    Tick time = 0;
367    short priority = 0;
368
369    Event *nextBin = head;
370    while (nextBin) {
371        Event *nextInBin = nextBin;
372        while (nextInBin) {
373            if (nextInBin->when() < time) {
374                cprintf("time goes backwards!");
375                nextInBin->dump();
376                return false;
377            } else if (nextInBin->when() == time &&
378                       nextInBin->priority() < priority) {
379                cprintf("priority inverted!");
380                nextInBin->dump();
381                return false;
382            }
383
384            if (map[reinterpret_cast<long>(nextInBin)]) {
385                cprintf("Node already seen");
386                nextInBin->dump();
387                return false;
388            }
389            map[reinterpret_cast<long>(nextInBin)] = true;
390
391            time = nextInBin->when();
392            priority = nextInBin->priority();
393
394            nextInBin = nextInBin->nextInBin;
395        }
396
397        nextBin = nextBin->nextBin;
398    }
399
400    return true;
401}
402
403Event*
404EventQueue::replaceHead(Event* s)
405{
406    Event* t = head;
407    head = s;
408    return t;
409}
410
411void
412dumpMainQueue()
413{
414    for (uint32_t i = 0; i < numMainEventQueues; ++i) {
415        mainEventQueue[i]->dump();
416    }
417}
418
419
420const char *
421Event::description() const
422{
423    return "generic";
424}
425
426void
427Event::trace(const char *action)
428{
429    // This DPRINTF is unconditional because calls to this function
430    // are protected by an 'if (DTRACE(Event))' in the inlined Event
431    // methods.
432    //
433    // This is just a default implementation for derived classes where
434    // it's not worth doing anything special.  If you want to put a
435    // more informative message in the trace, override this method on
436    // the particular subclass where you have the information that
437    // needs to be printed.
438    DPRINTFN("%s event %s @ %d\n", description(), action, when());
439}
440
441void
442Event::dump() const
443{
444    cprintf("Event %s (%s)\n", name(), description());
445    cprintf("Flags: %#x\n", flags);
446#ifdef EVENTQ_DEBUG
447    cprintf("Created: %d\n", whenCreated);
448#endif
449    if (scheduled()) {
450#ifdef EVENTQ_DEBUG
451        cprintf("Scheduled at  %d\n", whenScheduled);
452#endif
453        cprintf("Scheduled for %d, priority %d\n", when(), _priority);
454    } else {
455        cprintf("Not Scheduled\n");
456    }
457}
458
459EventQueue::EventQueue(const string &n)
460    : objName(n), head(NULL), _curTick(0)
461{
462}
463
464void
465EventQueue::asyncInsert(Event *event)
466{
467    async_queue_mutex.lock();
468    async_queue.push_back(event);
469    async_queue_mutex.unlock();
470}
471
472void
473EventQueue::handleAsyncInsertions()
474{
475    assert(this == curEventQueue());
476    async_queue_mutex.lock();
477
478    while (!async_queue.empty()) {
479        insert(async_queue.front());
480        async_queue.pop_front();
481    }
482
483    async_queue_mutex.unlock();
484}
485