IVGCVSW-3964 Implement the Periodic Counter Selection command handler
* Improved the PeriodicCounterPacket class to handle errors properly
* Improved the PeriodicCounterSelectionCommandHandler to handle
invalid counter UIDs in the selection packet
* Added the Periodic Counter Selection command handler to the
ProfilingService class
* Code refactoring and added comments
* Added WaitForPacketSent method to the SendCounterPacket class
to allow waiting for the packets to be sent (useful in the
unit tests)
* Added unit tests and updated the old ones accordingly
* Fixed threading issues with a number of unit tests
Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
Change-Id: I271b7b0bfa801d88fe1725b934d24e30cd839ed7
diff --git a/src/profiling/PeriodicCounterSelectionCommandHandler.cpp b/src/profiling/PeriodicCounterSelectionCommandHandler.cpp
index 9be37fc..db09856 100644
--- a/src/profiling/PeriodicCounterSelectionCommandHandler.cpp
+++ b/src/profiling/PeriodicCounterSelectionCommandHandler.cpp
@@ -7,6 +7,9 @@
#include "ProfilingUtils.hpp"
#include <boost/numeric/conversion/cast.hpp>
+#include <boost/format.hpp>
+
+#include <vector>
namespace armnn
{
@@ -14,57 +17,109 @@
namespace profiling
{
-using namespace std;
-using boost::numeric_cast;
-
void PeriodicCounterSelectionCommandHandler::ParseData(const Packet& packet, CaptureData& captureData)
{
std::vector<uint16_t> counterIds;
- uint32_t sizeOfUint32 = numeric_cast<uint32_t>(sizeof(uint32_t));
- uint32_t sizeOfUint16 = numeric_cast<uint32_t>(sizeof(uint16_t));
+ uint32_t sizeOfUint32 = boost::numeric_cast<uint32_t>(sizeof(uint32_t));
+ uint32_t sizeOfUint16 = boost::numeric_cast<uint32_t>(sizeof(uint16_t));
uint32_t offset = 0;
- if (packet.GetLength() > 0)
+ if (packet.GetLength() < 4)
{
- if (packet.GetLength() >= 4)
+ // Insufficient packet size
+ return;
+ }
+
+ // Parse the capture period
+ uint32_t capturePeriod = ReadUint32(packet.GetData(), offset);
+
+ // Set the capture period
+ captureData.SetCapturePeriod(capturePeriod);
+
+ // Parse the counter ids
+ unsigned int counters = (packet.GetLength() - 4) / 2;
+ if (counters > 0)
+ {
+ counterIds.reserve(counters);
+ offset += sizeOfUint32;
+ for (unsigned int i = 0; i < counters; ++i)
{
- captureData.SetCapturePeriod(ReadUint32(reinterpret_cast<const unsigned char*>(packet.GetData()), offset));
-
- unsigned int counters = (packet.GetLength() - 4) / 2;
-
- if (counters > 0)
- {
- counterIds.reserve(counters);
- offset += sizeOfUint32;
- for(unsigned int pos = 0; pos < counters; ++pos)
- {
- counterIds.emplace_back(ReadUint16(reinterpret_cast<const unsigned char*>(packet.GetData()),
- offset));
- offset += sizeOfUint16;
- }
- }
-
- captureData.SetCounterIds(counterIds);
+ // Parse the counter id
+ uint16_t counterId = ReadUint16(packet.GetData(), offset);
+ counterIds.emplace_back(counterId);
+ offset += sizeOfUint16;
}
}
+
+ // Set the counter ids
+ captureData.SetCounterIds(counterIds);
}
void PeriodicCounterSelectionCommandHandler::operator()(const Packet& packet)
{
- CaptureData captureData;
+ ProfilingState currentState = m_StateMachine.GetCurrentState();
+ switch (currentState)
+ {
+ case ProfilingState::Uninitialised:
+ case ProfilingState::NotConnected:
+ case ProfilingState::WaitingForAck:
+ throw RuntimeException(boost::str(boost::format("Periodic Counter Selection Command Handler invoked while in "
+ "an wrong state: %1%")
+ % GetProfilingStateName(currentState)));
+ case ProfilingState::Active:
+ {
+ // Process the packet
+ if (!(packet.GetPacketFamily() == 0u && packet.GetPacketId() == 4u))
+ {
+ throw armnn::InvalidArgumentException(boost::str(boost::format("Expected Packet family = 0, id = 4 but "
+ "received family = %1%, id = %2%")
+ % packet.GetPacketFamily()
+ % packet.GetPacketId()));
+ }
- ParseData(packet, captureData);
+ // Parse the packet to get the capture period and counter UIDs
+ CaptureData captureData;
+ ParseData(packet, captureData);
- vector<uint16_t> counterIds = captureData.GetCounterIds();
+ // Get the capture data
+ const uint32_t capturePeriod = captureData.GetCapturePeriod();
+ const std::vector<uint16_t>& counterIds = captureData.GetCounterIds();
- m_CaptureDataHolder.SetCaptureData(captureData.GetCapturePeriod(), counterIds);
+ // Check whether the selected counter UIDs are valid
+ std::vector<uint16_t> validCounterIds;
+ for (uint16_t counterId : counterIds)
+ {
+ // Check whether the counter is registered
+ if (!m_ReadCounterValues.IsCounterRegistered(counterId))
+ {
+ // Invalid counter UID, ignore it and continue
+ continue;
+ }
- m_CaptureThread.Start();
+ // The counter is valid
+ validCounterIds.push_back(counterId);
+ }
- // Write packet to Counter Stream Buffer
- m_SendCounterPacket.SendPeriodicCounterSelectionPacket(captureData.GetCapturePeriod(), captureData.GetCounterIds());
+ // Set the capture data with only the valid counter UIDs
+ m_CaptureDataHolder.SetCaptureData(capturePeriod, validCounterIds);
+
+ // Echo back the Periodic Counter Selection packet to the Counter Stream Buffer
+ m_SendCounterPacket.SendPeriodicCounterSelectionPacket(capturePeriod, validCounterIds);
+
+ // Notify the Send Thread that new data is available in the Counter Stream Buffer
+ m_SendCounterPacket.SetReadyToRead();
+
+ // Start the Period Counter Capture thread (if not running already)
+ m_PeriodicCounterCapture.Start();
+
+ break;
+ }
+ default:
+ throw RuntimeException(boost::str(boost::format("Unknown profiling service state: %1%")
+ % static_cast<int>(currentState)));
+ }
}
} // namespace profiling
-} // namespace armnn
\ No newline at end of file
+} // namespace armnn