X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fsim%2Feventq.hh;h=895f69424af2c31c0178799a05d10daf645fee93;hb=abd33d6fd26bb69d3bf53ceb6c2dc8f90d893e34;hp=a73e4b9dcba552794e7ec2cb3863d448820d0255;hpb=35d8e5b52bbf41203c19e7226836511377041d46;p=gem5.git diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a73e4b9dc..895f69424 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -41,13 +41,13 @@ #include #include #include +#include #include #include #include #include #include "base/flags.hh" -#include "base/misc.hh" #include "base/types.hh" #include "debug/Event.hh" #include "sim/serialize.hh" @@ -68,14 +68,11 @@ extern uint32_t numMainEventQueues; //! Array for main event queues. extern std::vector mainEventQueue; -#ifndef SWIG //! The current event queue for the running thread. Access to this queue //! does not require any locking from the thread. extern __thread EventQueue *_curEventQueue; -#endif - //! Current mode of execution: parallel / serial extern bool inParallelMode; @@ -95,7 +92,7 @@ inline void curEventQueue(EventQueue *q) { _curEventQueue = q; } */ class EventBase { - protected: + protected: typedef unsigned short FlagsType; typedef ::Flags Flags; @@ -103,8 +100,14 @@ class EventBase static const FlagsType PublicWrite = 0x001d; // public writable flags static const FlagsType Squashed = 0x0001; // has been squashed static const FlagsType Scheduled = 0x0002; // has been scheduled - static const FlagsType AutoDelete = 0x0004; // delete after dispatch - static const FlagsType AutoSerialize = 0x0008; // must be serialized + static const FlagsType Managed = 0x0004; // Use life cycle manager + static const FlagsType AutoDelete = Managed; // delete after dispatch + /** + * This used to be AutoSerialize. This value can't be reused + * without changing the checkpoint version since the flag field + * gets serialized. + */ + static const FlagsType Reserved0 = 0x0008; static const FlagsType IsExitEvent = 0x0010; // special exit event static const FlagsType IsMainQueue = 0x0020; // on main event queue static const FlagsType Initialized = 0x7a40; // somewhat random bits @@ -158,6 +161,9 @@ class EventBase /// (such as writebacks). static const Priority CPU_Tick_Pri = 50; + /// If we want to exit a thread in a CPU, it comes after CPU_Tick_Pri + static const Priority CPU_Exit_Pri = 64; + /// Statistics events (dump, reset, etc.) come after /// everything else, but before exit. static const Priority Stat_Event_Pri = 90; @@ -281,6 +287,55 @@ class Event : public EventBase, public Serializable // This function isn't really useful if TRACING_ON is not defined virtual void trace(const char *action); //!< trace event activity + protected: /* Memory management */ + /** + * @{ + * Memory management hooks for events that have the Managed flag set + * + * Events can use automatic memory management by setting the + * Managed flag. The default implementation automatically deletes + * events once they have been removed from the event queue. This + * typically happens when events are descheduled or have been + * triggered and not rescheduled. + * + * The methods below may be overridden by events that need custom + * memory management. For example, events exported to Python need + * to impement reference counting to ensure that the Python + * implementation of the event is kept alive while it lives in the + * event queue. + * + * @note Memory managers are responsible for implementing + * reference counting (by overriding both acquireImpl() and + * releaseImpl()) or checking if an event is no longer scheduled + * in releaseImpl() before deallocating it. + */ + + /** + * Managed event scheduled and being held in the event queue. + */ + void acquire() + { + if (flags.isSet(Event::Managed)) + acquireImpl(); + } + + /** + * Managed event removed from the event queue. + */ + void release() { + if (flags.isSet(Event::Managed)) + releaseImpl(); + } + + virtual void acquireImpl() {} + + virtual void releaseImpl() { + if (!scheduled()) + delete this; + } + + /** @} */ + public: /* @@ -339,7 +394,8 @@ class Event : public EventBase, public Serializable bool isExitEvent() const { return flags.isSet(IsExitEvent); } /// Check whether this event will auto-delete - bool isAutoDelete() const { return flags.isSet(AutoDelete); } + bool isManaged() const { return flags.isSet(Managed); } + bool isAutoDelete() const { return isManaged(); } /// Get the time that the event is scheduled Tick when() const { return _when; } @@ -352,13 +408,10 @@ class Event : public EventBase, public Serializable //! NULL. (Overridden in GlobalEvent::BarrierEvent.) virtual BaseGlobalEvent *globalEvent() { return NULL; } -#ifndef SWIG - void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; - void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; -#endif + void serialize(CheckpointOut &cp) const override; + void unserialize(CheckpointIn &cp) override; }; -#ifndef SWIG inline bool operator<(const Event &l, const Event &r) { @@ -397,7 +450,6 @@ operator!=(const Event &l, const Event &r) { return l.when() != r.when() || l.priority() != r.priority(); } -#endif /** * Queue of events sorted in time order @@ -437,7 +489,7 @@ operator!=(const Event &l, const Event &r) * otherwise they risk being scheduled in the past by * handleAsyncInsertions(). */ -class EventQueue : public Serializable +class EventQueue { private: std::string objName; @@ -485,7 +537,6 @@ class EventQueue : public Serializable EventQueue(const EventQueue &); public: -#ifndef SWIG /** * Temporarily migrate execution to a different event queue. * @@ -495,28 +546,36 @@ class EventQueue : public Serializable * example, be useful when performing IO across thread event * queues when timing is not crucial (e.g., during fast * forwarding). + * + * ScopedMigration does nothing if both eqs are the same */ class ScopedMigration { public: - ScopedMigration(EventQueue *_new_eq) - : new_eq(*_new_eq), old_eq(*curEventQueue()) + ScopedMigration(EventQueue *_new_eq, bool _doMigrate = true) + :new_eq(*_new_eq), old_eq(*curEventQueue()), + doMigrate((&new_eq != &old_eq)&&_doMigrate) { - old_eq.unlock(); - new_eq.lock(); - curEventQueue(&new_eq); + if (doMigrate){ + old_eq.unlock(); + new_eq.lock(); + curEventQueue(&new_eq); + } } ~ScopedMigration() { - new_eq.unlock(); - old_eq.lock(); - curEventQueue(&old_eq); + if (doMigrate){ + new_eq.unlock(); + old_eq.lock(); + curEventQueue(&old_eq); + } } private: EventQueue &new_eq; EventQueue &old_eq; + bool doMigrate; }; /** @@ -545,7 +604,6 @@ class EventQueue : public Serializable private: EventQueue &eq; }; -#endif EventQueue(const std::string &n); @@ -643,11 +701,6 @@ class EventQueue : public Serializable void unlock() { service_mutex.unlock(); } /**@}*/ -#ifndef SWIG - void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; - void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; -#endif - /** * Reschedule an event after a checkpoint. * @@ -661,12 +714,15 @@ class EventQueue : public Serializable */ void checkpointReschedule(Event *event); - virtual ~EventQueue() { } + virtual ~EventQueue() + { + while (!empty()) + deschedule(getHead()); + } }; void dumpMainQueue(); -#ifndef SWIG class EventManager { protected: @@ -728,26 +784,6 @@ class EventManager void setCurTick(Tick newVal) { eventq->setCurTick(newVal); } }; -template -void -DelayFunction(EventQueue *eventq, Tick when, T *object) -{ - class DelayEvent : public Event - { - private: - T *object; - - public: - DelayEvent(T *o) - : Event(Default_Pri, AutoDelete), object(o) - { } - void process() { (object->*F)(); } - const char *description() const { return "delay"; } - }; - - eventq->schedule(new DelayEvent(object), when); -} - template class EventWrapper : public Event { @@ -779,6 +815,33 @@ class EventWrapper : public Event const char *description() const { return "EventWrapped"; } }; -#endif + +class EventFunctionWrapper : public Event +{ + private: + std::function callback; + std::string _name; + + public: + EventFunctionWrapper(const std::function &callback, + const std::string &name, + bool del = false, + Priority p = Default_Pri) + : Event(p), callback(callback), _name(name) + { + if (del) + setFlags(AutoDelete); + } + + void process() { callback(); } + + const std::string + name() const + { + return _name + ".wrapped_function_event"; + } + + const char *description() const { return "EventFunctionWrapped"; } +}; #endif // __SIM_EVENTQ_HH__