forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
6.5 KiB
200 lines
6.5 KiB
// |
|
// Copyright © 2019 Arm Ltd and Contributors. All rights reserved. |
|
// SPDX-License-Identifier: MIT |
|
// |
|
|
|
#include "GatordMockService.hpp" |
|
|
|
#include <common/include/Assert.hpp> |
|
#include <common/include/CommandHandlerRegistry.hpp> |
|
#include <common/include/CommonProfilingUtils.hpp> |
|
#include <common/include/PacketVersionResolver.hpp> |
|
#include <common/include/NetworkSockets.hpp> |
|
|
|
#include <cerrno> |
|
#include <iostream> |
|
#include <string> |
|
|
|
namespace armnn |
|
{ |
|
|
|
namespace gatordmock |
|
{ |
|
|
|
void GatordMockService::SendConnectionAck() |
|
{ |
|
if (m_EchoPackets) |
|
{ |
|
std::cout << "Sending connection acknowledgement." << std::endl; |
|
} |
|
// The connection ack packet is an empty data packet with packetId == 1. |
|
m_BasePipeServer.get()->SendPacket(0, 1, nullptr, 0); |
|
} |
|
|
|
void GatordMockService::SendRequestCounterDir() |
|
{ |
|
if (m_EchoPackets) |
|
{ |
|
std::cout << "Sending connection acknowledgement." << std::endl; |
|
} |
|
// The request counter directory packet is an empty data packet with packetId == 3. |
|
m_BasePipeServer.get()->SendPacket(0, 3, nullptr, 0); |
|
} |
|
|
|
void GatordMockService::SendActivateTimelinePacket() |
|
{ |
|
if (m_EchoPackets) |
|
{ |
|
std::cout << "Sending activate timeline packet." << std::endl; |
|
} |
|
// The activate timeline packet is an empty data packet with packetId == 6. |
|
m_BasePipeServer.get()->SendPacket(0, 6, nullptr, 0); |
|
} |
|
|
|
void GatordMockService::SendDeactivateTimelinePacket() |
|
{ |
|
if (m_EchoPackets) |
|
{ |
|
std::cout << "Sending deactivate timeline packet." << std::endl; |
|
} |
|
// The deactivate timeline packet is an empty data packet with packetId == 7. |
|
m_BasePipeServer.get()->SendPacket(0, 7, nullptr, 0); |
|
} |
|
|
|
bool GatordMockService::LaunchReceivingThread() |
|
{ |
|
if (m_EchoPackets) |
|
{ |
|
std::cout << "Launching receiving thread." << std::endl; |
|
} |
|
// At this point we want to make the socket non blocking. |
|
if (!m_BasePipeServer.get()->SetNonBlocking()) |
|
{ |
|
m_BasePipeServer.get()->Close(); |
|
std::cerr << "Failed to set socket as non blocking: " << strerror(errno) << std::endl; |
|
return false; |
|
} |
|
m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this); |
|
return true; |
|
} |
|
|
|
void GatordMockService::WaitForReceivingThread() |
|
{ |
|
// The receiving thread may already have died. |
|
if (m_CloseReceivingThread != true) |
|
{ |
|
m_CloseReceivingThread.store(true); |
|
} |
|
// Check that the receiving thread is running |
|
if (m_ListeningThread.joinable()) |
|
{ |
|
// Wait for the receiving thread to complete operations |
|
m_ListeningThread.join(); |
|
} |
|
|
|
if(m_EchoPackets) |
|
{ |
|
m_TimelineDecoder.print(); |
|
} |
|
} |
|
|
|
bool GatordMockService::WaitForStreamMetaData() |
|
{ |
|
return m_BasePipeServer->WaitForStreamMetaData(); |
|
} |
|
|
|
void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters) |
|
{ |
|
// The packet body consists of a UINT32 representing the period following by zero or more |
|
// UINT16's representing counter UID's. If the list is empty it implies all counters are to |
|
// be disabled. |
|
|
|
if (m_EchoPackets) |
|
{ |
|
std::cout << "SendPeriodicCounterSelectionList: Period=" << std::dec << period << "uSec" << std::endl; |
|
std::cout << "List length=" << counters.size() << std::endl; |
|
} |
|
// Start by calculating the length of the packet body in bytes. This will be at least 4. |
|
uint32_t dataLength = static_cast<uint32_t>(4 + (counters.size() * 2)); |
|
|
|
std::unique_ptr<unsigned char[]> uniqueData = std::make_unique<unsigned char[]>(dataLength); |
|
unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get()); |
|
|
|
uint32_t offset = 0; |
|
arm::pipe::WriteUint32(data, offset, period); |
|
offset += 4; |
|
for (std::vector<uint16_t>::iterator it = counters.begin(); it != counters.end(); ++it) |
|
{ |
|
arm::pipe::WriteUint16(data, offset, *it); |
|
offset += 2; |
|
} |
|
|
|
// Send the packet. |
|
m_BasePipeServer.get()->SendPacket(0, 4, data, dataLength); |
|
// There will be an echo response packet sitting in the receive thread. PeriodicCounterSelectionResponseHandler |
|
// should deal with it. |
|
} |
|
|
|
void GatordMockService::WaitCommand(uint32_t timeout) |
|
{ |
|
// Wait for a maximum of timeout microseconds or if the receive thread has closed. |
|
// There is a certain level of rounding involved in this timing. |
|
uint32_t iterations = timeout / 1000; |
|
std::cout << std::dec << "Wait command with timeout of " << timeout << " iterations = " << iterations << std::endl; |
|
uint32_t count = 0; |
|
while ((this->ReceiveThreadRunning() && (count < iterations))) |
|
{ |
|
std::this_thread::sleep_for(std::chrono::microseconds(1000)); |
|
++count; |
|
} |
|
if (m_EchoPackets) |
|
{ |
|
std::cout << std::dec << "Wait command with timeout of " << timeout << " microseconds completed. " << std::endl; |
|
} |
|
} |
|
|
|
void GatordMockService::ReceiveLoop() |
|
{ |
|
m_CloseReceivingThread.store(false); |
|
while (!m_CloseReceivingThread.load()) |
|
{ |
|
try |
|
{ |
|
arm::pipe::Packet packet = m_BasePipeServer.get()->WaitForPacket(500); |
|
|
|
arm::pipe::PacketVersionResolver packetVersionResolver; |
|
|
|
arm::pipe::Version version = |
|
packetVersionResolver.ResolvePacketVersion(packet.GetPacketFamily(), packet.GetPacketId()); |
|
|
|
arm::pipe::CommandHandlerFunctor* commandHandlerFunctor = m_HandlerRegistry.GetFunctor( |
|
packet.GetPacketFamily(), |
|
packet.GetPacketId(), |
|
version.GetEncodedValue()); |
|
|
|
|
|
|
|
ARM_PIPE_ASSERT(commandHandlerFunctor); |
|
commandHandlerFunctor->operator()(packet); |
|
} |
|
catch (const arm::pipe::TimeoutException&) |
|
{ |
|
// In this case we ignore timeouts and and keep trying to receive. |
|
} |
|
catch (const arm::pipe::InvalidArgumentException& e) |
|
{ |
|
// We couldn't find a functor to handle the packet? |
|
std::cerr << "Packet received that could not be processed: " << e.what() << std::endl; |
|
} |
|
catch (const arm::pipe::ProfilingException& e) |
|
{ |
|
// A runtime exception occurred which means we must exit the loop. |
|
std::cerr << "Receive thread closing: " << e.what() << std::endl; |
|
m_CloseReceivingThread.store(true); |
|
} |
|
} |
|
} |
|
|
|
} // namespace gatordmock |
|
|
|
} // namespace armnn
|
|
|