diff options
author | Colm Donelan <Colm.Donelan@arm.com> | 2019-10-11 13:09:49 +0100 |
---|---|---|
committer | Colm Donelan <Colm.Donelan@arm.com> | 2019-10-11 13:12:37 +0100 |
commit | a21620d32a8a0a8d527c061e2a22d51009d75877 (patch) | |
tree | b08ffee4cddb1bb3b1d206c67ea80bc2093d7bf5 /src | |
parent | 67ef2a52c3cdcc37538d77711bbcea2f0e5655e5 (diff) | |
download | armnn-a21620d32a8a0a8d527c061e2a22d51009d75877.tar.gz |
IVGCVSW-3721 Add support for startup sequence (Mock Gatord service).
* Receive and process the stream metadata from the client.
* Send the connection ack packet.
* Wait in a receiving thread and print the packets.
* GatordMockTest and Impl for PeriodicCounterCapture CommandHandler
* CaptureData class to retain packet data
* MockUtils
* Update SocketProfilingConnection to fix non blocking receipt of packets.
* Restructure directory layout following review comments.
* Extract the mock service into a static library in the cmake files.
Signed-off-by: Colm Donelan <Colm.Donelan@arm.com>
Signed-off-by: Keith Davis <keith.davis@arm.com>
Signed-off-by: Mike Kelly <mike.kelly@arm.com>
Signed-off-by: Finn Williams <Finn.Williams@arm.com>
Signed-off-by: Kevin May <kevin.may@arm.com>
Change-Id: I33c1c9f93976708c9315f71290d42cff53b8c075
Diffstat (limited to 'src')
-rw-r--r-- | src/profiling/SocketProfilingConnection.cpp | 102 | ||||
-rw-r--r-- | src/profiling/SocketProfilingConnection.hpp | 4 |
2 files changed, 62 insertions, 44 deletions
diff --git a/src/profiling/SocketProfilingConnection.cpp b/src/profiling/SocketProfilingConnection.cpp index ad629928f9..6f7101b254 100644 --- a/src/profiling/SocketProfilingConnection.cpp +++ b/src/profiling/SocketProfilingConnection.cpp @@ -5,10 +5,11 @@ #include "SocketProfilingConnection.hpp" +#include <cerrno> #include <fcntl.h> +#include <sys/ioctl.h> #include <sys/socket.h> #include <sys/un.h> -#include <cerrno> #include <string> namespace armnn @@ -23,7 +24,7 @@ SocketProfilingConnection::SocketProfilingConnection() m_Socket[0].fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (m_Socket[0].fd == -1) { - throw RuntimeException(std::string("Socket construction failed: ") + strerror(errno)); + throw armnn::RuntimeException(std::string("Socket construction failed: ") + strerror(errno)); } // Connect to the named unix domain socket. @@ -35,7 +36,7 @@ SocketProfilingConnection::SocketProfilingConnection() if (0 != connect(m_Socket[0].fd, reinterpret_cast<const sockaddr*>(&server), sizeof(sockaddr_un))) { close(m_Socket[0].fd); - throw RuntimeException(std::string("Cannot connect to stream socket: ") + strerror(errno)); + throw armnn::RuntimeException(std::string("Cannot connect to stream socket: ") + strerror(errno)); } // Our socket will only be interested in polling reads. @@ -46,7 +47,7 @@ SocketProfilingConnection::SocketProfilingConnection() if (0 != fcntl(m_Socket[0].fd, F_SETFL, currentFlags | O_NONBLOCK)) { close(m_Socket[0].fd); - throw RuntimeException(std::string("Failed to set socket as non blocking: ") + strerror(errno)); + throw armnn::RuntimeException(std::string("Failed to set socket as non blocking: ") + strerror(errno)); } } @@ -59,7 +60,7 @@ void SocketProfilingConnection::Close() { if (close(m_Socket[0].fd) != 0) { - throw RuntimeException(std::string("Cannot close stream socket: ") + strerror(errno)); + throw armnn::RuntimeException(std::string("Cannot close stream socket: ") + strerror(errno)); } memset(m_Socket, 0, sizeof(m_Socket)); @@ -77,54 +78,67 @@ bool SocketProfilingConnection::WritePacket(const unsigned char* buffer, uint32_ Packet SocketProfilingConnection::ReadPacket(uint32_t timeout) { - // Poll for data on the socket or until timeout occurs - int pollResult = poll(m_Socket, 1, static_cast<int>(timeout)); - - switch (pollResult) + // Is there currently at least a headers worth of data waiting to be read? + int bytes_available; + ioctl(m_Socket[0].fd, FIONREAD, &bytes_available); + if (bytes_available >= 8) { - case -1: // Error - throw RuntimeException(std::string("Read failure from socket: ") + strerror(errno)); + // Yes there is. Read it: + return ReceivePacket(); + } + else + { + // Poll for data on the socket or until timeout occurs + int pollResult = poll(m_Socket, 1, static_cast<int>(timeout)); + + switch (pollResult) + { + case -1: // Error + throw armnn::RuntimeException(std::string("Read failure from socket: ") + strerror(errno)); - case 0: // Timeout - throw RuntimeException("Timeout while reading from socket"); + case 0: // Timeout + throw TimeoutException("Timeout while reading from socket"); - default: // Normal poll return but it could still contain an error signal + default: // Normal poll return but it could still contain an error signal - // Check if the socket reported an error - if (m_Socket[0].revents & (POLLNVAL | POLLERR | POLLHUP)) - { - throw Exception(std::string("Socket 0 reported an error: ") + strerror(errno)); - } + // Check if the socket reported an error + if (m_Socket[0].revents & (POLLNVAL | POLLERR | POLLHUP)) + { + throw armnn::RuntimeException(std::string("Socket reported an error: ") + strerror(errno)); + } - // Check if there is data to read - if (!(m_Socket[0].revents & (POLLIN))) - { - // No data to read from the socket. Silently ignore and continue - return Packet(); - } + // Check if there is data to read + if (!(m_Socket[0].revents & (POLLIN))) + { + // This is a very odd case. The file descriptor was woken up but no data was written. + throw armnn::RuntimeException("Poll resulted in : no data to read"); + } - // There is data to read, read the header first - char header[8] = {}; - if (8 != recv(m_Socket[0].fd, &header, sizeof(header), 0)) - { - // What do we do here if there's not a valid 8 byte header to read? - throw RuntimeException("The received packet did not contains a valid MIPE header"); + return ReceivePacket(); } + } +} - // stream_metadata_identifier is the first 4 bytes - uint32_t metadataIdentifier = 0; - std::memcpy(&metadataIdentifier, header, sizeof(metadataIdentifier)); +Packet SocketProfilingConnection::ReceivePacket() +{ + char header[8] = {}; + if (8 != recv(m_Socket[0].fd, &header, sizeof(header), 0)) + { + // What do we do here if there's not a valid 8 byte header to read? + throw armnn::RuntimeException("The received packet did not contains a valid MIPE header"); + } + // stream_metadata_identifier is the first 4 bytes + uint32_t metadataIdentifier = 0; + std::memcpy(&metadataIdentifier, header, sizeof(metadataIdentifier)); - // data_length is the next 4 bytes - uint32_t dataLength = 0; - std::memcpy(&dataLength, header + 4u, sizeof(dataLength)); + // data_length is the next 4 bytes + uint32_t dataLength = 0; + std::memcpy(&dataLength, header + 4u, sizeof(dataLength)); std::unique_ptr<unsigned char[]> packetData; - if (dataLength > 0) - { + if (dataLength > 0) + { packetData = std::make_unique<unsigned char[]>(dataLength); - } - ssize_t receivedLength = recv(m_Socket[0].fd, packetData.get(), dataLength, 0); if (receivedLength < 0) { @@ -133,11 +147,11 @@ Packet SocketProfilingConnection::ReadPacket(uint32_t timeout) if (dataLength != static_cast<uint32_t>(receivedLength)) { // What do we do here if we can't read in a full packet? - throw RuntimeException("Invalid MIPE packet"); + throw armnn::RuntimeException("Invalid MIPE packet"); } - - return Packet(metadataIdentifier, dataLength, packetData); } + + return Packet(metadataIdentifier, dataLength, packetData); } } // namespace profiling diff --git a/src/profiling/SocketProfilingConnection.hpp b/src/profiling/SocketProfilingConnection.hpp index 7c77a8bfc9..5fb02bb19e 100644 --- a/src/profiling/SocketProfilingConnection.hpp +++ b/src/profiling/SocketProfilingConnection.hpp @@ -25,6 +25,10 @@ public: Packet ReadPacket(uint32_t timeout) final; private: + + // Read a full packet from the socket. + Packet ReceivePacket(); + // To indicate we want to use an abstract UDS ensure the first character of the address is 0. const char* m_GatorNamespace = "\0gatord_namespace"; struct pollfd m_Socket[1]{}; |