Pre-/postprocessing is done within the event objects (Bochs-specific event added), ++coding-style.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1366 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
adrian
2012-06-21 10:47:22 +00:00
parent 5effe564f0
commit ad0cfb9b11
12 changed files with 420 additions and 438 deletions

View File

@ -209,7 +209,7 @@ void BochsController::fireInterruptDone()
m_Flows.toggle(m_CurrFlow);
}
void BochsController::m_onTimerTrigger(void* thisPtr)
void BochsController::onTimerTrigger(void* thisPtr)
{
// FIXME: The timer logic can be modified to use only one timer in Bochs.
// (For now, this suffices.)
@ -225,57 +225,6 @@ void BochsController::m_onTimerTrigger(void* thisPtr)
simulator.m_EvList.fireActiveEvents();
}
timer_id_t BochsController::m_registerTimer(TimerEvent* pev)
{
assert(pev != NULL);
return static_cast<timer_id_t>(
bx_pc_system.register_timer(pev, m_onTimerTrigger, pev->getTimeout(), !pev->getOnceFlag(),
1/*start immediately*/, "Fail*: BochsController"/*name*/));
}
bool BochsController::m_unregisterTimer(TimerEvent* pev)
{
assert(pev != NULL);
bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
}
bool BochsController::onEventAddition(BaseEvent* pev)
{
TimerEvent* tmev;
// Register the timer event in the Bochs simulator:
if ((tmev = dynamic_cast<TimerEvent*>(pev)) != NULL) {
tmev->setId(m_registerTimer(tmev));
if(tmev->getId() == -1)
return false; // unable to register the timer (error in Bochs' function call)
}
// Note: Maybe more stuff to do here for other event types.
return true;
}
void BochsController::onEventDeletion(BaseEvent* pev)
{
TimerEvent* tmev;
// Unregister the time event:
if ((tmev = dynamic_cast<TimerEvent*>(pev)) != NULL) {
m_unregisterTimer(tmev);
}
// Note: Maybe more stuff to do here for other event types.
}
void BochsController::onEventTrigger(BaseEvent* pev)
{
TimerEvent* tmev;
// Unregister the time event, if once-flag is true:
if ((tmev = dynamic_cast<TimerEvent*>(pev)) != NULL) {
if (tmev->getOnceFlag()) // deregister the timer (timer = single timeout)
m_unregisterTimer(tmev);
else // re-add the event (repetitive timer), tunneling the onEventAddition-handler
m_EvList.add(tmev, tmev->getParent());
}
// Note: Maybe more stuff to do here for other event types.
}
const std::string& BochsController::getMnemonic() const
{
static std::string str;

View File

@ -8,6 +8,7 @@
#include <string.h>
#include "FailBochsGlobals.hpp"
#include "BochsEvents.hpp"
#include "../SimulatorController.hpp"
#include "../Event.hpp"
@ -34,40 +35,6 @@ private:
unsigned m_Counter; //! current instr-ptr counter
std::ostream* m_pDest; //! debug output object (defaults to \c std::cout)
#endif
/**
* Static internal event handler for TimerEvents. This static function is
* called when a previously registered (Bochs) timer triggers. This function
* searches for the provided TimerEvent object within the EventList and
* fires such an event by calling \c fireActiveEvents().
* @param thisPtr a pointer to the TimerEvent-object triggered
*
* FIXME: Due to Bochs internal timer and ips-configuration related stuff,
* the simulator sometimes panics with "keyboard error:21" (see line
* 1777 in bios/rombios.c, function keyboard_init()) if a TimerEvent
* is added *before* the bios has been loaded and initialized. To
* reproduce this error, try adding a TimerEvent as the initial step
* in your experiment code and wait for it (addEventAndWait()).
*/
static void m_onTimerTrigger(void *thisPtr);
/**
* Registers a timer in the Bochs simulator. This timer fires \a TimerEvents
* to inform the corresponding experiment-flow. Note that the number of timers
* (in Bochs) is limited to \c BX_MAX_TIMERS (defaults to 64 in v2.4.6).
* @param pev a pointer to the (experiment flow-) allocated TimerEvent object,
* providing all required information to start the time, e.g. the
* timeout value.
* @return \c The unique id of the timer recently created. This id is carried
* along with the TimerEvent, @see getId(). On error, -1 is returned
* (e.g. because a timer with the same id is already existing)
*/
timer_id_t m_registerTimer(TimerEvent* pev);
/**
* Deletes a timer. No further events will be triggered by the timer.
* @param pev a pointer to the TimerEvent-object to be removed
* @return \c true if the timer with \a pev->getId() has been removed
* successfully, \c false otherwise
*/
bool m_unregisterTimer(TimerEvent* pev);
public:
// Initialize the controller.
BochsController();
@ -81,7 +48,8 @@ public:
* @param instrPtr the new instruction pointer
* @param address_space the address space the CPU is currently in
*/
void onInstrPtrChanged(address_t instrPtr, address_t address_space, BX_CPU_C *context, bxICacheEntry_c *cache_entry);
void onInstrPtrChanged(address_t instrPtr, address_t address_space, BX_CPU_C *context,
bxICacheEntry_c *cache_entry);
/**
* I/O port communication handler. This method is called (from
* the IOPortCom aspect) every time when Bochs performs a port I/O operation.
@ -91,31 +59,20 @@ public:
*/
void onIOPortEvent(unsigned char data, unsigned port, bool out);
/**
* This method is called when an experiment flow adds a new event by
* calling \c simulator.addEvent(pev) or \c simulator.addEventAndWait(pev).
* More specifically, the event will be added to the event-list first
* (buffer-list, to be precise) and then this event handler is called.
* @param pev the event which has been added
* @return You should return \c true to continue and \c false to prevent
* the addition of the event \a pev.
* Static internal event handler for TimerEvents. This static function is
* called when a previously registered (Bochs) timer triggers. This function
* searches for the provided TimerEvent object within the EventList and
* fires such an event by calling \c fireActiveEvents().
* @param thisPtr a pointer to the TimerEvent-object triggered
*
* FIXME: Due to Bochs internal timer and ips-configuration related stuff,
* the simulator sometimes panics with "keyboard error:21" (see line
* 1777 in bios/rombios.c, function keyboard_init()) if a TimerEvent
* is added *before* the bios has been loaded and initialized. To
* reproduce this error, try adding a \c TimerEvent as the initial step
* in your experiment code and wait for it (\c addEventAndWait()).
*/
bool onEventAddition(BaseEvent* pev);
/**
* This method is called when an experiment flow removes an event from
* the event-management by calling \c removeEvent(prev), \c clearEvents()
* or by deleting a complete flow (\c removeFlow). More specifically,
* this event handler will be called *before* the event is actually deleted.
* @param pev the event to be deleted when returning from the event handler
*/
void onEventDeletion(BaseEvent* pev);
/**
* This method is called when an previously added event is about to be
* triggered by the simulator-backend. More specifically, this event handler
* will be called *before* the event is actually triggered, i.e. before the
* corresponding coroutine is toggled.
* @param pev the event to be triggered when returning from the event handler
*/
void onEventTrigger(BaseEvent* pev);
static void onTimerTrigger(void *thisPtr);
/* ********************************************************************
* Simulator Controller & Access API:
* ********************************************************************/

View File

@ -0,0 +1,36 @@
#include "BochsEvents.hpp"
#include "../SALInst.hpp"
namespace fail {
bool TimerEvent::onEventAddition()
{
// Register the timer event in the Bochs simulator:
setId(m_registerTimer(this));
if(getId() == -1)
return false; // unable to register the timer (error in Bochs' function call)
return true;
}
void TimerEvent::onEventDeletion()
{
// Unregister the time event:
m_unregisterTimer(this);
}
timer_id_t TimerEvent::m_registerTimer(TimerEvent* pev)
{
assert(pev != NULL && "FATAL ERROR: TimerEvent object ptr cannot be NULL!");
return static_cast<timer_id_t>(
bx_pc_system.register_timer(pev, BochsController::onTimerTrigger, pev->getTimeout(),
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
}
bool TimerEvent::m_unregisterTimer(TimerEvent* pev)
{
assert(pev != NULL && "FATAL ERROR: TimerEvent object ptr cannot be NULL!");
bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
}
} // end-of-namespace: fail

View File

@ -0,0 +1,78 @@
#ifndef __BOCHS_EVENTS_HPP__
#define __BOCHS_EVENTS_HPP__
#include "../Event.hpp"
#include "BochsController.hpp"
namespace fail {
/**
* \class TimerEvent
* Concrete TimerEvent implementation of GenericTimerEvent for the Bochs
* simulator backend.
*/
class TimerEvent : public GenericTimerEvent {
private:
/**
* Registers a timer in the Bochs simulator. This timer fires \a TimerEvents
* to inform the corresponding experiment-flow. Note that the number of timers
* (in Bochs) is limited to \c BX_MAX_TIMERS (defaults to 64 in v2.4.6).
* @param pev a pointer to the (experiment flow-) allocated TimerEvent object,
* providing all required information to start the time, e.g. the
* timeout value.
* @return \c The unique id of the timer recently created. This id is carried
* along with the TimerEvent, @see getId(). On errors, -1 is returned
* (e.g. because a timer with the same id is already existing)
*/
static timer_id_t m_registerTimer(TimerEvent* pev);
/**
* Deletes a timer. No further events will be triggered by the timer.
* @param pev a pointer to the TimerEvent-object to be removed
* @return \c true if the timer with \a pev->getId() has been removed
* successfully, \c false otherwise
*/
static bool m_unregisterTimer(TimerEvent* pev);
public:
/**
* Creates a new timer event. This can be used to implement a timeout-
* mechanism in the experiment-flow. The timer starts automatically when
* added to FailBochs.
* @param timeout the time intervall in milliseconds (ms)
* @param once \c true, if the TimerEvent should be triggered once,
* \c false if it should occur regularly
* @see SimulatorController::addEvent
*/
TimerEvent(unsigned timeout)
: GenericTimerEvent(timeout) { }
~TimerEvent() { onEventDeletion(); }
/**
* This method is called when an experiment flow adds a new event by
* calling \c simulator.addEvent(pev) or \c simulator.addEventAndWait(pev).
* More specifically, the event will be added to the event-list first
* (buffer-list, to be precise) and then this event handler is called.
* @return You should return \c true to continue and \c false to prevent
* the addition of the event \a pev, yielding an error in the
* experiment flow (i.e. -1 is returned).
*/
virtual bool onEventAddition();
/**
* This method is called when an experiment flow removes an event from
* the event-management by calling \c removeEvent(prev), \c clearEvents()
* or by deleting a complete flow (\c removeFlow). More specifically, this
* event handler will be called *before* the event is actually deleted.
*/
virtual void onEventDeletion();
/**
* This method is called when an previously added event is about to be
* triggered by the simulator-backend. More specifically, this event handler
* will be called *before* the event is actually triggered, i.e. before the
* corresponding coroutine is toggled.
*/
void onEventTrigger() { onEventDeletion(); }
};
} // end-of-namespace: fail
#endif // __BOCHS_EVENTS_HPP__