summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarina DSouza <larsouza@in.ibm.com>2012-03-20 00:32:52 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-04-24 09:40:04 -0500
commit5ac7921a5f77d7d33e7cc86f91522de4751f98b0 (patch)
tree24d6148d99b05f351bcff1a1ad633365cc724532
parent85b30189df1a0c9cffb0a83900c62a78780b5521 (diff)
downloadtalos-hostboot-5ac7921a5f77d7d33e7cc86f91522de4751f98b0.tar.gz
talos-hostboot-5ac7921a5f77d7d33e7cc86f91522de4751f98b0.zip
Initial commit of the Maintenance Cmd Monitor with unit test file.
RTC: 22610 Change-Id: I6e08afda4d658bccf2baa15830dd366a187b54b1 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/775 Tested-by: Jenkins Server Reviewed-by: Bradley W. Bishop <bradleyb@us.ibm.com> Reviewed-by: Zane Shelley <zshelle@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/usr/diag/mdia/makefile2
-rw-r--r--src/usr/diag/mdia/mdiafwd.H1
-rwxr-xr-xsrc/usr/diag/mdia/mdiamonitor.C278
-rwxr-xr-xsrc/usr/diag/mdia/mdiamonitor.H181
-rw-r--r--src/usr/diag/mdia/mdiasm.H10
-rw-r--r--src/usr/diag/mdia/test/mdiatestmonitor.H206
6 files changed, 676 insertions, 2 deletions
diff --git a/src/usr/diag/mdia/makefile b/src/usr/diag/mdia/makefile
index 23600acf1..1cd9e0dc2 100644
--- a/src/usr/diag/mdia/makefile
+++ b/src/usr/diag/mdia/makefile
@@ -26,7 +26,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/diag
MODULE = mdia
-OBJS = mdiatrace.o mdiaworkitem.o
+OBJS = mdiamonitor.o mdiatrace.o mdiaworkitem.o
SUBDIRS = test.d
diff --git a/src/usr/diag/mdia/mdiafwd.H b/src/usr/diag/mdia/mdiafwd.H
index bb7efb98a..8763dbcd2 100644
--- a/src/usr/diag/mdia/mdiafwd.H
+++ b/src/usr/diag/mdia/mdiafwd.H
@@ -34,6 +34,7 @@
/**
* @brief forwards
*/
+class MdiaCommandMonitorTest;
namespace MDIA
{
diff --git a/src/usr/diag/mdia/mdiamonitor.C b/src/usr/diag/mdia/mdiamonitor.C
new file mode 100755
index 000000000..17ed1a942
--- /dev/null
+++ b/src/usr/diag/mdia/mdiamonitor.C
@@ -0,0 +1,278 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/diag/mdia/mdiamonitor.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#include <sys/time.h>
+#include <targeting/util.H>
+#include <vector>
+#include "mdiamonitor.H"
+#include "mdiasm.H"
+
+namespace MDIA
+{
+
+uint64_t CommandMonitor::addMonitor(uint64_t i_to)
+{
+ uint64_t monitor = 0;
+
+ mutex_lock(&iv_mutex);
+
+ monitor = ++iv_nextMonitor;
+
+ // add a new monitor to our map
+
+ iv_monitors[monitor] = i_to;
+
+ mutex_unlock(&iv_mutex);
+
+ return monitor;
+}
+
+void CommandMonitor::removeMonitor(uint64_t i_monitor)
+{
+ mutex_lock(&iv_mutex);
+
+ // remove the specified monitor
+
+ iv_monitors.erase(i_monitor);
+
+ mutex_unlock(&iv_mutex);
+}
+
+tid_t CommandMonitor::getTID()
+{
+ tid_t tid = 0;
+
+ mutex_lock(&iv_mutex);
+
+ tid = iv_tid;
+
+ mutex_unlock(&iv_mutex);
+
+ return tid;
+}
+
+bool CommandMonitor::isShutdown()
+{
+ bool shutdown = false;
+
+ mutex_lock(&iv_mutex);
+
+ shutdown = iv_shutdown;
+
+ mutex_unlock(&iv_mutex);
+
+ return shutdown;
+}
+
+uint64_t CommandMonitor::getMonitorID()
+{
+ uint64_t monitor = 0;
+
+ mutex_lock(&iv_mutex);
+
+ monitor = iv_nextMonitor;
+
+ mutex_unlock(&iv_mutex);
+
+ return monitor;
+}
+
+uint64_t CommandMonitor::getMonitorMapTimeoutEntry(uint64_t i_monitor)
+{
+ uint64_t timeout = 0;
+
+ mutex_lock(&iv_mutex);
+
+ timeout = iv_monitors[i_monitor];
+
+ mutex_unlock(&iv_mutex);
+
+ return timeout;
+}
+
+void CommandMonitor::threadMain(StateMachine & i_sm)
+{
+ static const uint64_t singleStepPauseSecs = 0;
+ static const uint64_t singleStepPauseNSecs = 10000000;
+ static uint64_t wakeupIntervalNanoSecs = 0;
+
+ // periodically wakeup and check for any command
+ // timeouts
+
+ if(TARGETING::is_vpo())
+ {
+ wakeupIntervalNanoSecs = TEN_CTX_SWITCHES_NS;
+ }
+ else
+ {
+ wakeupIntervalNanoSecs = singleStepPauseNSecs;
+ }
+
+ bool shutdown = false, callbackNeeded = false;
+ std::vector<uint64_t> monitorsTimedout;
+
+ while(true)
+ {
+ if( TARGETING::is_vpo() )
+ {
+ nanosleep(0, wakeupIntervalNanoSecs);
+ }
+ else
+ {
+ // sleep for 10 ms
+ nanosleep(singleStepPauseSecs, wakeupIntervalNanoSecs);
+ }
+
+ mutex_lock(&iv_mutex);
+
+ // check to see if the istep is finished
+
+ shutdown = iv_shutdown;
+
+ if(!shutdown)
+ {
+ // scan the monitor map and if any
+ // timed out, inform the state machine
+
+ iterator it = iv_monitors.begin();
+
+ while(it != iv_monitors.end())
+ {
+ if(it->second >= wakeupIntervalNanoSecs)
+ {
+ it->second -= wakeupIntervalNanoSecs;
+ it++;
+ }
+
+ else
+ {
+ callbackNeeded = true;
+ monitorsTimedout.push_back(it->first);
+
+ // remove the monitor
+
+ iv_monitors.erase(it++);
+ }
+ }
+ }
+
+ mutex_unlock(&iv_mutex);
+
+ if(callbackNeeded)
+ {
+ i_sm.processCommandTimeout(monitorsTimedout);
+ callbackNeeded = false;
+ }
+
+ // istep finished...shutdown
+
+ if(shutdown)
+ break;
+ }
+}
+
+namespace CommandMonitorImpl
+{
+struct ThreadArgs
+{
+ CommandMonitor * obj;
+ StateMachine * sm;
+};
+}
+
+void CommandMonitor::start(StateMachine & i_sm)
+{
+ using namespace CommandMonitorImpl;
+
+ // start the monitor thread
+
+ mutex_lock(&iv_mutex);
+
+ // no-op if already started
+
+ if(!iv_tid)
+ {
+ ThreadArgs * args = new ThreadArgs;
+ if(NULL != args)
+ {
+ args->obj = this;
+ args->sm = &i_sm;
+
+ iv_shutdown = false;
+ iv_tid = task_create(&CommandMonitor::staticMain, args);
+
+ }
+ }
+
+ mutex_unlock(&iv_mutex);
+}
+
+void CommandMonitor::shutdown()
+{
+ mutex_lock(&iv_mutex);
+
+ // instruct the monitor thread to shutdown
+
+ iv_shutdown = true;
+
+ // wait for it to exit
+ // unless it was stopped already
+
+ tid_t tid = iv_tid;
+ iv_tid = 0;
+
+ mutex_unlock(&iv_mutex);
+
+ if(tid)
+ task_wait_tid(tid, 0, 0);
+}
+
+void CommandMonitor::staticMain(void * i_args)
+{
+ using namespace CommandMonitorImpl;
+
+ if(NULL != i_args)
+ {
+ ThreadArgs * args = static_cast<ThreadArgs *>(i_args);
+
+ args->obj->threadMain(*args->sm);
+
+ delete args;
+ args = NULL;
+ }
+}
+
+CommandMonitor::CommandMonitor() :
+ iv_tid(0),
+ iv_shutdown(false),
+ iv_nextMonitor(0)
+{
+ mutex_init(&iv_mutex);
+}
+
+CommandMonitor::~CommandMonitor()
+{
+ shutdown();
+
+ mutex_destroy(&iv_mutex);
+}
+}
diff --git a/src/usr/diag/mdia/mdiamonitor.H b/src/usr/diag/mdia/mdiamonitor.H
new file mode 100755
index 000000000..8a955dda9
--- /dev/null
+++ b/src/usr/diag/mdia/mdiamonitor.H
@@ -0,0 +1,181 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/diag/mdia/mdiamonitor.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __MSS_MEMDIAG_MDIAMONITOR_H
+#define __MSS_MEMDIAG_MDIAMONITOR_H
+
+#include <map>
+#include <sys/sync.h>
+#include <sys/task.h>
+#include <stdint.h>
+#include "mdiafwd.H"
+
+/**
+ * @file mdiamonitor.H
+ * @brief mdia Maintenance Command Monitor
+ */
+
+namespace MDIA
+{
+
+/**
+ * @brief maint command timeout monitor
+ *
+ * provides an interface for the workflow state machine
+ * to register / unregister for a monitor and receive a callback
+ * if the monitor times out. when the state machine callback is
+ * made the monitor is automatically removed
+ */
+class CommandMonitor
+{
+ public:
+ /**
+ * @brief add a new monitor with specified timeout value
+ *
+ * @param[in] i_to Maint Cmd timeout value
+ *
+ * @retval Monitor ID
+ */
+ uint64_t addMonitor(uint64_t i_to);
+
+ /**
+ * @brief remove a monitor
+ *
+ * @param[in] i_monitor MonitorMap's key, monitor ID
+ */
+ void removeMonitor(uint64_t i_monitor);
+
+ /**
+ * @brief start the thread up, specify callback
+ *
+ * @param[in] i_sm state machine to which call is made
+ */
+ void start(StateMachine & i_sm);
+
+ /**
+ * @brief shut the thread down
+ */
+ void shutdown();
+
+ /**
+ * @brief ctor
+ */
+ CommandMonitor();
+
+ /**
+ * @brief dtor
+ */
+ ~CommandMonitor();
+
+ private:
+
+ /**
+ * @brief main thread function
+ */
+ static void staticMain(void *);
+
+ /**
+ * @brief main thread function
+ *
+ * @param[in] i_sm state machine provided for callback
+ */
+ void threadMain(StateMachine & i_sm);
+
+ /**
+ * @brief Get the thread id
+ *
+ * @retval ThreadID of CommandMonitor
+ */
+ tid_t getTID();
+
+ /**
+ * @brief Is the CommandMonitor shut down
+ *
+ * @retval true if shutdown
+ * false if not shutdown
+ */
+ bool isShutdown();
+
+ /**
+ * @brief Get the monitor id counter
+ *
+ * @retval Monitor ID counter
+ */
+ uint64_t getMonitorID();
+
+ /**
+ * @brief Get MonitorMap Timeout entry
+ *
+ * @param[in] i_monitor Monitor ID
+ *
+ * @retval Timeout value associated with monitor ID i_monitor
+ */
+ uint64_t getMonitorMapTimeoutEntry(uint64_t i_monitor);
+
+ /**
+ * @brief serialization mutex
+ */
+ mutex_t iv_mutex;
+
+ /**
+ * @brief thread number
+ */
+ tid_t iv_tid;
+
+ /**
+ * @brief shutdown request indicator
+ */
+ bool iv_shutdown;
+
+ /**
+ * @brief monitor ID counter
+ */
+ uint64_t iv_nextMonitor;
+
+ /**
+ * @brief aliases. Map containing monitorID key and timeout entries.
+ */
+ typedef std::map<uint64_t, uint64_t> MonitorMap;
+ typedef MonitorMap::iterator iterator;
+
+ /**
+ * @brief maint command monitors
+ */
+ MonitorMap iv_monitors;
+
+ /**
+ * @brief copy disabled
+ */
+ CommandMonitor(const CommandMonitor &);
+
+ /**
+ * @brief assignment disabled
+ */
+ CommandMonitor & operator=(const CommandMonitor &);
+
+ /**
+ * @brief friend class
+ */
+ friend class ::MdiaCommandMonitorTest;
+};
+}
+#endif
diff --git a/src/usr/diag/mdia/mdiasm.H b/src/usr/diag/mdia/mdiasm.H
index b320f72f6..e83acf89b 100644
--- a/src/usr/diag/mdia/mdiasm.H
+++ b/src/usr/diag/mdia/mdiasm.H
@@ -49,6 +49,14 @@ class StateMachine
void executeWorkItem(TARGETING::TargetHandle_t i_target, WorkFlowPhase i_phase) {}
/**
+ * @brief used by Maint cmd monitor to notify that
+ * maint cmd timed out - called in monitor thread context
+ *
+ * @param[in] i_monitorIDs Vector of monitorIDs
+ */
+ virtual void processCommandTimeout(std::vector<uint64_t> i_monitorIDs) {}
+
+ /**
* @brief ctor
*/
StateMachine() {}
@@ -56,7 +64,7 @@ class StateMachine
/**
* @brief dtor
*/
- ~StateMachine() {}
+ virtual ~StateMachine() {}
private:
diff --git a/src/usr/diag/mdia/test/mdiatestmonitor.H b/src/usr/diag/mdia/test/mdiatestmonitor.H
new file mode 100644
index 000000000..db491f22b
--- /dev/null
+++ b/src/usr/diag/mdia/test/mdiatestmonitor.H
@@ -0,0 +1,206 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/diag/mdia/test/mdiatestmonitor.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __TEST_MDIATESTMONITOR_H
+#define __TEST_MDIATESTMONITOR_H
+
+#include <cxxtest/TestSuite.H>
+#include <sys/task.h>
+#include <sys/time.h>
+#include <stdint.h>
+#include <targeting/util.H>
+#include "../mdiafwd.H"
+#include "../mdiamonitor.H"
+#include "../mdiasm.H"
+
+using namespace MDIA;
+
+class MdiaStateMachineTest: public StateMachine
+{
+ public:
+ void processCommandTimeout(std::vector<uint64_t>)
+ {
+ iv_processedTimeout = true;
+ }
+
+ bool timeoutProcessed()
+ {
+ return iv_processedTimeout;
+ }
+
+ MdiaStateMachineTest() : iv_processedTimeout(false) {}
+
+ ~MdiaStateMachineTest()
+ {
+ iv_processedTimeout = false;
+ }
+
+ private:
+
+ bool iv_processedTimeout;
+};
+
+class MdiaCommandMonitorTest: public CxxTest::TestSuite
+{
+ public:
+ void testCommandMonitor(void)
+ {
+
+ CommandMonitor l_cm;
+ do
+ {
+ if( 0 != l_cm.getTID())
+ {
+ TS_FAIL("Thread id != 0");
+ break;
+ }
+ else if(true == l_cm.isShutdown())
+ {
+ TS_FAIL("Var iv_shutdown != false");
+ break;
+ }
+ else if(0 != l_cm.getMonitorID())
+ {
+ TS_FAIL("Monitor ID counter != 0");
+ break;
+ }
+ else
+ {
+ TS_TRACE("SUCCESS:Dflt CommandMonitor ctor");
+ }
+ }while(0);
+ }
+
+ void teststart(void)
+ {
+ tid_t l_tid = 0;
+ StateMachine l_sm;
+ CommandMonitor* l_cm1 = new CommandMonitor();
+ l_cm1->start(l_sm);
+ l_tid = l_cm1->getTID();
+ if(0 == l_cm1->getTID())
+ {
+ TS_FAIL("Command Monitor task not started");
+ }
+ else
+ {
+ l_cm1->start(l_sm);
+ if(l_tid != l_cm1->getTID())
+ {
+ TS_FAIL("Command Monitor task started again");
+ }
+ else
+ {
+ TS_TRACE("SUCCESS: CommandMonitor::start");
+ }
+ }
+
+ delete l_cm1;
+ l_cm1 = NULL;
+ }
+
+ void testaddMonitor(void)
+ {
+ uint64_t l_timeout = 10;
+ CommandMonitor l_cm1;
+ uint64_t l_mon = l_cm1.addMonitor(l_timeout);
+ if(1 != l_mon)
+ {
+ TS_FAIL("Key monitor ID not set corretly");
+ }
+ else
+ {
+ l_mon = l_cm1.addMonitor(++l_timeout);
+
+ if(l_timeout != l_cm1.getMonitorMapTimeoutEntry(l_mon))
+ {
+ TS_FAIL("Map entries not set right");
+ }
+ else
+ {
+ TS_TRACE("SUCCESS: CommandMonitor::addMonitor");
+ }
+ }
+ }
+
+ void testthreadMainTimeout(void)
+ {
+ uint64_t timeoutNanosecs = 10000000;
+ MdiaStateMachineTest l_sm;
+ CommandMonitor l_cm;
+ l_cm.start(l_sm);
+ l_cm.addMonitor(timeoutNanosecs);
+ l_cm.addMonitor(timeoutNanosecs);
+ if( TARGETING::is_vpo() )
+ {
+ nanosleep(0, TEN_CTX_SWITCHES_NS);
+ }
+ else
+ {
+ //sleep for 100ms
+ nanosleep(0, 100000000);
+ }
+ if(true != l_sm.timeoutProcessed())
+ {
+ TS_FAIL("Not a timeout");
+ }
+ else
+ {
+ TS_TRACE("SUCCESS: testthreadMainTimeout");
+ }
+ }
+
+ void testremoveMonitor(void)
+ {
+ uint64_t l_timeout = 20;
+ CommandMonitor l_cm1;
+ l_cm1.addMonitor(l_timeout);
+ l_cm1.addMonitor(++l_timeout);
+ l_cm1.removeMonitor(2);
+ if(0 != l_cm1.getMonitorMapTimeoutEntry(2))
+ {
+ TS_FAIL("Map entry not removed");
+ }
+ else
+ {
+ TS_TRACE("SUCCESS: CommandMonitor::removeMonitor");
+ }
+ }
+
+ void testshutdown(void)
+ {
+ StateMachine l_sm;
+ CommandMonitor l_cm;
+ l_cm.start(l_sm);
+ l_cm.shutdown();
+ if(false == l_cm.isShutdown() && (0 != l_cm.getTID()))
+ {
+ TS_FAIL("Command Monitor not shutdown");
+ }
+ else
+ {
+ TS_TRACE("SUCCESS: CommandMonitor::shutdown");
+ }
+ }
+
+};
+#endif
OpenPOWER on IntegriCloud