This commit is contained in:
HailoRT-Automation
2024-09-29 11:29:10 +03:00
committed by GitHub
parent 01e4c7f5a7
commit 3d67325209
357 changed files with 7522 additions and 3723 deletions

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
find_program(CCACHE_PROGRAM ccache)
find_program(CLACHE_PROGRAM clcache)

View File

@@ -125,6 +125,8 @@ typedef enum __attribute__((packed)) {
CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_CACHE_INPUT,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_ACTIVATE_CACHE_OUTPUT,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_WAIT_FOR_CACHE_UPDATED,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_SLEEP,
CONTEXT_SWITCH_DEFS__ACTION_TYPE_HALT,
/* Must be last */
CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT
@@ -447,6 +449,10 @@ typedef struct {
uint8_t packed_vdma_channel_id;
} CONTEXT_SWITCH_DEFS__change_boundary_input_batch_t;
typedef struct {
uint32_t sleep_time;
} CONTEXT_SWITCH_DEFS__sleep_action_data_t;
#pragma pack(pop)
#ifdef __cplusplus

View File

@@ -1033,6 +1033,8 @@ typedef struct {
uint8_t is_action_list_end;
uint32_t batch_counter_length;
uint32_t batch_counter;
uint32_t idle_time_length;
uint32_t idle_time;
uint32_t action_list_length;
uint8_t action_list[0];
} CONTROL_PROTOCOL__download_context_action_list_response_t;

View File

@@ -769,6 +769,7 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_EXTERNAL_ACTION_LIST_ADDRESS)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_CACHE_SIZE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_READ_OFFSET_SIZE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_STATUS_INVALID_SLEEP_TIME)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__D2H_EVENT_MANAGER)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_MESSAGE_HIGH_PRIORITY_QUEUE_CREATE_FAILED)\

2
hailort/.gitignore vendored
View File

@@ -1,3 +1,5 @@
build/
build-*x86_64/
build-*aarch64/
dist/
/external/

View File

@@ -1,14 +1,12 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
option(HAILO_BUILD_PYBIND "Build Python binding" OFF)
option(HAILO_BUILD_EMULATOR "Build hailort for emulator" OFF)
option(HAILO_BUILD_UT "Build Unit Tests" OFF)
option(HAILO_BUILD_HW_DEBUG_TOOL "Build hw debug tool" OFF)
option(HAILO_INTERNAL_BUILD "Build internal hailort componments" OFF)
option(HAILO_BUILD_GSTREAMER "Compile gstreamer plugins" OFF)
option(HAILO_BUILD_EXAMPLES "Build examples" OFF)
option(HAILO_OFFLINE_COMPILATION "Don't download external dependencies" OFF)
option(HAILO_BUILD_SERVICE "Build hailort service" OFF)
option(HAILO_BUILD_PROFILER "Build hailort profiler" ON)
option(HAILO_COMPILE_WARNING_AS_ERROR "Add compilation flag for treating compilation warnings as errors" OFF)
option(HAILO_SUPPORT_PACKAGING "Create HailoRT package (internal)" OFF)
option(HAILO_BUILD_DOC "Build doc" OFF)
@@ -31,7 +29,7 @@ endif()
# Set firmware version
add_definitions( -DFIRMWARE_VERSION_MAJOR=4 )
add_definitions( -DFIRMWARE_VERSION_MINOR=18 )
add_definitions( -DFIRMWARE_VERSION_MINOR=19 )
add_definitions( -DFIRMWARE_VERSION_REVISION=0 )
if(HAILO_BUILD_SERVICE)
add_definitions( -DHAILO_SUPPORT_MULTI_PROCESS )
@@ -75,8 +73,10 @@ add_subdirectory(hrpc)
add_subdirectory(hrpc_protocol)
add_subdirectory(libhailort)
add_subdirectory(hailortcli)
if(HAILO_BUILD_HW_DEBUG_TOOL)
if(HAILO_INTERNAL_BUILD)
add_subdirectory(tools/hw_debug)
add_subdirectory(tools/pcie_tunnel)
add_subdirectory(tools/loopback_server)
endif()
if(HAILO_BUILD_SERVICE)

View File

@@ -4,7 +4,7 @@
| Catch2 | Catch2 Authors | BSL-1.0 | 2.13.7 | Cloned entire package | https://github.com/catchorg/Catch2 |
| protobuf | Google Inc. | BSD | 21.12 | Cloned entire package | https://github.com/protocolbuffers/protobuf |
| pybind11 | Wenzel Jakob | BSD | 2.10.1 | Cloned entire package | https://github.com/pybind/pybind11 |
| spdlog | Gabi Melman | MIT | 1.6.1 | Cloned entire package | https://github.com/gabime/spdlog |
| spdlog | Gabi Melman | MIT | 1.14.1 | Cloned entire package | https://github.com/gabime/spdlog |
| folly | Facebook, Inc. and its affiliates | Apache License 2.0 | v2020.08.17.00 | Copied only the file `folly/TokenBucket.h` | https://github.com/facebook/folly |
| nlohmann_json_cmake_fetchcontent | ArthurSonzogni | MIT License | v3.9.1 | Cloned entire package | https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent |
| readerwriterqueue | Cameron Desrochers | Simplified BSD | 1.0.3 | Cloned entire package | https://github.com/cameron314/readerwriterqueue |

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
FUNCTION(disable_exceptions target)
if(WIN32)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
function(execute_process_in_clean_env)
cmake_parse_arguments(execute_process_in_clean_env "" "RESULT_VARIABLE" "" ${ARGN})

View File

@@ -5,7 +5,7 @@ include(FetchContent)
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog
GIT_TAG 22a169bc319ac06948e7ee0be6b9b0ac81386604
GIT_TAG 27cb4c76708608465c413f6d0e6b8d99a4d84302 # version 1.14.1
GIT_SHALLOW TRUE
SOURCE_DIR ${HAILO_EXTERNAL_DIR}/spdlog-src
SUBBUILD_DIR ${HAILO_EXTERNAL_DIR}/spdlog-subbuild

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
if(WIN32)
set(HAILORT_COMMON_OS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/os/windows")
@@ -15,12 +15,16 @@ set(SRC_FILES
${HAILORT_COMMON_OS_DIR}/socket.cpp
${HAILORT_COMMON_OS_DIR}/process.cpp
${HAILORT_COMMON_OS_DIR}/os_utils.cpp
${HAILORT_COMMON_OS_DIR}/file_descriptor.cpp
${HAILORT_COMMON_OS_DIR}/mmap_buffer.cpp
${HAILORT_COMMON_OS_DIR}/shared_memory_buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/barrier.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/string_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/event_internal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fork_support.cpp
${CMAKE_CURRENT_SOURCE_DIR}/buffer_pool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/device_measurements.cpp
)
@@ -29,6 +33,8 @@ if(WIN32)
# Windows only modules:
set(SRC_FILES ${SRC_FILES}
${HAILORT_COMMON_OS_DIR}/string_conversion.cpp
${HAILORT_COMMON_OS_DIR}/virtual_alloc_guard.cpp
${HAILORT_COMMON_OS_DIR}/named_mutex_guard.cpp
)
elseif(UNIX)
# Unix only modules
@@ -37,4 +43,5 @@ elseif(UNIX)
)
endif()
set(HAILORT_COMMON_CPP_SOURCES ${SRC_FILES} PARENT_SCOPE)

View File

@@ -0,0 +1,58 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file buffer_pool.cpp
* @brief Buffer pool implementation
**/
#include "buffer_pool.hpp"
#include "hailo/hailort.h"
namespace hailort
{
BasicBufferPool::BasicBufferPool(size_t buffer_size, std::vector<BufferPtr> &&buffers,
SpscQueue<BufferPtr> &&free_buffers_queue, size_t buffers_count) :
m_buffer_size(buffer_size),
m_buffers_count(buffers_count),
m_buffers(std::move(buffers)),
m_free_buffers_queue(std::move(free_buffers_queue))
{}
Expected<BufferPtr> BasicBufferPool::acquire_buffer()
{
TRY_WITH_ACCEPTABLE_STATUS(HAILO_SHUTDOWN_EVENT_SIGNALED, auto buffer,
m_free_buffers_queue.dequeue(DEFAULT_TRANSFER_TIMEOUT));
return buffer;
}
size_t BasicBufferPool::current_size()
{
return m_free_buffers_queue.size_approx();
}
hailo_status BasicBufferPool::return_to_pool(BufferPtr buffer)
{
CHECK(buffer->size() == m_buffer_size, HAILO_INTERNAL_FAILURE,
"Buffer size is not the same as expected for pool! ({} != {})", buffer->size(), m_buffer_size);
std::unique_lock<std::mutex> lock(m_mutex);
auto status = m_free_buffers_queue.enqueue(buffer);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
size_t BasicBufferPool::buffers_count()
{
return m_buffers_count;
}
size_t BasicBufferPool::buffer_size()
{
return m_buffer_size;
}
} /* namespace hailort */

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file buffer_pool.hpp
* @brief Buffer pool
**/
#ifndef _HAILO_BUFFER_POOL_HPP_
#define _HAILO_BUFFER_POOL_HPP_
#include "hailo/hailort.h"
#include "hailo/hailort_common.hpp"
#include "hailo/buffer.hpp"
#include "hailo/vdevice.hpp"
#include "hailo/dma_mapped_buffer.hpp"
#include "common/thread_safe_queue.hpp"
#include <mutex>
namespace hailort
{
// TODO: HRT-12690 - Make other buffer pools to use this as base class
class BasicBufferPool
{
public:
BasicBufferPool(size_t buffer_size, std::vector<BufferPtr> &&buffers,
SpscQueue<BufferPtr> &&m_free_buffers_queue, size_t buffers_count);
BasicBufferPool(BasicBufferPool &&) = delete;
BasicBufferPool(const BasicBufferPool &) = delete;
BasicBufferPool &operator=(BasicBufferPool &&) = delete;
BasicBufferPool &operator=(const BasicBufferPool &) = delete;
virtual ~BasicBufferPool() = default;
Expected<BufferPtr> acquire_buffer();
size_t current_size();
hailo_status return_to_pool(BufferPtr buffer);
size_t buffers_count();
size_t buffer_size();
private:
size_t m_buffer_size;
size_t m_buffers_count;
std::vector<BufferPtr> m_buffers;
SpscQueue<BufferPtr> m_free_buffers_queue;
std::mutex m_mutex;
};
using BasicBufferPoolPtr = std::shared_ptr<BasicBufferPool>;
} /* namespace hailort */
#endif /* _HAILO_BUFFER_POOL_HPP_ */

View File

@@ -20,6 +20,12 @@
#include <atomic>
enum class ShouldMeasurePower {
AUTO_DETECT, // auto detect if should measure power, based on device.get_capabilities()
NO,
YES
};
class BaseMeasurement
{
public:

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2020-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file env_vars.hpp
* @brief: defines a set of environment variables used in the HailoRT
* **/
#ifndef HAILO_ENV_VARS_HPP_
#define HAILO_ENV_VARS_HPP_
namespace hailort
{
#define HAILORT_LOGGER_PATH_ENV_VAR ("HAILORT_LOGGER_PATH")
#define HAILORT_CONSOLE_LOGGER_LEVEL_ENV_VAR ("HAILORT_CONSOLE_LOGGER_LEVEL")
#define SCHEDULER_MON_ENV_VAR ("HAILO_MONITOR")
#define SCHEDULER_MON_ENV_VAR_VALUE ("1")
#define TRACE_ENV_VAR ("HAILO_TRACE")
#define TRACE_ENV_VAR_VALUE ("scheduler")
#define TRACE_ENV_VAR_TIME_IN_SECONDS_BOUNDED_DUMP ("HAILO_TRACE_TIME_IN_SECONDS_BOUNDED_DUMP")
#define TRACE_ENV_VAR_SIZE_IN_KB_BOUNDED_DUMP ("HAILO_TRACE_SIZE_IN_KB_BOUNDED_DUMP")
#define PROFILER_FILE_ENV_VAR ("HAILO_TRACE_PATH")
} /* namespace hailort */
#endif /* HAILO_ENV_VARS_HPP_ */

View File

@@ -72,7 +72,7 @@ hailo_status FileReader::read(uint8_t *buffer, size_t n)
return m_fstream->good() ? HAILO_SUCCESS : HAILO_FILE_OPERATION_FAILURE;
}
hailo_status FileReader::read_from_offset(size_t offset, MemoryView &dst, size_t size)
hailo_status FileReader::read_from_offset(uint64_t offset, MemoryView dst, size_t size)
{
assert(nullptr != m_fstream);
@@ -93,10 +93,12 @@ hailo_status FileReader::open()
{
if (nullptr == m_fstream) { // The first call to open creates the ifstream object
m_fstream = std::make_shared<std::ifstream>(m_file_path, std::ios::in | std::ios::binary);
return m_fstream->good() ? HAILO_SUCCESS : HAILO_OPEN_FILE_FAILURE;
} else {
m_fstream->open(m_file_path, std::ios::in | std::ios::binary);
}
m_fstream->open(m_file_path, std::ios::in | std::ios::binary);
return m_fstream->good() ? HAILO_SUCCESS : HAILO_OPEN_FILE_FAILURE;
CHECK(m_fstream->good(), HAILO_OPEN_FILE_FAILURE, "Failed opening file, path: {}", m_file_path);
return HAILO_SUCCESS;
}
bool FileReader::is_open() const
@@ -173,7 +175,7 @@ hailo_status BufferReader::read(uint8_t *buffer, size_t n)
return HAILO_SUCCESS;
}
hailo_status BufferReader::read_from_offset(size_t offset, MemoryView &dst, size_t size)
hailo_status BufferReader::read_from_offset(uint64_t offset, MemoryView dst, size_t size)
{
memcpy(dst.data(), m_memview.data() + offset, size);
return HAILO_SUCCESS;

View File

@@ -35,7 +35,7 @@ class SeekableBytesReader
public:
virtual ~SeekableBytesReader() = default;
virtual hailo_status read(uint8_t *buffer, size_t n) = 0;
virtual hailo_status read_from_offset(size_t offset, MemoryView &dst, size_t n) = 0;
virtual hailo_status read_from_offset(uint64_t offset, MemoryView dst, size_t n) = 0;
virtual hailo_status open() = 0;
virtual bool is_open() const = 0;
virtual hailo_status seek(size_t position) = 0;
@@ -54,7 +54,7 @@ public:
FileReader(const std::string &file_path);
virtual hailo_status read(uint8_t *buffer, size_t n);
virtual hailo_status read_from_offset(size_t offset, MemoryView &dst, size_t n);
virtual hailo_status read_from_offset(uint64_t offset, MemoryView dst, size_t n);
virtual hailo_status open();
virtual bool is_open() const;
virtual hailo_status seek(size_t position);
@@ -78,7 +78,7 @@ public:
BufferReader(const MemoryView &memview);
virtual hailo_status read(uint8_t *buffer, size_t n);
virtual hailo_status read_from_offset(size_t offset, MemoryView &dst, size_t n);
virtual hailo_status read_from_offset(uint64_t offset, MemoryView dst, size_t n);
virtual hailo_status open();
virtual bool is_open() const;
virtual hailo_status seek(size_t position);

View File

@@ -0,0 +1,106 @@
/**
* Copyright (c) 2020-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file internal_env_Vars.hpp
* @brief: defines a set of internal environment variables used for development
* **/
#ifndef HAILO_INTERNAL_ENV_VARS_HPP_
#define HAILO_INTERNAL_ENV_VARS_HPP_
namespace hailort
{
/* Service, hrpc-server, comunication */
/* Changes the default address for grpc communication. used for the service-over-ip feature */
#define HAILORT_SERVICE_ADDRESS_ENV_VAR ("HAILORT_SERVICE_ADDRESS")
/* Indicates to the HailoRT gRPC Service whether to use shared memory for the tesnors data.
Note: Cannot be used for service-over-ip */
#define HAILO_SERVICE_SHARED_MEMORY_ENV_VAR ("HAILO_SERVICE_SHARED_MEMORY_OFF")
#define HAILO_SERVICE_SHARED_MEMORY_OFF "1"
/* Defines a costum pcie port for raw-connection */
#define HAILO_CONNECTION_PCIE_PORT_ENV_VAR ("HAILO_CONNECTION_PCIE_PORT")
/* Forces the client to use socket-based communication on a specific address. if not set, socket communicaiton wont be used. */
#define HAILO_SOCKET_COM_ADDR_CLIENT_ENV_VAR ("HAILO_SOCKET_COM_ADDR_CLIENT")
/* Forces the hrpc-server to use socket-based communication on a specific address. if not set, socket communicaiton wont be used. */
#define HAILO_SOCKET_COM_ADDR_SERVER_ENV_VAR ("HAILO_SOCKET_COM_ADDR_SERVER")
/* HAILO_SOCKET_COM_ADDR_CLIENT_ENV_VAR and HAILO_SOCKET_COM_ADDR_SERVER_ENV_VAR can be set to either ip:port ("X.X.X.X:P"),
or to HAILO_SOCKET_COM_ADDR_UNIX_SOCKET which forces working with unix-socket*/
#define HAILO_SOCKET_COM_ADDR_UNIX_SOCKET ("localhost")
/* General */
/* Defines whether the offset of the kv cache will be updated automatically or not.
can be set to either HAILORT_AUTO_UPDATE_CACHE_OFFSET_ENV_VAR_DEFAULT or
HAILORT_AUTO_UPDATE_CACHE_OFFSET_ENV_VAR_DISABLED, or to a numeric value defining the offset update value in bytes`*/
#define HAILORT_AUTO_UPDATE_CACHE_OFFSET_ENV_VAR ("HAILORT_AUTO_UPDATE_CACHE_OFFSET")
#define HAILORT_AUTO_UPDATE_CACHE_OFFSET_ENV_VAR_DEFAULT ("default")
#define HAILORT_AUTO_UPDATE_CACHE_OFFSET_ENV_VAR_DISABLED ("disabled")
/* Used for the internal CLI mode `measure-nnc-performance` */
#define HAILO_CONFIGURE_FOR_HW_INFER_ENV_VAR ("HAILO_CONFIGURE_FOR_HW_INFER")
/* Disable context switch intermediate buffer reuse (naive plan) */
#define HAILO_FORCE_NAIVE_PER_BUFFER_TYPE_ALOCATION_ENV_VAR ("HAILO_FORCE_NAIVE_PER_BUFFER_TYPE_ALOCATION")
/* forces the minimum FD used events to be above `HIGH_FD_OFFSET`.
useful for systems with limitations on the FD count and values */
#define HAILO_USE_HIGH_FD_ENV_VAR ("HAILO_USE_HIGH_FD")
/* Force hailo15m partial cluster layout bitmap (which clusters are activated) */
#define FORCE_LAYOUT_INTERNAL_ENV_VAR ("FORCE_LAYOUT_INTERNAL")
/* Logger */
/* Forces flush of the logger to file on every trace, instead of the default (warnings and above) */
#define HAILORT_LOGGER_FLUSH_EVERY_PRINT_ENV_VAR ("HAILORT_LOGGER_FLUSH_EVERY_PRINT")
/* Force QNX Driver logs to be flushed to specific file - or if left undefined - to stderr */
#define HAILO_QNX_DRIVER_LOG_STDERR_ENV_VAR ("HAILO_QNX_DRIVER_LOG_STDERR")
/* Inference */
/* Disables the hrt-multiplexer */
#define DISABLE_MULTIPLEXER_ENV_VAR ("HAILO_DISABLE_MULTIPLEXER_INTERNAL")
/* Disable scheduler Idle optimization */
#define HAILO_DISABLE_IDLE_OPT_ENV_VAR ("HAILO_DISABLE_IDLE_OPT")
/* Model configuration */
/* If not set, hailort will try to use default desc-size, and only then fallback to larger desc-sizes */
#define HAILO_LEGACY_BOUNDARY_CHANNEL_PAGE_SIZE_ENV_VAR ("HAILO_LEGACY_BOUNDARY_CHANNEL_PAGE_SIZE")
/* If set - Action list will be sent to Firmware SRAM over DDR unrelated to the size of the action list
(Otherwise - DDR will only be used if infinite action list is needed) */
#define DDR_ACTION_LIST_ENV_VAR ("HAILO_DDR_ACTION_LIST")
#define DDR_ACTION_LIST_ENV_VAR_VALUE ("1")
/* Forces using descriptor-lists instead of CCB for config-channels on h1x devices */
#define HAILO_FORCE_CONF_CHANNEL_OVER_DESC_ENV_VAR ("HAILO_FORCE_CONF_CHANNEL_OVER_DESC")
/* Forces using descriptor-lists instead of CCB for inter-context-channels on h1x devices */
#define HAILO_FORCE_INFER_CONTEXT_CHANNEL_OVER_DESC_ENV_VAR ("HAILO_FORCE_INFER_CONTEXT_CHANNEL_OVER_DESC")
/* Forces using descriptor-lists instead of CCB for ddr-channels on h1x devices */
#define HAILO_FORCE_DDR_CHANNEL_OVER_CCB_ENV_VAR ("HAILO_FORCE_DDR_CHANNEL_OVER_CCB")
/* Sets the default power-mode of the ConfiguredNetworkGroups to `HAILO_POWER_MODE_ULTRA_PERFORMANCE` */
#define FORCE_POWER_MODE_ULTRA_PERFORMANCE_ENV_VAR ("FORCE_POWER_MODE_ULTRA_PERFORMANCE")
} /* namespace hailort */
#endif /* HAILO_INTERNAL_ENV_VARS_HPP_ */

View File

@@ -43,6 +43,8 @@ inline std::ostream& operator<<(std::ostream& os, const hailo_status& status)
return os << status_str << "(" << static_cast<int>(status) << ")";
}
template <> struct fmt::formatter<hailo_status> : fmt::ostream_formatter {};
namespace hailort
{

View File

@@ -16,7 +16,7 @@
#include "hailo/expected.hpp"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include "os/file_descriptor.hpp"
#include "common/file_descriptor.hpp"
namespace hailort
{
@@ -85,14 +85,14 @@ public:
{
auto mmap = MmapBufferImpl::create_shared_memory(length);
CHECK_EXPECTED(mmap);
return MmapBuffer<T>(std::move(mmap.release()));
return MmapBuffer<T>(mmap.release());
}
static Expected<MmapBuffer<T>> create_file_map(size_t length, FileDescriptor &file, uintptr_t offset)
{
auto mmap = MmapBufferImpl::create_file_map(length, file, offset);
CHECK_EXPECTED(mmap);
return MmapBuffer<T>(std::move(mmap.release()));
return MmapBuffer<T>(mmap.release());
}
#if defined(__QNX__)

View File

@@ -9,7 +9,7 @@
#include "common/logger_macros.hpp"
#include "os/file_descriptor.hpp"
#include "common/file_descriptor.hpp"
#include <errno.h>
namespace hailort

View File

@@ -7,9 +7,8 @@
* @brief Wrapper around unix memory mapping (mmap)
**/
#include "os/mmap_buffer.hpp"
#include "common/mmap_buffer.hpp"
#include "vdma/driver/hailort_driver.hpp"
#include "hailo_ioctl_common.h"
#include <sys/ioctl.h>
#include <sys/mman.h>

View File

@@ -0,0 +1,112 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file shared_memory_buffer.cpp
* @brief Posix Shared memory implementation
**/
#include "common/shared_memory_buffer.hpp"
#include "common/utils.hpp"
#include "hailo/hailort.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
namespace hailort
{
#ifndef __ANDROID__
Expected<SharedMemoryBufferPtr> SharedMemoryBuffer::create(size_t size, const std::string &shm_name)
{
auto shm_segment_fd = shm_open(shm_name.c_str(), (O_CREAT | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO)); // mode 0777
CHECK_AS_EXPECTED((shm_segment_fd != -1), HAILO_INTERNAL_FAILURE, "Failed to create shared memory object, errno = {}", errno);
auto shm_fd = FileDescriptor(shm_segment_fd);
auto res = ftruncate(shm_fd, size);
CHECK_AS_EXPECTED(res != -1, HAILO_INTERNAL_FAILURE, "Failed to set size of shared memory object, errno = {}", errno);
TRY(auto mmapped_buffer, MmapBuffer<void>::create_file_map(size, shm_fd, 0));
auto result = make_shared_nothrow<SharedMemoryBuffer>(shm_name, std::move(shm_fd), std::move(mmapped_buffer), true);
CHECK_NOT_NULL_AS_EXPECTED(result, HAILO_OUT_OF_HOST_MEMORY);
return result;
}
Expected<SharedMemoryBufferPtr> SharedMemoryBuffer::open(size_t size, const std::string &shm_name)
{
auto shm_segment_fd = shm_open(shm_name.c_str(), O_RDWR, (S_IRWXU | S_IRWXG | S_IRWXO)); // mode 0777
CHECK_AS_EXPECTED((shm_segment_fd != -1), HAILO_INTERNAL_FAILURE, "Failed to open shared memory object, errno = {}", errno);
auto shm_fd = FileDescriptor(shm_segment_fd);
TRY(auto mmapped_buffer, MmapBuffer<void>::create_file_map(size, shm_fd, 0));
auto result = make_shared_nothrow<SharedMemoryBuffer>(shm_name, std::move(shm_fd), std::move(mmapped_buffer), false);
CHECK_NOT_NULL_AS_EXPECTED(result, HAILO_OUT_OF_HOST_MEMORY);
return result;
}
SharedMemoryBuffer::~SharedMemoryBuffer()
{
if (m_memory_owner) {
shm_unlink(m_shm_name.c_str());
}
}
size_t SharedMemoryBuffer::size() const
{
return m_shm_mmap_buffer.size();
}
void *SharedMemoryBuffer::user_address()
{
return m_shm_mmap_buffer.address();
}
std::string SharedMemoryBuffer::shm_name()
{
return m_shm_name;
}
#else
// TODO: HRT-14770 support android shared memory
Expected<SharedMemoryBufferPtr> SharedMemoryBuffer::create(size_t, const std::string &)
{
LOGGER__ERROR("SharedMemoryBuffer::create is not implemented for Android");
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
Expected<SharedMemoryBufferPtr> SharedMemoryBuffer::open(size_t, const std::string &)
{
LOGGER__ERROR("SharedMemoryBuffer::open is not implemented for Android");
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
size_t SharedMemoryBuffer::size() const
{
LOGGER__ERROR("SharedMemoryBuffer::size is not implemented for Android");
return 0;
}
void *SharedMemoryBuffer::user_address()
{
LOGGER__ERROR("SharedMemoryBuffer::user_address is not implemented for Android");
return nullptr;
}
std::string SharedMemoryBuffer::shm_name()
{
LOGGER__ERROR("SharedMemoryBuffer::shm_name is not implemented for Android");
return "";
}
#endif
} /* namespace hailort */

View File

@@ -35,13 +35,17 @@ hailo_status Socket::SocketModuleWrapper::free_module()
Expected<Socket> Socket::create(int af, int type, int protocol)
{
TRY(auto module_wrapper, SocketModuleWrapper::create());
auto module_wrapper_ptr = make_shared_nothrow<SocketModuleWrapper>(std::move(module_wrapper));
CHECK_NOT_NULL(module_wrapper_ptr, HAILO_OUT_OF_HOST_MEMORY);
TRY(const auto socket_fd, create_socket_fd(af, type, protocol));
auto obj = Socket(std::move(module_wrapper), socket_fd);
auto obj = Socket(module_wrapper_ptr, socket_fd);
return obj;
}
Socket::Socket(SocketModuleWrapper &&module_wrapper, const socket_t socket_fd) :
Socket::Socket(std::shared_ptr<SocketModuleWrapper> module_wrapper, const socket_t socket_fd) :
m_module_wrapper(std::move(module_wrapper)), m_socket_fd(socket_fd)
{
}
@@ -107,6 +111,56 @@ hailo_status Socket::get_sock_name(sockaddr *addr, socklen_t *len)
return HAILO_SUCCESS;
}
hailo_status Socket::listen(int backlog)
{
auto res = ::listen(m_socket_fd, backlog);
CHECK(0 == res, HAILO_ETH_FAILURE, "Failed to listen on socket. errno={}", errno);
return HAILO_SUCCESS;
}
Expected<Socket> Socket::accept()
{
auto client_socket = ::accept(m_socket_fd, nullptr, nullptr);
CHECK(client_socket != INVALID_SOCKET, make_unexpected(HAILO_ETH_FAILURE), "Failed to accept connection {}", errno);
return Socket(m_module_wrapper, client_socket);
}
hailo_status Socket::connect(const sockaddr *addr, socklen_t len)
{
int ret = ::connect(m_socket_fd, addr, len);
CHECK(0 == ret, HAILO_ETH_FAILURE, "Failed to connect to socket {}", errno);
return HAILO_SUCCESS;
}
Expected<size_t> Socket::recv(uint8_t *buffer, size_t size, int flags)
{
auto read_bytes = ::recv(m_socket_fd, buffer, size, flags);
CHECK(read_bytes >= 0, make_unexpected(HAILO_ETH_FAILURE), "Failed to read from socket {}", errno);
return Expected<size_t>(read_bytes);
}
Expected<size_t> Socket::send(const uint8_t *buffer, size_t size, int flags)
{
auto bytes_written = ::send(m_socket_fd, buffer, size, flags);
CHECK(bytes_written >= 0, make_unexpected(HAILO_ETH_FAILURE), "Failed to write to socket {}", errno);
return Expected<size_t>(bytes_written);
}
hailo_status Socket::sendall(const uint8_t *buffer, size_t size, int flags)
{
size_t offset = 0;
while (offset < size) {
const auto size_to_write = size - offset;
TRY(auto bytes_written, send(buffer + offset, size_to_write, flags));
if (bytes_written == 0) {
return HAILO_ETH_SEND_FAILURE;
}
offset += bytes_written;
}
return HAILO_SUCCESS;
}
hailo_status Socket::ntop(int af, const void *src, char *dst, socklen_t size)
{
CHECK_ARG_NOT_NULL(src);
@@ -205,6 +259,16 @@ hailo_status Socket::enable_broadcast()
return HAILO_SUCCESS;
}
hailo_status Socket::allow_reuse_address()
{
int allow_reuse = 1;
auto socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_REUSEADDR, &allow_reuse, sizeof(allow_reuse));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Cannot set socket to be broadcast");
return HAILO_SUCCESS;
}
hailo_status Socket::send_to(const uint8_t *src_buffer, size_t src_buffer_size, int flags,
const sockaddr *dest_addr, socklen_t dest_addr_size, size_t *bytes_sent)
{

View File

@@ -9,8 +9,7 @@
#include "common/logger_macros.hpp"
#include "os/file_descriptor.hpp"
#include "os/windows/osdep.hpp"
#include "common/file_descriptor.hpp"
namespace hailort
{

View File

@@ -0,0 +1,48 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file mmap_buffer.cpp
* @brief Wrapper around windows memory mapping (mmap). Not implemented yet
**/
#include "common/mmap_buffer.hpp"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
namespace hailort
{
void * const MmapBufferImpl::INVALID_ADDR = NULL;
Expected<MmapBufferImpl> MmapBufferImpl::create_shared_memory(size_t)
{
LOGGER__ERROR("Creating shared memory is not implemented on windows");
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
Expected<MmapBufferImpl> MmapBufferImpl::create_file_map(size_t size, FileDescriptor &fd, uintptr_t offset)
{
DWORD offset_high = static_cast<DWORD>(offset >> 32); // High 32 bits
DWORD offset_low = static_cast<DWORD>(offset & 0xFFFFFFFF); // Low 32 bits
auto file_view_ptr = MapViewOfFile(fd, FILE_MAP_ALL_ACCESS, offset_high, offset_low, size);
CHECK_AS_EXPECTED((file_view_ptr != nullptr), HAILO_INTERNAL_FAILURE, "Failed to map view of file, error = {}", GetLastError());
return MmapBufferImpl(file_view_ptr, size);
}
hailo_status MmapBufferImpl::unmap()
{
if (m_address != nullptr) {
UnmapViewOfFile(m_address);
m_address = nullptr;
}
return HAILO_SUCCESS;
}
} /* namespace hailort */

View File

@@ -0,0 +1,45 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file named_mutex_guard.hpp
* @brief Named mutex guard implementation
**/
#include "named_mutex_guard.hpp"
#include "hailo/hailort.h"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
namespace hailort
{
Expected<std::unique_ptr<NamedMutexGuard>> NamedMutexGuard::create(const std::string &named_mutex)
{
// Create a named mutex
HANDLE mutex_handle = CreateMutex(NULL, FALSE, named_mutex.c_str());
CHECK_AS_EXPECTED(mutex_handle != NULL, HAILO_INTERNAL_FAILURE, "Failed to create named mutex, error = {}", GetLastError());
// Check if the mutex is already acquired by another instance
if (GetLastError() == ERROR_ALREADY_EXISTS) {
LOGGER__ERROR("Another instance of {} is already running", named_mutex);
CloseHandle(mutex_handle);
return make_unexpected(HAILO_INVALID_OPERATION);
}
auto guarded_named_mutex = make_unique_nothrow<NamedMutexGuard>(mutex_handle);
CHECK_NOT_NULL_AS_EXPECTED(guarded_named_mutex, HAILO_OUT_OF_HOST_MEMORY);
return guarded_named_mutex;
}
NamedMutexGuard::NamedMutexGuard(HANDLE mutex_handle) : m_mutex_handle(mutex_handle)
{}
NamedMutexGuard::~NamedMutexGuard()
{
CloseHandle(m_mutex_handle);
}
} /* namespace hailort */

View File

@@ -0,0 +1,39 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file named_mutex_guard.hpp
* @brief Named mutex guard
**/
#ifndef _HAILO_NAMED_MUTEX_GUARD_HPP_
#define _HAILO_NAMED_MUTEX_GUARD_HPP_
#include "hailo/hailort.h"
#include "hailo/expected.hpp"
#include <string>
#include <memory>
namespace hailort
{
class NamedMutexGuard
{
public:
static Expected<std::unique_ptr<NamedMutexGuard>> create(const std::string &named_mutex);
NamedMutexGuard(NamedMutexGuard &&) = delete;
NamedMutexGuard(const NamedMutexGuard &) = delete;
NamedMutexGuard &operator=(NamedMutexGuard &&) = delete;
NamedMutexGuard &operator=(const NamedMutexGuard &) = delete;
virtual ~NamedMutexGuard();
NamedMutexGuard(HANDLE mutex_handle);
private:
HANDLE m_mutex_handle;
};
} /* namespace hailort */
#endif /* _HAILO_NAMED_MUTEX_GUARD_HPP_ */

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file shared_memory_buffer.cpp
* @brief Shared memory implementaion in Windows.
* Based on Windows docs: https://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
**/
#include "common/shared_memory_buffer.hpp"
#include "common/utils.hpp"
#include "hailo/hailort.h"
#include <windows.h>
namespace hailort
{
Expected<SharedMemoryBufferPtr> SharedMemoryBuffer::create(size_t size, const std::string &shm_name)
{
HANDLE handle_map_file = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0,
static_cast<DWORD>(size), static_cast<LPCSTR>(shm_name.c_str()));
CHECK_AS_EXPECTED((handle_map_file != nullptr), HAILO_INTERNAL_FAILURE, "Failed to create shared memory object, error = {}", GetLastError());
auto shm_fd = FileDescriptor(handle_map_file);
TRY(auto mmapped_buffer, MmapBuffer<void>::create_file_map(size, shm_fd, 0));
auto result = make_shared_nothrow<SharedMemoryBuffer>(shm_name, std::move(shm_fd), std::move(mmapped_buffer), true);
CHECK_NOT_NULL_AS_EXPECTED(result, HAILO_OUT_OF_HOST_MEMORY);
return result;
}
Expected<SharedMemoryBufferPtr> SharedMemoryBuffer::open(size_t size, const std::string &shm_name)
{
HANDLE handle_map_file = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, static_cast<LPCSTR>(shm_name.c_str()));
CHECK_AS_EXPECTED((handle_map_file != nullptr), HAILO_INTERNAL_FAILURE, "Failed to open file mapping object, error = {}", GetLastError());
auto shm_fd = FileDescriptor(handle_map_file);
TRY(auto mmapped_buffer, MmapBuffer<void>::create_file_map(size, shm_fd, 0));
auto result = make_shared_nothrow<SharedMemoryBuffer>(shm_name, std::move(shm_fd), std::move(mmapped_buffer), false);
CHECK_NOT_NULL_AS_EXPECTED(result, HAILO_OUT_OF_HOST_MEMORY);
return result;
}
SharedMemoryBuffer::~SharedMemoryBuffer()
{}
size_t SharedMemoryBuffer::size() const
{
return m_shm_mmap_buffer.size();
}
void *SharedMemoryBuffer::user_address()
{
return m_shm_mmap_buffer.address();
}
std::string SharedMemoryBuffer::shm_name()
{
return m_shm_name;
}
} /* namespace hailort */

View File

@@ -41,13 +41,17 @@ hailo_status Socket::SocketModuleWrapper::free_module()
Expected<Socket> Socket::create(int af, int type, int protocol)
{
TRY(auto module_wrapper, SocketModuleWrapper::create());
auto module_wrapper_ptr = make_shared_nothrow<SocketModuleWrapper>(std::move(module_wrapper));
CHECK_NOT_NULL(module_wrapper_ptr, HAILO_OUT_OF_HOST_MEMORY);
TRY(const auto socket_fd, create_socket_fd(af, type, protocol));
auto obj = Socket(std::move(module_wrapper), socket_fd);
auto obj = Socket(std::move(module_wrapper_ptr), socket_fd);
return std::move(obj);
}
Socket::Socket(SocketModuleWrapper &&module_wrapper, const socket_t socket_fd) :
Socket::Socket(std::shared_ptr<SocketModuleWrapper> module_wrapper, const socket_t socket_fd) :
m_module_wrapper(std::move(module_wrapper)), m_socket_fd(socket_fd)
{
}
@@ -110,6 +114,56 @@ hailo_status Socket::get_sock_name(sockaddr *addr, socklen_t *len)
return HAILO_SUCCESS;
}
hailo_status Socket::listen(int backlog)
{
auto res = ::listen(m_socket_fd, backlog);
CHECK(0 == res, HAILO_ETH_FAILURE, "Failed to listen on socket. errno={}", errno);
return HAILO_SUCCESS;
}
Expected<Socket> Socket::accept()
{
auto client_socket = ::accept(m_socket_fd, nullptr, nullptr);
CHECK(client_socket != INVALID_SOCKET, make_unexpected(HAILO_ETH_FAILURE), "Failed to accept connection {}", errno);
return Socket(m_module_wrapper, client_socket);
}
hailo_status Socket::connect(const sockaddr *addr, socklen_t len)
{
int ret = ::connect(m_socket_fd, addr, len);
CHECK(0 == ret, HAILO_ETH_FAILURE, "Failed to connect to socket {}", errno);
return HAILO_SUCCESS;
}
Expected<size_t> Socket::recv(uint8_t *buffer, size_t size, int flags)
{
auto read_bytes = ::recv(m_socket_fd, reinterpret_cast<char*>(buffer), static_cast<int>(size), flags);
CHECK(read_bytes >= 0, make_unexpected(HAILO_ETH_FAILURE), "Failed to read from socket {}", errno);
return Expected<size_t>(read_bytes);
}
Expected<size_t> Socket::send(const uint8_t *buffer, size_t size, int flags)
{
auto bytes_written = ::send(m_socket_fd, reinterpret_cast<const char*>(buffer), static_cast<int>(size), flags);
CHECK(bytes_written >= 0, make_unexpected(HAILO_ETH_FAILURE), "Failed to write to socket {}", errno);
return Expected<size_t>(bytes_written);
}
hailo_status Socket::sendall(const uint8_t *buffer, size_t size, int flags)
{
size_t offset = 0;
while (offset < size) {
const auto size_to_write = size - offset;
TRY(auto bytes_written, send(buffer + offset, size_to_write, flags));
if (bytes_written == 0) {
return HAILO_ETH_SEND_FAILURE;
}
offset += bytes_written;
}
return HAILO_SUCCESS;
}
hailo_status Socket::ntop(int af, const void *src, char *dst, socklen_t size)
{
CHECK_ARG_NOT_NULL(src);
@@ -190,6 +244,17 @@ hailo_status Socket::enable_broadcast()
return HAILO_SUCCESS;
}
hailo_status Socket::allow_reuse_address()
{
int allow_reuse = 1;
auto socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_REUSEADDR,
reinterpret_cast<const char*>(&allow_reuse), sizeof(allow_reuse));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Cannot set socket to be broadcast");
return HAILO_SUCCESS;
}
hailo_status Socket::send_to(const uint8_t *src_buffer, size_t src_buffer_size, int flags,
const sockaddr *dest_addr, socklen_t dest_addr_size, size_t *bytes_sent)
{

View File

@@ -7,7 +7,7 @@
* @brief Guard object for VirtualAlloc and VirtualFree
**/
#include "os/windows/virtual_alloc_guard.hpp"
#include "virtual_alloc_guard.hpp"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"

View File

@@ -0,0 +1,81 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file shared_memory_buffer.hpp
* @brief Shared memory buffer
**/
#ifndef _HAILO_SHARED_MEMORY_BUFFER_HPP_
#define _HAILO_SHARED_MEMORY_BUFFER_HPP_
#include "common/file_descriptor.hpp"
#include "common/mmap_buffer.hpp"
#include "hailo/hailort.h"
#include "hailo/expected.hpp"
#include "hailo/buffer.hpp"
namespace hailort
{
#define SHARED_MEMORY_NAME_SEPERATOR '_'
#define INVALID_SHARED_MEMORY_CHAR '/'
#if defined(_MSC_VER)
#define SHARED_MEMORY_NAME_PREFIX "Global\\"
#else
#define SHARED_MEMORY_NAME_PREFIX '/'
#endif
class SharedMemoryBuffer;
using SharedMemoryBufferPtr = std::shared_ptr<SharedMemoryBuffer>;
class SharedMemoryBuffer
{
public:
static Expected<SharedMemoryBufferPtr> create(size_t size, const std::string &shm_name);
static Expected<SharedMemoryBufferPtr> open(size_t size, const std::string &shm_name);
SharedMemoryBuffer(const SharedMemoryBuffer &) = delete;
SharedMemoryBuffer &operator=(SharedMemoryBuffer &&) = delete;
SharedMemoryBuffer &operator=(const SharedMemoryBuffer &) = delete;
virtual ~SharedMemoryBuffer();
SharedMemoryBuffer(const std::string &shm_name, FileDescriptor &&shm_fd, MmapBuffer<void> &&shm_mmap_buffer, bool memory_owner) :
m_shm_name(shm_name),
m_shm_fd(std::move(shm_fd)),
m_shm_mmap_buffer(std::move(shm_mmap_buffer)),
m_memory_owner(memory_owner)
{}
SharedMemoryBuffer(SharedMemoryBuffer&& other) noexcept :
m_shm_name(std::exchange(other.m_shm_name, "")),
m_shm_fd(std::move(other.m_shm_fd)),
m_shm_mmap_buffer(std::move(other.m_shm_mmap_buffer)),
m_memory_owner(std::exchange(other.m_memory_owner, false))
{}
virtual size_t size() const;
virtual void *user_address();
std::string shm_name();
static std::string get_valid_shm_name(const std::string &name)
{
std::string valid_shm_name = name;
std::replace(valid_shm_name.begin(), valid_shm_name.end(), INVALID_SHARED_MEMORY_CHAR, SHARED_MEMORY_NAME_SEPERATOR);
valid_shm_name = SHARED_MEMORY_NAME_PREFIX + valid_shm_name;
return valid_shm_name;
}
private:
std::string m_shm_name;
FileDescriptor m_shm_fd;
MmapBuffer<void> m_shm_mmap_buffer;
bool m_memory_owner;
};
} /* namespace hailort */
#endif /* _HAILO_SHARED_MEMORY_BUFFER_HPP_ */

View File

@@ -50,9 +50,18 @@ public:
hailo_status socket_bind(const sockaddr *addr, socklen_t len);
hailo_status get_sock_name(sockaddr *addr, socklen_t *len);
hailo_status listen(int backlog);
Expected<Socket> accept();
hailo_status connect(const sockaddr *addr, socklen_t len);
Expected<size_t> recv(uint8_t *buffer, size_t size, int flags = 0);
Expected<size_t> send(const uint8_t *buffer, size_t size, int flags = 0);
hailo_status sendall(const uint8_t *buffer, size_t size, int flags = 0);
hailo_status set_recv_buffer_size_max();
hailo_status set_timeout(const std::chrono::milliseconds timeout_ms, timeval_t *timeout);
hailo_status enable_broadcast();
hailo_status allow_reuse_address();
hailo_status abort();
// TODO: Should these be in udp.cpp?
@@ -96,12 +105,12 @@ private:
static hailo_status free_module();
};
Socket(SocketModuleWrapper &&module_wrapper, const socket_t socket_fd);
Socket(std::shared_ptr<SocketModuleWrapper> module_wrapper, const socket_t socket_fd);
static Expected<socket_t> create_socket_fd(int af, int type, int protocol);
hailo_status close_socket_fd();
// Itialization dependency
SocketModuleWrapper m_module_wrapper;
std::shared_ptr<SocketModuleWrapper> m_module_wrapper;
socket_t m_socket_fd;
};

View File

@@ -12,6 +12,7 @@
#include "hailo/expected.hpp"
#include <string>
#include <algorithm>
namespace hailort
{
@@ -22,6 +23,14 @@ public:
static Expected<uint8_t> to_uint8(const std::string &str, int base);
static Expected<uint32_t> to_uint32(const std::string &str, int base);
static std::string to_lower(const std::string &str)
{
std::string lower_str = str;
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(),
[](auto ch) { return static_cast<char>(::tolower(ch)); });
return lower_str;
}
static std::string to_hex_string(const uint8_t *array, size_t size, bool uppercase, const std::string &delimiter="");
};

View File

@@ -0,0 +1,90 @@
/**
* Copyright (c) 2020-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file thread_pool.hpp
* @brief Implementation of thread pool that uses async threads
**/
#ifndef _THREAD_POOL_HPP_
#define _THREAD_POOL_HPP_
#include "async_thread.hpp"
namespace hailort {
class HailoThreadPool {
public:
HailoThreadPool(size_t num_worker_threads) : m_num_threads(num_worker_threads), m_kill_threads(false) {
auto shutdown_event = Event::create_shared(Event::State::not_signalled).release();
for (size_t i = 0; i < num_worker_threads; i++) {
m_threads.emplace_back(std::make_unique<AsyncThread<hailo_status>>(
[this]() -> hailo_status {
while(true) {
std::function<hailo_status()> func;
{
std::unique_lock<std::mutex> lock(m_mutex);
m_cv.wait(lock, [this](){ return (m_kill_threads || !m_queue.empty()); });
if (m_kill_threads && m_queue.empty()) {
return HAILO_SUCCESS;
}
func = std::move(m_queue.front());
m_queue.pop();
}
hailo_status status = func();
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("thread failed with status {}");
}
}
}
));
}
}
HailoThreadPool(const HailoThreadPool &) = delete;
HailoThreadPool(HailoThreadPool &&other) = delete;
HailoThreadPool& operator=(const HailoThreadPool&) = delete;
HailoThreadPool& operator=(HailoThreadPool &&) = delete;
template<class F, class... Args>
void add_job(F&& func, Args&&... args) {
auto job = std::bind(std::forward<F>(func), std::forward<Args>(args)...);
{
std::unique_lock<std::mutex> lock(m_mutex);
if (m_kill_threads) {
LOGGER__ERROR("Cannot add jobs after threadpool has been terminated");
return;
}
m_queue.emplace(job);
}
m_cv.notify_one();
}
~HailoThreadPool() {
{
std::unique_lock<std::mutex> lock(m_mutex);
m_kill_threads = true;
}
m_cv.notify_all();
for (size_t i = 0; i < m_num_threads; i++) {
AsyncThreadPtr<hailo_status> thread = std::move(m_threads[i]);
thread->get();
}
}
private:
size_t m_num_threads;
std::vector<AsyncThreadPtr<hailo_status>> m_threads;
std::queue<std::function<hailo_status()>> m_queue;
std::mutex m_mutex;
std::condition_variable m_cv;
std::atomic<bool> m_kill_threads;
};
} /* namespace hailort*/
#endif // _THREAD_POOL_HPP_

View File

@@ -26,6 +26,7 @@
#include <cstdint>
#include <cstddef>
#include <fstream>
#include <algorithm>
namespace hailort
@@ -261,7 +262,7 @@ inline hailo_status get_status(const Expected<T> &exp)
#define _CHECK_GRPC_STATUS(status, ret_val, warning_msg) \
do { \
if (!status.ok()) { \
LOGGER__ERROR("CHECK_GRPC_STATUS failed with error code: {}.", status.error_code()); \
LOGGER__ERROR("CHECK_GRPC_STATUS failed with error code: {}.", static_cast<int>(status.error_code())); \
LOGGER__WARNING(warning_msg); \
return ret_val; \
} \
@@ -367,7 +368,7 @@ static uint32_t get_min_value_of_unordered_map(const std::unordered_map<K, V> &m
return min_count;
}
static inline bool is_env_variable_on(const char* env_var_name, const std::string &required_value = "1")
static inline bool is_env_variable_on(const char *env_var_name, const std::string &required_value = "1")
{
auto env_var = std::getenv(env_var_name);
return ((nullptr != env_var) && (strncmp(env_var, required_value.c_str(), required_value.size()) == 0));

View File

@@ -1,13 +1,13 @@
// SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) AND MIT
/**
* Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
**/
#ifndef _HAILO_IOCTL_COMMON_H_
#define _HAILO_IOCTL_COMMON_H_
#define HAILO_DRV_VER_MAJOR 4
#define HAILO_DRV_VER_MINOR 18
#define HAILO_DRV_VER_MINOR 19
#define HAILO_DRV_VER_REVISION 0
#define _STRINGIFY_EXPANDED( x ) #x
@@ -17,10 +17,11 @@
// This value is not easily changeable.
// For example: the channel interrupts ioctls assume we have up to 32 channels
#define MAX_VDMA_CHANNELS_PER_ENGINE (32)
#define MAX_VDMA_ENGINES (3)
#define SIZE_OF_VDMA_DESCRIPTOR (16)
#define VDMA_DEST_CHANNELS_START (16)
#define MAX_VDMA_CHANNELS_PER_ENGINE (32)
#define VDMA_CHANNELS_PER_ENGINE_PER_DIRECTION (16)
#define MAX_VDMA_ENGINES (3)
#define SIZE_OF_VDMA_DESCRIPTOR (16)
#define VDMA_DEST_CHANNELS_START (16)
#define HAILO_VDMA_MAX_ONGOING_TRANSFERS (128)
#define HAILO_VDMA_MAX_ONGOING_TRANSFERS_MASK (HAILO_VDMA_MAX_ONGOING_TRANSFERS - 1)
@@ -37,8 +38,8 @@
#define FW_ACCESS_APP_CPU_CONTROL_MASK (1 << FW_ACCESS_CONTROL_INTERRUPT_SHIFT)
#define FW_ACCESS_DRIVER_SHUTDOWN_SHIFT (2)
#define FW_ACCESS_DRIVER_SHUTDOWN_MASK (1 << FW_ACCESS_DRIVER_SHUTDOWN_SHIFT)
#define FW_ACCESS_SOC_CONNECT_SHIFT (3)
#define FW_ACCESS_SOC_CONNECT_MASK (1 << FW_ACCESS_SOC_CONNECT_SHIFT)
#define FW_ACCESS_SOC_CONTROL_SHIFT (3)
#define FW_ACCESS_SOC_CONTROL_MASK (1 << FW_ACCESS_SOC_CONTROL_SHIFT)
#define INVALID_VDMA_CHANNEL (0xff)
@@ -245,6 +246,12 @@ struct hailo_desc_list_release_params {
uintptr_t desc_handle; // in
};
struct hailo_write_action_list_params {
uint8_t *data; // in
size_t size; // in
uint64_t dma_address; // out
};
/* structure used in ioctl HAILO_DESC_LIST_BIND_VDMA_BUFFER */
struct hailo_desc_list_program_params {
size_t buffer_handle; // in
@@ -508,6 +515,7 @@ struct hailo_vdma_launch_transfer_params {
/* structure used in ioctl HAILO_SOC_CONNECT */
struct hailo_soc_connect_params {
uint16_t port_number; // in
uint8_t input_channel_index; // out
uint8_t output_channel_index; // out
uintptr_t input_desc_handle; // in
@@ -522,6 +530,7 @@ struct hailo_soc_close_params {
/* structure used in ioctl HAILO_PCI_EP_ACCEPT */
struct hailo_pci_ep_accept_params {
uint16_t port_number; // in
uint8_t input_channel_index; // out
uint8_t output_channel_index; // out
uintptr_t input_desc_handle; // in
@@ -562,6 +571,7 @@ struct tCompatibleHailoIoctlData
struct hailo_soc_close_params SocCloseParams;
struct hailo_pci_ep_accept_params AcceptParams;
struct hailo_pci_ep_close_params PciEpCloseParams;
struct hailo_write_action_list_params WriteActionListParams;
} Buffer;
};
#endif // _MSC_VER
@@ -632,6 +642,7 @@ enum hailo_nnc_ioctl_code {
HAILO_DISABLE_NOTIFICATION_CODE,
HAILO_READ_LOG_CODE,
HAILO_RESET_NN_CORE_CODE,
HAILO_WRITE_ACTION_LIST_CODE,
// Must be last
HAILO_NNC_IOCTL_MAX_NR
@@ -642,6 +653,7 @@ enum hailo_nnc_ioctl_code {
#define HAILO_DISABLE_NOTIFICATION _IO_(HAILO_NNC_IOCTL_MAGIC, HAILO_DISABLE_NOTIFICATION_CODE)
#define HAILO_READ_LOG _IOWR_(HAILO_NNC_IOCTL_MAGIC, HAILO_READ_LOG_CODE, struct hailo_read_log_params)
#define HAILO_RESET_NN_CORE _IO_(HAILO_NNC_IOCTL_MAGIC, HAILO_RESET_NN_CORE_CODE)
#define HAILO_WRITE_ACTION_LIST _IOW_(HAILO_NNC_IOCTL_MAGIC, HAILO_WRITE_ACTION_LIST_CODE, struct hailo_write_action_list_params)
enum hailo_soc_ioctl_code {
HAILO_SOC_IOCTL_CONNECT_CODE,

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/spdlog.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/readerwriterqueue.cmake)
@@ -10,32 +10,22 @@ set(HAILORT_SERVER_SOURCES
hailort_server.cpp
${HRPC_CPP_SOURCES}
${HRPC_PROTOCOL_CPP_SOURCES}
${HAILORT_COMMON_OS_DIR}/os_utils.cpp
${HAILORT_SERVICE_DIR}/cng_buffer_pool.cpp
${HAILORT_COMMON_DIR}/common/event_internal.cpp
${HAILO_FULL_OS_DIR}/event.cpp # TODO HRT-10681: move to common
${DRIVER_OS_DIR}/driver_os_specific.cpp
${HAILO_OS_DIR}/file_descriptor.cpp
${HAILO_OS_DIR}/mmap_buffer.cpp
${HAILORT_SRC_DIR}/vdma/pcie_session.cpp
${HAILORT_SRC_DIR}/vdma/memory/descriptor_list.cpp
${HAILORT_SRC_DIR}/vdma/memory/mapped_buffer.cpp
${HAILORT_SRC_DIR}/vdma/memory/dma_able_buffer.cpp
${HAILORT_SRC_DIR}/vdma/memory/vdma_edge_layer.cpp
${HAILORT_SRC_DIR}/vdma/driver/hailort_driver.cpp
${HAILORT_SRC_DIR}/vdma/channel/interrupts_dispatcher.cpp
${HAILORT_SRC_DIR}/vdma/channel/transfer_launcher.cpp
${HAILORT_SRC_DIR}/vdma/channel/boundary_channel.cpp
${HAILORT_SRC_DIR}/vdma/channel/channels_group.cpp
${HAILORT_SRC_DIR}/stream_common/transfer_common.cpp
${HAILORT_SRC_DIR}/vdma/channel/transfer_common.cpp
${HAILORT_COMMON_CPP_SOURCES}
)
if(WIN32)
# hailort_driver.cpp in windows depends on string_conversion
# dma_able_buffer.cpp in windows depends on virtual_alloc_guard
set(HAILORT_SERVER_SOURCES ${HAILORT_SERVER_SOURCES}
${HAILORT_COMMON_OS_DIR}/string_conversion.cpp
${HAILO_FULL_OS_DIR}/virtual_alloc_guard.cpp)
endif()
add_executable(hailort_server ${HAILORT_SERVER_SOURCES})
target_include_directories(hailort_server PRIVATE
@@ -53,3 +43,9 @@ target_link_libraries(hailort_server PRIVATE
spdlog::spdlog
readerwriterqueue
)
if(WIN32)
target_link_libraries(hailort_server PRIVATE Ws2_32 Iphlpapi Shlwapi winmm.lib)
elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Android)
# TODO: HRT-14770 fix android build
target_link_libraries(hailort_server PRIVATE rt)
endif()

View File

@@ -41,6 +41,16 @@ using namespace hailort;
return make_unexpected(HAILO_INTERNAL_FAILURE); \
} \
} while (0)
#define CHECK_AS_HRPC_STATUS(_cond, _status, T) \
do { \
if (!(_cond)) { \
LOGGER__ERROR("CHECK_AS_HRPC_STATUS failed, status: {}", _status); \
auto reply = T::serialize_reply(_status); \
if (reply) return reply; \
LOGGER__CRITICAL("Failed to create reply with status: {}", reply.status()); \
return make_unexpected(HAILO_INTERNAL_FAILURE); \
} \
} while (0)
#define __HAILO_CONCAT(x, y) x ## y
#define _HAILO_CONCAT(x, y) __HAILO_CONCAT(x, y)
@@ -115,7 +125,7 @@ hailo_status hrpc::HailoRTServer::cleanup_client_resources(RpcConnection client_
Expected<std::unique_ptr<hrpc::HailoRTServer>> hrpc::HailoRTServer::create_unique()
{
TRY(auto connection_context, ConnectionContext::create_shared(true));
TRY(auto connection_context, ConnectionContext::create_server_shared());
auto res = make_unique_nothrow<HailoRTServer>(connection_context);
CHECK_NOT_NULL(res, HAILO_OUT_OF_HOST_MEMORY);
return res;
@@ -158,6 +168,7 @@ int main()
TRY_AS_HRPC_STATUS(auto tuple, CreateInferModelSerializer::deserialize_request(request), CreateInferModelSerializer);
auto vdevice_handle = std::get<0>(tuple);
uint64_t hef_size = std::get<1>(tuple);
auto name = std::get<2>(tuple);
assert(hef_size <= SIZE_MAX);
TRY_AS_HRPC_STATUS(auto hef_buffer, Buffer::create(static_cast<size_t>(hef_size), BufferStorageParams::create_dma()), CreateInferModelSerializer);
@@ -166,8 +177,8 @@ int main()
CHECK_SUCCESS_AS_HRPC_STATUS(status, CreateInferModelSerializer);
auto &vdevice_manager = ServiceResourceManager<VDevice>::get_instance();
auto lambda = [view = MemoryView(hef_buffer)] (std::shared_ptr<VDevice> vdevice) {
return vdevice->create_infer_model(view);
auto lambda = [view = MemoryView(hef_buffer), &name] (std::shared_ptr<VDevice> vdevice) {
return vdevice->create_infer_model(view, name);
};
auto infer_model = vdevice_manager.execute<Expected<std::shared_ptr<InferModel>>>(vdevice_handle, lambda);
CHECK_EXPECTED_AS_HRPC_STATUS(infer_model, CreateInferModelSerializer);
@@ -434,10 +445,10 @@ int main()
auto bindings_lambda = [] (std::shared_ptr<ConfiguredInferModel> configured_infer_model) {
return configured_infer_model->create_bindings();
};
TRY_AS_HRPC_STATUS(auto request_tuple, RunAsyncSerializer::deserialize_request(request), RunAsyncSerializer);
auto configured_infer_model_handle = std::get<0>(request_tuple);
auto infer_model_handle = std::get<1>(request_tuple);
auto callback_id = std::get<2>(request_tuple);
TRY_AS_HRPC_STATUS(auto request_struct, RunAsyncSerializer::deserialize_request(request), RunAsyncSerializer);
auto configured_infer_model_handle = request_struct.configured_infer_model_handle;
auto infer_model_handle = request_struct.infer_model_handle;
auto callback_id = request_struct.callback_handle;
auto bindings = cim_manager.execute<Expected<ConfiguredInferModel::Bindings>>(configured_infer_model_handle, bindings_lambda);
CHECK_EXPECTED_AS_HRPC_STATUS(bindings, RunAsyncSerializer);
@@ -452,17 +463,28 @@ int main()
std::vector<BufferPtr> inputs; // TODO: add infer vector pool
inputs.reserve(infer_model_info->inputs_names.size());
uint32_t buffer_size_index = 0;
for (const auto &input_name : infer_model_info->inputs_names) {
TRY_AS_HRPC_STATUS(auto input, bindings->input(input_name), RunAsyncSerializer);
TRY_AS_HRPC_STATUS(auto buffer_ptr, buffer_pool_per_cim[configured_infer_model_handle]->acquire_buffer(input_name),
RunAsyncSerializer);
auto status = server_context->connection().read_buffer(MemoryView(*buffer_ptr));
CHECK_SUCCESS_AS_HRPC_STATUS(status, RunAsyncSerializer);
uint32_t read_size = 0;
while (read_size < buffer_ptr->size()) {
uint32_t current_size = request_struct.input_buffer_sizes[buffer_size_index++];
CHECK_AS_HRPC_STATUS(read_size + current_size <= buffer_ptr->size(), HAILO_INTERNAL_FAILURE,
RunAsyncSerializer);
auto status = server_context->connection().read_buffer(MemoryView(buffer_ptr->data() + read_size, current_size));
CHECK_SUCCESS_AS_HRPC_STATUS(status, RunAsyncSerializer);
read_size += current_size;
}
inputs.emplace_back(buffer_ptr);
status = input.set_buffer(MemoryView(*buffer_ptr));
auto status = input.set_buffer(MemoryView(*buffer_ptr));
CHECK_SUCCESS_AS_HRPC_STATUS(status, RunAsyncSerializer);
}
@@ -488,7 +510,16 @@ int main()
return configured_infer_model->run_async(bindings,
[callback_id, server_context, inputs, outputs, &buffer_pool_per_cim, configured_infer_model_handle, infer_model_info]
(const AsyncInferCompletionInfo &completion_info) {
auto status = server_context->trigger_callback(callback_id, completion_info.status, [outputs, completion_info] (hrpc::RpcConnection connection) -> hailo_status {
for (uint32_t i = 0; i < inputs.size(); i++) {
auto status = buffer_pool_per_cim[configured_infer_model_handle]->return_to_pool(infer_model_info->inputs_names[i], inputs[i]);
if (status != HAILO_SUCCESS) {
LOGGER__CRITICAL("return_to_pool failed for input {}, status = {}. Server should restart!", infer_model_info->inputs_names[i], status);
return;
}
}
auto status = server_context->trigger_callback(callback_id, completion_info.status, configured_infer_model_handle,
[outputs, completion_info] (hrpc::RpcConnection connection) -> hailo_status {
if (HAILO_SUCCESS == completion_info.status) {
for (auto output : outputs) {
auto status = connection.write_buffer(MemoryView(*output));
@@ -503,13 +534,6 @@ int main()
LOGGER__CRITICAL("Error {} returned from connection.write(). Server Should restart!", status);
}
for (uint32_t i = 0; i < inputs.size(); i++) {
status = buffer_pool_per_cim[configured_infer_model_handle]->return_to_pool(infer_model_info->inputs_names[i], inputs[i]);
if (status != HAILO_SUCCESS) {
LOGGER__CRITICAL("return_to_pool failed for input {}, status = {}. Server should restart!", infer_model_info->inputs_names[i], status);
return;
}
}
for (uint32_t i = 0; i < outputs.size(); i++) {
status = buffer_pool_per_cim[configured_infer_model_handle]->return_to_pool(infer_model_info->outputs_names[i], outputs[i]);
if (status != HAILO_SUCCESS) {
@@ -527,6 +551,52 @@ int main()
TRY_AS_HRPC_STATUS(auto reply, RunAsyncSerializer::serialize_reply(HAILO_SUCCESS), RunAsyncSerializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__CREATE,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto status = CreateDeviceSerializer::deserialize_request(request);
CHECK_SUCCESS_AS_HRPC_STATUS(status, CreateDeviceSerializer);
TRY_AS_HRPC_STATUS(auto device, Device::create(), CreateDeviceSerializer);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto id = manager.register_resource(SINGLE_CLIENT_PID, std::move(device));
auto reply = CreateDeviceSerializer::serialize_reply(HAILO_SUCCESS, id);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__DESTROY,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &manager = ServiceResourceManager<Device>::get_instance();
TRY_AS_HRPC_STATUS(auto device_handle, DestroyDeviceSerializer::deserialize_request(request), DestroyDeviceSerializer);
(void)manager.release_resource(device_handle, SINGLE_CLIENT_PID);
TRY_AS_HRPC_STATUS(auto reply, DestroyDeviceSerializer::serialize_reply(HAILO_SUCCESS), DestroyDeviceSerializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__IDENTIFY,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
TRY_AS_HRPC_STATUS(auto device_handle, IdentifyDeviceSerializer::deserialize_request(request), IdentifyDeviceSerializer);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [] (std::shared_ptr<Device> device) {
return device->identify();
};
TRY_AS_HRPC_STATUS(auto identity,
manager.execute<Expected<hailo_device_identity_t>>(device_handle, device_lambda), IdentifyDeviceSerializer);
TRY_AS_HRPC_STATUS(auto reply, IdentifyDeviceSerializer::serialize_reply(HAILO_SUCCESS, identity), IdentifyDeviceSerializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__EXTENDED_INFO,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
TRY_AS_HRPC_STATUS(auto device_handle, ExtendedDeviceInfoSerializer::deserialize_request(request), ExtendedDeviceInfoSerializer);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [] (std::shared_ptr<Device> device) {
return device->get_extended_device_information();
};
TRY_AS_HRPC_STATUS(auto extended_info,
manager.execute<Expected<hailo_extended_device_information_t>>(device_handle, device_lambda), ExtendedDeviceInfoSerializer);
TRY_AS_HRPC_STATUS(auto reply, ExtendedDeviceInfoSerializer::serialize_reply(HAILO_SUCCESS, extended_info), ExtendedDeviceInfoSerializer);
return reply;
});
server->set_dispatcher(dispatcher);
auto status = server->serve();

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/spdlog.cmake)
@@ -30,6 +30,8 @@ target_link_libraries(hailort_service
if(WIN32)
# Needed in order to compile eth utils (we compile here ${HAILORT_COMMON_CPP_SOURCES}, consider removing)
target_link_libraries(hailort_service Iphlpapi Shlwapi Kernel32 Advapi32)
elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Android)
target_link_libraries(hailort_service rt)
endif()
target_include_directories(hailort_service

View File

@@ -14,9 +14,8 @@
namespace hailort
{
Expected<std::shared_ptr<ServiceStreamBufferPool>> ServiceStreamBufferPool::create(uint32_t vdevice_handle,
size_t buffer_size, size_t buffer_count, hailo_dma_buffer_direction_t direction, EventPtr shutdown_event)
Expected<BasicBufferPoolPtr> ServiceNetworkGroupBufferPool::create_stream_buffer_pool(size_t buffer_size,
size_t buffer_count, hailo_dma_buffer_direction_t direction, EventPtr shutdown_event)
{
auto map_buffer_lambda = [direction](std::shared_ptr<VDevice> vdevice, BufferPtr buffer) {
return DmaMappedBuffer::create(*vdevice, buffer->data(), buffer->size(), direction);
@@ -26,59 +25,28 @@ Expected<std::shared_ptr<ServiceStreamBufferPool>> ServiceStreamBufferPool::crea
TRY(auto free_buffers_queue,
SpscQueue<BufferPtr>::create(buffer_count, shutdown_event, DEFAULT_TRANSFER_TIMEOUT));
std::vector<AllocatedMappedBuffer> buffers;
std::vector<BufferPtr> buffers;
buffers.reserve(buffer_count);
for (size_t i = 0; i < buffer_count; i++) {
TRY(auto buffer, Buffer::create_shared(buffer_size, BufferStorageParams::create_dma()));
TRY(auto mapped_buffer,
vdevice_manager.execute<Expected<DmaMappedBuffer>>(vdevice_handle, map_buffer_lambda, buffer));
vdevice_manager.execute<Expected<DmaMappedBuffer>>(m_vdevice_handle, map_buffer_lambda, buffer));
auto status = free_buffers_queue.enqueue(buffer);
CHECK_SUCCESS(status);
buffers.emplace_back(AllocatedMappedBuffer{ buffer, std::move(mapped_buffer)});
buffers.emplace_back(buffer);
m_mapped_buffers.emplace_back(DmaMappedBuffer(std::move(mapped_buffer)));
}
auto buffer_pool_ptr = make_shared_nothrow<ServiceStreamBufferPool>(buffer_size, std::move(buffers),
auto buffer_pool_ptr = make_shared_nothrow<BasicBufferPool>(buffer_size, std::move(buffers),
std::move(free_buffers_queue), buffer_count);
CHECK_NOT_NULL_AS_EXPECTED(buffer_pool_ptr, HAILO_OUT_OF_HOST_MEMORY);
return buffer_pool_ptr;
}
ServiceStreamBufferPool::ServiceStreamBufferPool(size_t buffer_size, std::vector<AllocatedMappedBuffer> &&buffers,
SpscQueue<BufferPtr> &&free_buffers_queue, size_t buffers_count) :
m_buffer_size(buffer_size),
m_buffers_count(buffers_count),
m_buffers(std::move(buffers)),
m_free_buffers_queue(std::move(free_buffers_queue))
{}
Expected<BufferPtr> ServiceStreamBufferPool::acquire_buffer()
{
TRY_WITH_ACCEPTABLE_STATUS(HAILO_SHUTDOWN_EVENT_SIGNALED, auto buffer,
m_free_buffers_queue.dequeue(DEFAULT_TRANSFER_TIMEOUT));
return buffer;
}
hailo_status ServiceStreamBufferPool::return_to_pool(BufferPtr buffer)
{
CHECK(buffer->size() == m_buffer_size, HAILO_INTERNAL_FAILURE,
"Buffer size is not the same as expected for pool! ({} != {})", buffer->size(), m_buffer_size);
std::unique_lock<std::mutex> lock(m_mutex);
auto status = m_free_buffers_queue.enqueue(buffer);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
size_t ServiceStreamBufferPool::buffers_count()
{
return m_buffers_count;
}
Expected<std::shared_ptr<ServiceNetworkGroupBufferPool>> ServiceNetworkGroupBufferPool::create(uint32_t vdevice_handle)
{
TRY(auto shutdown_event, Event::create_shared(Event::State::not_signalled));
@@ -90,14 +58,13 @@ Expected<std::shared_ptr<ServiceNetworkGroupBufferPool>> ServiceNetworkGroupBuff
}
ServiceNetworkGroupBufferPool::ServiceNetworkGroupBufferPool(EventPtr shutdown_event, uint32_t vdevice_handle) :
m_stream_name_to_buffer_pool(), m_shutdown_event(shutdown_event), m_vdevice_handle(vdevice_handle)
m_stream_name_to_buffer_pool(), m_mapped_buffers(), m_shutdown_event(shutdown_event), m_vdevice_handle(vdevice_handle), m_is_shutdown(false)
{}
hailo_status ServiceNetworkGroupBufferPool::allocate_pool(const std::string &name,
hailo_dma_buffer_direction_t direction, size_t frame_size, size_t pool_size)
{
TRY(auto buffer_pool, ServiceStreamBufferPool::create(m_vdevice_handle, frame_size,
pool_size, direction, m_shutdown_event));
TRY(auto buffer_pool, create_stream_buffer_pool(frame_size, pool_size, direction, m_shutdown_event));
std::unique_lock<std::mutex> lock(m_mutex);
m_stream_name_to_buffer_pool[name] = buffer_pool;
@@ -111,9 +78,9 @@ hailo_status ServiceNetworkGroupBufferPool::reallocate_pool(const std::string &n
std::unique_lock<std::mutex> lock(m_mutex);
auto pool_size = m_stream_name_to_buffer_pool[name]->buffers_count();
m_stream_name_to_buffer_pool[name].reset();
m_mapped_buffers.clear();
TRY(auto buffer_pool, ServiceStreamBufferPool::create(m_vdevice_handle, frame_size,
pool_size, direction, m_shutdown_event));
TRY(auto buffer_pool, create_stream_buffer_pool(frame_size, pool_size, direction, m_shutdown_event));
m_stream_name_to_buffer_pool[name] = buffer_pool;
return HAILO_SUCCESS;
@@ -125,8 +92,15 @@ Expected<BufferPtr> ServiceNetworkGroupBufferPool::acquire_buffer(const std::str
"acquire_buffer() for stream {} failed, stream name does not exist in buffer pool", stream_name);
std::unique_lock<std::mutex> lock(m_mutex);
TRY(auto buffer, m_stream_name_to_buffer_pool.at(stream_name)->acquire_buffer());
auto pool = m_stream_name_to_buffer_pool.at(stream_name);
m_cv.wait(lock, [this, pool] () {
return (pool->current_size() > 0) || m_is_shutdown;
});
if (m_is_shutdown) {
return make_unexpected(HAILO_SHUTDOWN_EVENT_SIGNALED);
}
TRY(auto buffer, pool->acquire_buffer());
return buffer;
}
@@ -135,15 +109,23 @@ hailo_status ServiceNetworkGroupBufferPool::return_to_pool(const std::string &st
CHECK(contains(m_stream_name_to_buffer_pool, stream_name), HAILO_INTERNAL_FAILURE,
"acquire_buffer() for stream {} failed, stream name does not exist in buffer pool", stream_name);
std::unique_lock<std::mutex> lock(m_mutex);
auto status = m_stream_name_to_buffer_pool.at(stream_name)->return_to_pool(buffer);
CHECK_SUCCESS(status);
{
std::unique_lock<std::mutex> lock(m_mutex);
auto status = m_stream_name_to_buffer_pool.at(stream_name)->return_to_pool(buffer);
CHECK_SUCCESS(status);
}
m_cv.notify_all();
return HAILO_SUCCESS;
}
hailo_status ServiceNetworkGroupBufferPool::shutdown()
{
{
std::unique_lock<std::mutex> lock(m_mutex);
m_is_shutdown = true;
}
m_cv.notify_all();
return m_shutdown_event->signal();
}

View File

@@ -15,40 +15,12 @@
#include "hailo/buffer.hpp"
#include "hailo/vdevice.hpp"
#include "hailo/dma_mapped_buffer.hpp"
#include "utils/thread_safe_queue.hpp"
#include "common/thread_safe_queue.hpp"
#include "common/buffer_pool.hpp"
namespace hailort
{
class ServiceStreamBufferPool
{
public:
static Expected<std::shared_ptr<ServiceStreamBufferPool>> create(uint32_t vdevice_handle, size_t buffer_size,
size_t buffer_count, hailo_dma_buffer_direction_t direction, EventPtr shutdown_event);
struct AllocatedMappedBuffer {
BufferPtr buffer;
DmaMappedBuffer mapped_buffer;
};
ServiceStreamBufferPool(size_t buffer_size, std::vector<AllocatedMappedBuffer> &&buffers,
SpscQueue<BufferPtr> &&m_free_buffers_queue, size_t buffers_count);
virtual ~ServiceStreamBufferPool() = default;
Expected<BufferPtr> acquire_buffer();
hailo_status return_to_pool(BufferPtr buffer);
size_t buffers_count();
private:
size_t m_buffer_size;
size_t m_buffers_count;
std::vector<AllocatedMappedBuffer> m_buffers;
SpscQueue<BufferPtr> m_free_buffers_queue;
std::mutex m_mutex;
};
using BufferPoolPtr = std::shared_ptr<ServiceStreamBufferPool>;
using stream_name_t = std::string;
// This object holds a buffer pool for each stream of the network group.
@@ -77,10 +49,17 @@ public:
hailo_status shutdown();
private:
std::unordered_map<stream_name_t, BufferPoolPtr> m_stream_name_to_buffer_pool;
Expected<BasicBufferPoolPtr> create_stream_buffer_pool(size_t buffer_size,
size_t buffer_count, hailo_dma_buffer_direction_t direction, EventPtr shutdown_event);
std::unordered_map<stream_name_t, BasicBufferPoolPtr> m_stream_name_to_buffer_pool;
// This is in order to keep the DmaMappedBuffer buffers alive while using the buffers pool.
std::vector<DmaMappedBuffer> m_mapped_buffers;
EventPtr m_shutdown_event;
uint32_t m_vdevice_handle;
std::mutex m_mutex;
std::condition_variable m_cv;
bool m_is_shutdown;
};
} /* namespace hailort */

View File

@@ -94,6 +94,53 @@ void HailoRtRpcService::abort_vstreams_by_pids(std::set<uint32_t> &pids)
}
}
hailo_status HailoRtRpcService::shutdown_configured_network_group(uint32_t vdevice_handle)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng) {
return cng->shutdown();
};
auto &cng_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto status = cng_manager.execute(vdevice_handle, lambda);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
void HailoRtRpcService::shutdown_configured_network_groups_by_pids(std::set<uint32_t> &pids)
{
auto cng_handles = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance().resources_handles_by_pids(pids);
for (auto &handle : cng_handles) {
auto status = shutdown_configured_network_group(handle);
if (status != HAILO_SUCCESS) {
LOGGER__ERROR("Failed to shutdown configured network group queue with handle={}, status={}", handle, status);
}
}
}
void HailoRtRpcService::shutdown_buffer_pool_by_pids(std::set<uint32_t> &pids)
{
auto buffer_pools_handles = ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance().resources_handles_by_pids(pids);
for (auto &handle : buffer_pools_handles) {
auto status = shutdown_cng_buffer_pool(handle);
if (status != HAILO_SUCCESS) {
LOGGER__ERROR("Failed to shutdown cng buffer pool with handle={}, status={}", handle, status);
}
}
}
void HailoRtRpcService::shutdown_vdevice_cb_queue_by_pids(std::set<uint32_t> &pids)
{
auto vdevice_cb_queue_handles = ServiceResourceManager<VDeviceCallbacksQueue>::get_instance().resources_handles_by_pids(pids);
for (auto &handle : vdevice_cb_queue_handles) {
auto status = shutdown_vdevice_cb_queue(handle);
if (status != HAILO_SUCCESS) {
LOGGER__ERROR("Failed to shutdown vdevice callbacks queue with handle={}, status={}", handle, status);
}
}
}
void HailoRtRpcService::remove_disconnected_clients()
{
std::this_thread::sleep_for(hailort::HAILO_KEEPALIVE_INTERVAL / 2);
@@ -113,10 +160,17 @@ void HailoRtRpcService::remove_disconnected_clients()
// blocking operation (which will be finished with timeout).
// To release the vstream the ServiceResourceManager is waiting for the resource_mutex which is also locked in execute.
abort_vstreams_by_pids(pids_to_remove);
// It is important to shutdown the cb Queue before the NG shutdown, as ongoing callbacks might continue to try to enqueue
shutdown_vdevice_cb_queue_by_pids(pids_to_remove);
shutdown_configured_network_groups_by_pids(pids_to_remove);
shutdown_buffer_pool_by_pids(pids_to_remove);
for (auto &client_pid : pids_to_remove) {
ServiceResourceManager<OutputVStream>::get_instance().release_by_pid(client_pid);
ServiceResourceManager<InputVStream>::get_instance().release_by_pid(client_pid);
ServiceResourceManager<ConfiguredNetworkGroup>::get_instance().release_by_pid(client_pid);
ServiceResourceManager<VDeviceCallbacksQueue>::get_instance().release_by_pid(client_pid);
ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance().release_by_pid(client_pid);
ServiceResourceManager<VDevice>::get_instance().release_by_pid(client_pid);
LOGGER__INFO("Client disconnected, pid: {}", client_pid);
@@ -126,7 +180,6 @@ void HailoRtRpcService::remove_disconnected_clients()
}
}
void HailoRtRpcService::keep_alive()
{
while (true) {
@@ -191,12 +244,17 @@ grpc::Status HailoRtRpcService::VDevice_create(grpc::ServerContext *, const VDev
update_client_id_timestamp(request->pid());
std::unique_lock<std::mutex> lock(m_vdevice_mutex);
auto &vdevice_manager = ServiceResourceManager<VDevice>::get_instance();
auto &cb_queue_manager = ServiceResourceManager<VDeviceCallbacksQueue>::get_instance();
auto vdevice_handle = vdevice_manager.register_resource(request->pid(), std::move(vdevice.release()));
auto cb_queue = VDeviceCallbacksQueue::create(MAX_QUEUE_SIZE);
if (HAILO_SUCCESS != cb_queue.status()) {
// cb_queue_handle and vdevice_handle indexes must be the same
cb_queue_manager.advance_current_handle_index();
}
CHECK_EXPECTED_AS_RPC_STATUS(cb_queue, reply);
auto &cb_queue_manager = ServiceResourceManager<VDeviceCallbacksQueue>::get_instance();
auto cb_queue_handle = cb_queue_manager.register_resource(request->pid(), std::move(cb_queue.release()));
if (cb_queue_handle != vdevice_handle) {
LOGGER__ERROR("cb_queue_handle = {} must be equal to vdevice_handle ={}", cb_queue_handle, vdevice_handle);
@@ -209,17 +267,26 @@ grpc::Status HailoRtRpcService::VDevice_create(grpc::ServerContext *, const VDev
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::VDevice_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
hailo_status HailoRtRpcService::shutdown_vdevice_cb_queue(uint32_t vdevice_handle)
{
auto lambda = [](std::shared_ptr<VDeviceCallbacksQueue> cb_queue) {
return cb_queue->shutdown();
};
auto &cb_queue_manager = ServiceResourceManager<VDeviceCallbacksQueue>::get_instance();
auto status = cb_queue_manager.execute(request->vdevice_identifier().vdevice_handle(), lambda);
auto status = cb_queue_manager.execute(vdevice_handle, lambda);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
grpc::Status HailoRtRpcService::VDevice_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
{
auto status = shutdown_vdevice_cb_queue(request->vdevice_identifier().vdevice_handle());
CHECK_SUCCESS_AS_RPC_STATUS(status, reply);
auto &cb_queue_manager = ServiceResourceManager<VDeviceCallbacksQueue>::get_instance();
cb_queue_manager.release_resource(request->vdevice_identifier().vdevice_handle(), request->pid());
auto &manager = ServiceResourceManager<VDevice>::get_instance();
@@ -307,9 +374,16 @@ grpc::Status HailoRtRpcService::VDevice_configure(grpc::ServerContext*, const VD
hailo_status HailoRtRpcService::create_buffer_pools_for_ng(uint32_t vdevice_handle, uint32_t ng_handle, uint32_t request_pid,
bool allocate_for_raw_streams)
{
TRY(auto cng_buffer_pool, ServiceNetworkGroupBufferPool::create(vdevice_handle));
auto &cng_buffer_pool_manager = ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance();
auto cng_buffer_pool_exp = ServiceNetworkGroupBufferPool::create(vdevice_handle);
if (HAILO_SUCCESS != cng_buffer_pool_exp.status()) {
// cng_buffer_pool_handle and network_group_handle indexes must be the same
cng_buffer_pool_manager.advance_current_handle_index();
return cng_buffer_pool_exp.status();
}
auto cng_buffer_pool = cng_buffer_pool_exp.release();
auto cng_buffer_pool_handle = cng_buffer_pool_manager.register_resource(request_pid, cng_buffer_pool);
CHECK(cng_buffer_pool_handle == ng_handle, HAILO_INTERNAL_FAILURE,
"cng_buffer_pool_handle = {} must be equal to network_group_handle ={}", cng_buffer_pool_handle, ng_handle);
@@ -431,16 +505,44 @@ ProtoCallbackIdentifier serialize_callback_identifier(uint32_t vdevice_handle, u
return cb_identifier;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
ProtoCallbackIdentifier serialize_callback_identifier_shm(uint32_t vdevice_handle, uint32_t ng_handle, callback_type_t cb_type,
const std::string &stream_name, uint32_t cb_idx, hailo_status status, const ProtoShmBufferIdentifier &shm_buffer_identifier)
{
ProtoCallbackIdentifier cb_identifier;
cb_identifier.set_vdevice_handle(vdevice_handle);
cb_identifier.set_network_group_handle(ng_handle);
cb_identifier.set_cb_type(cb_type);
cb_identifier.set_stream_name(stream_name);
cb_identifier.set_cb_idx(cb_idx);
cb_identifier.set_status(status);
auto proto_shm_identifier = cb_identifier.mutable_shared_memory_identifier();
proto_shm_identifier->set_name(shm_buffer_identifier.name());
proto_shm_identifier->set_size(shm_buffer_identifier.size());
return cb_identifier;
}
hailo_status HailoRtRpcService::shutdown_cng_buffer_pool(uint32_t network_group_handle)
{
auto buffer_shutdown_lambda = [](std::shared_ptr<ServiceNetworkGroupBufferPool> cng_buffer_pool) {
return cng_buffer_pool->shutdown();
};
auto &buffer_pool_manager = ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance();
auto status = buffer_pool_manager.execute(request->network_group_identifier().network_group_handle(), buffer_shutdown_lambda);
auto status = buffer_pool_manager.execute(network_group_handle, buffer_shutdown_lambda);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_release(grpc::ServerContext*, const Release_Request *request,
Release_Reply *reply)
{
auto status = shutdown_cng_buffer_pool(request->network_group_identifier().network_group_handle());
CHECK_SUCCESS_AS_RPC_STATUS(status, reply);
auto &buffer_pool_manager = ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance();
buffer_pool_manager.release_resource(request->network_group_identifier().network_group_handle(), request->pid());
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
@@ -456,20 +558,30 @@ hailo_status HailoRtRpcService::add_input_named_buffer(const ProtoTransferReques
// Prepare input buffer
BufferPtr buffer;
MemoryView mem_view;
auto *data = reinterpret_cast<const uint8_t*>(proto_stream_transfer_request.data().c_str());
if (reinterpret_cast<size_t>(data) % HailoRTCommon::HW_DATA_ALIGNMENT == 0) {
// Input buffers is aligned to 8
mem_view = MemoryView::create_const(data, proto_stream_transfer_request.data().size());
} else {
// The memory is not aligned to 8, therefore we need to copy the data into a buffer
TRY(buffer, Buffer::create_shared(data, proto_stream_transfer_request.data().size(),
BufferStorageParams::create_dma()));
if (proto_stream_transfer_request.has_shared_memory_identifier()) {
TRY(buffer, Buffer::create_shared(proto_stream_transfer_request.shared_memory_identifier().size(),
BufferStorageParams::open_shared_memory(proto_stream_transfer_request.shared_memory_identifier().name())));
mem_view = MemoryView(*buffer);
} else {
auto *data = reinterpret_cast<const uint8_t*>(proto_stream_transfer_request.data().c_str());
if (reinterpret_cast<size_t>(data) % HailoRTCommon::HW_DATA_ALIGNMENT == 0) {
// Input buffers is aligned to 8
mem_view = MemoryView::create_const(data, proto_stream_transfer_request.data().size());
} else {
// The memory is not aligned to 8, therefore we need to copy the data into a buffer
TRY(buffer, Buffer::create_shared(data, proto_stream_transfer_request.data().size(),
BufferStorageParams::create_dma()));
mem_view = MemoryView(*buffer);
}
}
// Preparing callback
auto &stream_name = proto_stream_transfer_request.stream_name();
CHECK(stream_name != INVALID_STREAM_NAME, HAILO_INTERNAL_FAILURE, "Got invalid stream name");
auto cb_idx = proto_stream_transfer_request.cb_idx();
CHECK(cb_idx != INVALID_CB_INDEX, HAILO_INTERNAL_FAILURE, "Got invalid callback index");
std::function<void(hailo_status)> transfer_done = [this, vdevice_handle, ng_handle, cb_idx, stream_name, buffer, infer_async_request]
(hailo_status status)
{
@@ -493,18 +605,38 @@ hailo_status HailoRtRpcService::add_input_named_buffer(const ProtoTransferReques
hailo_status HailoRtRpcService::add_output_named_buffer(const ProtoTransferRequest &proto_stream_transfer_request, uint32_t vdevice_handle,
uint32_t ng_handle, NamedBuffersCallbacks &named_buffers_callbacks)
{
// Prepare output buffer
auto &stream_name = proto_stream_transfer_request.stream_name();
TRY(auto buffer, acquire_buffer_from_cng_pool(ng_handle, stream_name));
CHECK(stream_name != INVALID_STREAM_NAME, HAILO_INTERNAL_FAILURE, "Got invalid stream name");
// Prepare output buffer
BufferPtr buffer;
bool is_shared_mem = proto_stream_transfer_request.has_shared_memory_identifier();
auto shm_identifier = proto_stream_transfer_request.shared_memory_identifier();
if (is_shared_mem) {
TRY(buffer, Buffer::create_shared(shm_identifier.size(),
BufferStorageParams::open_shared_memory(shm_identifier.name())));
} else {
TRY(buffer, acquire_buffer_from_cng_pool(ng_handle, stream_name));
}
// Prepare callback
auto cb_idx = proto_stream_transfer_request.cb_idx();
std::function<void(hailo_status)> transfer_done = [this, vdevice_handle, ng_handle, cb_idx, stream_name, buffer]
CHECK(cb_idx != INVALID_CB_INDEX, HAILO_INTERNAL_FAILURE, "Got invalid callback index");
std::function<void(hailo_status)> transfer_done = [this, vdevice_handle, ng_handle, cb_idx, stream_name, buffer,
is_shared_mem, shm_identifier]
(hailo_status status)
{
auto cb_identifier = serialize_callback_identifier(vdevice_handle, ng_handle, CALLBACK_TYPE_TRANSFER,
stream_name, cb_idx, status, buffer);
return_buffer_to_cng_pool(ng_handle, stream_name, buffer);
ProtoCallbackIdentifier cb_identifier;
if (is_shared_mem) {
cb_identifier = serialize_callback_identifier_shm(vdevice_handle, ng_handle, CALLBACK_TYPE_TRANSFER,
stream_name, cb_idx, status, shm_identifier);
} else {
cb_identifier = serialize_callback_identifier(vdevice_handle, ng_handle, CALLBACK_TYPE_TRANSFER,
stream_name, cb_idx, status, buffer);
return_buffer_to_cng_pool(ng_handle, stream_name, buffer);
}
enqueue_cb_identifier(vdevice_handle, std::move(cb_identifier));
};
@@ -542,6 +674,9 @@ void HailoRtRpcService::enqueue_cb_identifier(uint32_t vdevice_handle, ProtoCall
auto &cb_queue_manager = ServiceResourceManager<VDeviceCallbacksQueue>::get_instance();
auto status = cb_queue_manager.execute(vdevice_handle, lambda, std::move(cb_identifier));
if (HAILO_SHUTDOWN_EVENT_SIGNALED != status) {
LOGGER__TRACE("Failed to enqueue callback to VDeviceCallbacksQueue '{}' because it is shutdown", vdevice_handle);
}
if (status != HAILO_SUCCESS) {
LOGGER__ERROR("Failed to enqueue callback to VDeviceCallbacksQueue with status={}", status);
}
@@ -1323,6 +1458,7 @@ grpc::Status HailoRtRpcService::InputVStreams_create(grpc::ServerContext *, cons
auto &vstreams_manager = ServiceResourceManager<InputVStream>::get_instance();
for (size_t i = 0; i < vstreams.size(); i++) {
reply->add_names(vstreams[i].name());
auto handle = vstreams_manager.register_resource(client_pid, make_shared_nothrow<InputVStream>(std::move(vstreams[i])));
reply->add_handles(handle);
}
@@ -1388,7 +1524,7 @@ grpc::Status HailoRtRpcService::OutputVStreams_create(grpc::ServerContext *, con
vstreams[i].get_frame_size(), output_params.at(vstreams[i].name()).queue_size);
};
CHECK_SUCCESS_AS_RPC_STATUS(cng_buffer_pool_manager.execute(network_group_handle, allocate_lambda), reply);
reply->add_names(vstreams[i].name());
auto handle = vstream_manager.register_resource(client_pid, make_shared_nothrow<OutputVStream>(std::move(vstreams[i])));
reply->add_handles(handle);
}

View File

@@ -227,6 +227,7 @@ private:
hailo_status abort_input_vstream(uint32_t handle);
hailo_status abort_output_vstream(uint32_t handle);
void abort_vstreams_by_pids(std::set<uint32_t> &pids);
void release_configured_network_groups_by_pid(uint32_t client_pid);
void remove_disconnected_clients();
void update_client_id_timestamp(uint32_t pid);
Expected<size_t> get_min_buffer_pool_size(uint32_t ng_handle);
@@ -247,6 +248,12 @@ private:
Expected<BufferPtr> acquire_buffer_from_cng_pool(uint32_t ng_handle, const std::string &output_name);
Expected<size_t> output_vstream_frame_size(uint32_t vstream_handle);
hailo_status update_buffer_size_in_pool(uint32_t vstream_handle, uint32_t network_group_handle);
void shutdown_configured_network_groups_by_pids(std::set<uint32_t> &pids);
void shutdown_buffer_pool_by_pids(std::set<uint32_t> &pids);
void shutdown_vdevice_cb_queue_by_pids(std::set<uint32_t> &pids);
hailo_status shutdown_cng_buffer_pool(uint32_t network_group_handle);
hailo_status shutdown_vdevice_cb_queue(uint32_t vdevice_handle);
hailo_status shutdown_configured_network_group(uint32_t vdevice_handle);
std::mutex m_keep_alive_mutex;
std::map<uint32_t, std::chrono::time_point<std::chrono::high_resolution_clock>> m_clients_pids;

View File

@@ -8,5 +8,8 @@
[Service]
HAILORT_LOGGER_PATH="/var/log/hailo"
HAILORT_LOGGER_FLUSH_EVERY_PRINT=0
HAILO_MONITOR=0
HAILO_TRACE=0
HAILO_TRACE_TIME_IN_SECONDS_BOUNDED_DUMP=0
HAILO_TRACE_SIZE_IN_KB_BOUNDED_DUMP=0
HAILO_TRACE_PATH=""

View File

@@ -83,6 +83,13 @@ public:
return index;
}
// For cases where other resources are already registered and we want to align the indexes
void advance_current_handle_index()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_current_handle_index++;
}
Expected<uint32_t> dup_handle(uint32_t handle, uint32_t pid)
{
std::unique_lock<std::mutex> lock(m_mutex);

View File

@@ -30,28 +30,30 @@
#include <syslog.h>
#include <sys/stat.h>
void RunService() {
const std::string server_address = hailort::HAILORT_SERVICE_ADDRESS;
hailort::HailoRtRpcService service;
using namespace hailort;
void RunService()
{
const std::string server_address = HAILORT_SERVICE_ADDRESS;
HailoRtRpcService service;
grpc::ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.SetMaxReceiveMessageSize(-1);
builder.RegisterService(&service);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
chmod(hailort::HAILO_DEFAULT_SERVICE_ADDR.c_str(), S_IROTH | S_IWOTH | S_IRUSR | S_IWUSR);
chmod(HAILO_DEFAULT_SERVICE_ADDR.c_str(), S_IROTH | S_IWOTH | S_IRUSR | S_IWUSR);
server->Wait();
}
void write_pid_to_lock_file()
{
auto status = hailort::Filesystem::create_directory(HAILO_DAEMON_PID_DIR);
auto status = Filesystem::create_directory(HAILO_DAEMON_PID_DIR);
if (status != HAILO_SUCCESS) {
HAILORT_OS_LOG_ERROR("Cannot create directory at path, status={}", status);
return;
}
auto locked_file = hailort::LockedFile::create(HAILO_DAEMON_PID_FILE, "wx");
auto locked_file = LockedFile::create(HAILO_DAEMON_PID_FILE, "wx");
if (HAILO_SUCCESS != locked_file.status()) {
HAILORT_OS_LOG_ERROR("Failed to lock pid file for hailort service, status={}", locked_file.status());
return;

View File

@@ -17,7 +17,7 @@
#include "hailo/hailort.h"
#include "hailo/network_group.hpp"
#include "hailo/hailort_common.hpp"
#include "utils/thread_safe_queue.hpp"
#include "common/thread_safe_queue.hpp"
namespace hailort
{
@@ -27,6 +27,11 @@ namespace hailort
class VDeviceCallbacksQueue final
{
public:
~VDeviceCallbacksQueue()
{
shutdown();
};
static Expected<std::unique_ptr<VDeviceCallbacksQueue>> create(uint32_t max_queue_size)
{
TRY(auto shutdown_event, Event::create_shared(Event::State::not_signalled));
@@ -48,6 +53,9 @@ public:
{
std::unique_lock<std::mutex> lock(m_mutex);
auto status = m_callbacks_ids_queue.enqueue(std::move(callback_id));
if (HAILO_SHUTDOWN_EVENT_SIGNALED == status) {
return status;
}
CHECK_SUCCESS(status);
return HAILO_SUCCESS;

View File

@@ -29,12 +29,15 @@
#include "hailort_rpc_service.hpp"
#include "rpc/rpc_definitions.hpp"
#include "common/os_utils.hpp"
#include "common/os/windows/named_mutex_guard.hpp"
#include <winsvc.h>
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
using namespace hailort;
#define SERVICE_NAME ("hailort_service")
static const DWORD HRT_SERVICE_INIT_WAIT_TIME_MS(3000);
static const DWORD HRT_SERVICE_ZERO_WAIT_TIME_MS(0);
@@ -46,9 +49,16 @@ std::unique_ptr<grpc::Server> g_hailort_rpc_server = nullptr;
void RunService()
{
const std::string server_address = hailort::HAILORT_SERVICE_ADDRESS;
hailort::HailoRtRpcService service;
// Create a named mutex
auto service_named_mutex = NamedMutexGuard::create(HAILORT_SERVICE_NAMED_MUTEX);
if (HAILO_SUCCESS != service_named_mutex.status()) {
LOGGER__ERROR("Failed to create service named mutex with status={}. Please check if another instance is already running.",
service_named_mutex.status());
return;
}
const std::string server_address = HAILORT_SERVICE_ADDRESS;
HailoRtRpcService service;
grpc::ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.SetMaxReceiveMessageSize(-1);

View File

@@ -8,3 +8,8 @@
reg ADD HKLM\SYSTEM\CurrentControlSet\Services\hailort_service /f /v Environment /t REG_MULTI_SZ /d ^
HAILORT_LOGGER_PATH="%PROGRAMDATA%\HailoRT_Service\logs"\0^
HAILO_TRACE=0\0^
HAILO_TRACE_TIME_IN_SECONDS_BOUNDED_DUMP=0\0^
HAILO_TRACE_SIZE_IN_KB_BOUNDED_DUMP=0\0^
HAILO_TRACE_PATH=""\0
@REM TODO: HRT-7304 - Add `HAILO_MONITOR`

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
include(GNUInstallDirs)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/cli11.cmake)
@@ -65,7 +65,11 @@ add_executable(hailortcli
target_compile_options(hailortcli PRIVATE ${HAILORT_COMPILE_OPTIONS})
set_property(TARGET hailortcli PROPERTY CXX_STANDARD 14)
set_property(TARGET hailortcli PROPERTY INSTALL_RPATH "$ORIGIN" "../lib/") # Link with a relative libhailort
# Link with a relative libhailort
set_property(TARGET hailortcli PROPERTY INSTALL_RPATH "$ORIGIN")
set_property(TARGET hailortcli APPEND PROPERTY INSTALL_RPATH "\$ORIGIN/../lib/")
target_link_libraries(hailortcli
libhailort
CLI11::CLI11
@@ -82,7 +86,10 @@ if(WIN32)
elseif(CMAKE_SYSTEM_NAME STREQUAL QNX)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/pevents.cmake)
target_link_libraries(hailortcli pevents)
elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Android)
target_link_libraries(hailortcli rt)
endif()
target_include_directories(hailortcli
PRIVATE
${CMAKE_CURRENT_BINARY_DIR} # CMAKE_CURRENT_BINARY_DIR is necessary for config_definitions_header

View File

@@ -8,6 +8,7 @@
**/
#include "benchmark_command.hpp"
#include "CLI/App.hpp"
#include "hailortcli.hpp"
#include "infer_stats_printer.hpp"
@@ -30,8 +31,8 @@ BenchmarkCommand::BenchmarkCommand(CLI::App &parent_app) :
m_app->add_option("-t, --time-to-run", m_params.time_to_run, "Measurement time in seconds per hw_only/streaming/latency measurement mode")
->check(CLI::PositiveNumber)
->default_val(15);
m_app->add_option("--no-power", m_not_measure_power, "Skip power measurement, even if the platform supports it. The default value is False")
->default_val("false");
auto no_power_opt = m_app->add_option("--no-power", m_not_measure_power, "Skip power measurement, even if the platform supports it. The default value is False");
hailo_deprecate_options(m_app, { std::make_shared<OptionDeprecation>(no_power_opt) }, false);
m_app->add_option("--batch-size", m_params.batch_size, "Inference batch size (default is 1)")
->default_val(1);
m_app->add_option("--power-mode", m_params.power_mode,
@@ -64,15 +65,15 @@ hailo_status BenchmarkCommand::execute()
{
std::cout << "Starting Measurements..." << std::endl;
std::cout << "Measuring FPS in hw_only mode" << std::endl;
TRY(auto hw_only_mode_info, hw_only_mode(), "hw_only measuring failed");
std::cout << "Measuring FPS in HW-only mode" << std::endl;
TRY(auto hw_only_mode_info, hw_only_mode(), "Measuring FPS in HW-only mode failed");
std::cout << "Measuring FPS " << (!m_not_measure_power ? "and Power " : "") << "in streaming mode" << std::endl;
TRY(auto streaming_mode_info, fps_streaming_mode(), "FPS in streaming mode failed");
std::cout << "Measuring FPS (and Power on supported platforms) in streaming mode" << std::endl;
TRY(auto streaming_mode_info, fps_streaming_mode(), "Measuring FPS (and Power on supported platforms) in streaming mode failed");
// TODO - HRT-6931 - measure latency only in the case of single device.
std::cout << "Measuring HW Latency" << std::endl;
TRY(auto latency_info, latency(), "Latency measuring failed");
TRY(auto latency_info, latency(), "Measuring Latency failed");
assert(hw_only_mode_info.network_group_results().size() == streaming_mode_info.network_group_results().size());
assert(latency_info.network_group_results().size() == streaming_mode_info.network_group_results().size());
@@ -101,7 +102,7 @@ hailo_status BenchmarkCommand::execute()
std::cout << " (overall) = " << InferStatsPrinter::latency_result_to_ms(overall_latency.value()) << " ms" << std::endl;
}
}
if (!m_not_measure_power) {
if (streaming_mode_info.power_measurements_are_valid) {
for (const auto &pair : streaming_mode_info.m_power_measurements) {
std::cout << "Device " << pair.first << ":" << std::endl;
const auto &data = pair.second->data();
@@ -123,7 +124,7 @@ hailo_status BenchmarkCommand::execute()
Expected<InferResult> BenchmarkCommand::hw_only_mode()
{
m_params.transform.transform = (m_params.inputs_name_and_file_path.size() > 0);
m_params.power_measurement.measure_power = false;
m_params.power_measurement.measure_power = ShouldMeasurePower::NO;
m_params.measure_latency = false;
m_params.mode = InferMode::HW_ONLY;
return run_command_hef(m_params);
@@ -131,7 +132,7 @@ Expected<InferResult> BenchmarkCommand::hw_only_mode()
Expected<InferResult> BenchmarkCommand::fps_streaming_mode()
{
m_params.power_measurement.measure_power = !m_not_measure_power;
m_params.power_measurement.measure_power = ShouldMeasurePower::AUTO_DETECT;
m_params.mode = InferMode::STREAMING;
m_params.measure_latency = false;
m_params.transform.transform = true;
@@ -141,7 +142,7 @@ Expected<InferResult> BenchmarkCommand::fps_streaming_mode()
Expected<InferResult> BenchmarkCommand::latency()
{
m_params.power_measurement.measure_power = false;
m_params.power_measurement.measure_power = ShouldMeasurePower::NO;
m_params.measure_latency = true;
m_params.mode = InferMode::STREAMING;
m_params.transform.transform = true;

View File

@@ -15,9 +15,6 @@
BoardConfigCommand::BoardConfigCommand(CLI::App &parent_app) :
ContainerCommand(parent_app.add_subcommand("board-config", "Board configuration tool"))
{
// This will make the board-config command to be hidden in the --help print in the command line.
m_app->group("");
add_subcommand<BoardConfigReadSubcommand>();
add_subcommand<BoardConfigWriteSubcommand>();
}

View File

@@ -44,11 +44,11 @@ public:
protected:
template<typename CommandType>
CommandType &add_subcommand(bool hidden = false)
CommandType &add_subcommand(OptionVisibility visibility = OptionVisibility::VISIBLE)
{
// Unnamed "option groups" hide subcommands/options from the help message
// (see https://github.com/CLIUtils/CLI11/blob/main/README.md)
auto *parent = hidden ? m_app->add_option_group("") : m_app;
auto *parent = (visibility == OptionVisibility::HIDDEN) ? m_app->add_option_group("") : m_app;
auto command = std::make_shared<CommandType>(*parent);
m_subcommands.push_back(command);
return *command;

View File

@@ -362,6 +362,14 @@ Expected<ordered_json> DownloadActionListCommand::parse_action_data(uint32_t bas
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__resume_vdma_channel_action_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__resume_vdma_channel_action_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_SLEEP:
data_json = *reinterpret_cast<CONTEXT_SWITCH_DEFS__sleep_action_data_t *>(action);
action_length_local = sizeof(CONTEXT_SWITCH_DEFS__sleep_action_data_t);
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_HALT:
data_json = json({});
action_length_local = 0;
break;
case CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT:
// Fallthrough
// Handling CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT is needed because we compile this file with -Wswitch-enum
@@ -413,9 +421,10 @@ Expected<ordered_json> DownloadActionListCommand::parse_context(Device &device,
uint8_t converted_context_type = static_cast<uint8_t>(context_type);
uint32_t action_list_base_address = 0;
uint32_t batch_counter = 0;
uint32_t idle_time = 0;
TRY(auto action_list, device.download_context_action_list(network_group_id, converted_context_type, context_index,
&action_list_base_address, &batch_counter));
&action_list_base_address, &batch_counter, &idle_time));
// Needs to fit in 2 bytes due to firmware limitation of action list size
CHECK_AS_EXPECTED(IS_FIT_IN_UINT16(action_list.size()), HAILO_INTERNAL_FAILURE,
"Action list size is expected to fit in 2B. actual size is {}", action_list.size());
@@ -424,6 +433,7 @@ Expected<ordered_json> DownloadActionListCommand::parse_context(Device &device,
{"action_list_base_address", action_list_base_address},
{"action_list_size", action_list.size() },
{"batch_counter", batch_counter},
{"idle_time", idle_time},
{"context_name", context_name},
};

View File

@@ -25,6 +25,7 @@ using ordered_json = nlohmann::ordered_json;
class DownloadActionListCommand : public DeviceCommand
{
public:
using DeviceCommand::execute;
explicit DownloadActionListCommand(CLI::App &parent_app);
// To be used from external commands
static hailo_status execute(Device &device, const std::string &output_file_path,
@@ -115,6 +116,8 @@ static std::pair<CONTEXT_SWITCH_DEFS__ACTION_TYPE_t, std::string> mapping[] = {
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_CHANGE_BOUNDARY_INPUT_BATCH, "change boundary input batch"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_PAUSE_VDMA_CHANNEL, "pause vdma channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_RESUME_VDMA_CHANNEL, "resume vdma channel"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_SLEEP, "sleep"},
{CONTEXT_SWITCH_DEFS__ACTION_TYPE_HALT, "halt"},
};
static_assert(ARRAY_ENTRIES(mapping) == CONTEXT_SWITCH_DEFS__ACTION_TYPE_COUNT,
"Missing a mapping from a CONTEXT_SWITCH_DEFS__ACTION_TYPE_t to it's string value");
@@ -130,6 +133,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__module_config_done_inter
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__fetch_ccw_bursts_action_data_t, config_stream_index, ccw_bursts);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__enable_nms_action_t, nms_unit_index, network_index, number_of_classes, burst_size);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__write_data_by_type_action_t, address, data_type, data, shift, mask, network_index);
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CONTEXT_SWITCH_DEFS__sleep_action_data_t, sleep_time);
// Non-default implementations
void to_json(json &j, const CONTEXT_SWITCH_DEFS__deactivate_vdma_channel_action_data_t &data);

View File

@@ -197,7 +197,7 @@ FwControlResetCommand::FwControlResetCommand(CLI::App &parent_app) :
m_app->add_option("--reset-type", m_reset_mode, "Reset type")
->required()
->transform(HailoCheckedTransformer<hailo_reset_device_mode_t>({
{ "chip", HAILO_RESET_DEVICE_MODE_CHIP },
{ "chip", HAILO_RESET_DEVICE_MODE_CHIP },
{ "nn_core", HAILO_RESET_DEVICE_MODE_NN_CORE },
{ "soft", HAILO_RESET_DEVICE_MODE_SOFT },
{ "forced_soft", HAILO_RESET_DEVICE_MODE_FORCED_SOFT },
@@ -226,11 +226,31 @@ hailo_status FwControlTestMemoriesCommand::execute_on_device(Device &device)
return HAILO_SUCCESS;
}
FwControlDebugHaltContinueCommand::FwControlDebugHaltContinueCommand(CLI::App &parent_app) :
DeviceCommand(parent_app.add_subcommand("continue", "Continue breakpoint action"))
{}
hailo_status FwControlDebugHaltContinueCommand::execute_on_device(Device &device)
{
auto status = device.continue_context_switch_breakpoint(0);
CHECK_SUCCESS(status, "Failed to excute debug operation");
std::cout << "Control Operation Debug Continue completed successfully" << std::endl;
return HAILO_SUCCESS;
}
FwControlDebugCommand::FwControlDebugCommand(CLI::App &parent_app) :
ContainerCommand(parent_app.add_subcommand("debug", "Access to usefull debug operations"))
{
add_subcommand<FwControlDebugHaltContinueCommand>();
}
FwControlCommand::FwControlCommand(CLI::App &parent_app) :
ContainerCommand(parent_app.add_subcommand("fw-control", "Useful firmware control operations"))
{
add_subcommand<FwControlIdentifyCommand>();
add_subcommand<FwControlResetCommand>();
add_subcommand<FwControlTestMemoriesCommand>();
add_subcommand<DownloadActionListCommand>();
add_subcommand<FwControlResetCommand>(OptionVisibility::HIDDEN);
add_subcommand<FwControlTestMemoriesCommand>(OptionVisibility::HIDDEN);
add_subcommand<DownloadActionListCommand>(OptionVisibility::HIDDEN);
add_subcommand<FwControlDebugCommand>(OptionVisibility::HIDDEN);
}

View File

@@ -44,6 +44,19 @@ protected:
virtual hailo_status execute_on_device(Device &device) override;
};
class FwControlDebugHaltContinueCommand : public DeviceCommand {
public:
explicit FwControlDebugHaltContinueCommand(CLI::App &parent_app);
protected:
virtual hailo_status execute_on_device(Device &device) override;
};
class FwControlDebugCommand : public ContainerCommand {
public:
explicit FwControlDebugCommand(CLI::App &parent_app);
};
class FwControlCommand : public ContainerCommand {
public:
explicit FwControlCommand(CLI::App &parent_app);

View File

@@ -190,7 +190,7 @@ public:
add_subcommand<BenchmarkCommand>();
add_subcommand<PowerMeasurementSubcommand>();
add_subcommand<SensorConfigCommand>();
add_subcommand<BoardConfigCommand>();
add_subcommand<BoardConfigCommand>(OptionVisibility::HIDDEN);
add_subcommand<FwConfigCommand>();
add_subcommand<FwLoggerCommand>();
add_subcommand<FwUpdateCommand>();
@@ -198,7 +198,7 @@ public:
add_subcommand<MonCommand>();
#if defined(__GNUC__)
add_subcommand<UdpRateLimiterCommand>();
add_subcommand<HwInferEstimatorCommand>();
add_subcommand<HwInferEstimatorCommand>(OptionVisibility::HIDDEN);
#endif
add_subcommand<ParseHefCommand>();
add_subcommand<FwControlCommand>();

View File

@@ -342,6 +342,7 @@ public:
std::map<std::string, std::shared_ptr<LongPowerMeasurement>> m_power_measurements;
std::map<std::string, std::shared_ptr<LongPowerMeasurement>> m_current_measurements;
std::map<std::string, std::shared_ptr<AccumulatorResults>> m_temp_measurements;
bool power_measurements_are_valid = false;
private:
std::vector<NetworkGroupInferResult> m_network_group_results;

View File

@@ -16,6 +16,8 @@
#include "hailo/vstream.hpp"
#include "hailo/vdevice.hpp"
#include "common/internal_env_vars.hpp"
#include <iostream>
#define BYTES_TO_KILOBYTES (1024)
@@ -25,9 +27,6 @@ HwInferEstimatorCommand::HwInferEstimatorCommand(CLI::App &parent_app) :
"measure nerual network performance for given network using only the HW components without host SW")),
m_params({})
{
// This will make the command to be hidden in the --help print in the command line.
m_app->group("");
add_vdevice_options(m_app, m_params.vdevice_params);
m_app->add_option("hef", m_params.hef_path, "Path of the HEF to load")
->check(CLI::ExistingFile)
@@ -81,10 +80,10 @@ hailo_status HwInferEstimatorCommand::execute()
TRY(auto configure_params, get_configure_params(m_params, hef, interface));
/* Use Env var to configure all desc list with max depth */
setenv("HAILO_CONFIGURE_FOR_HW_INFER","Y",1);
setenv(HAILO_CONFIGURE_FOR_HW_INFER_ENV_VAR,"Y",1);
TRY(auto network_group_list,
device->configure(hef, configure_params), "Failed configure device from hef");
unsetenv("HAILO_CONFIGURE_FOR_HW_INFER");
unsetenv(HAILO_CONFIGURE_FOR_HW_INFER_ENV_VAR);
CHECK(1 == network_group_list.size(), HAILO_INVALID_OPERATION,
"HW Inference is not supported on HEFs with multiple network groups");

View File

@@ -10,6 +10,7 @@
#include "hailo/hailort.h"
#include "common/filesystem.hpp"
#include "common/env_vars.hpp"
#include "mon_command.hpp"
#include "common.hpp"

View File

@@ -138,67 +138,78 @@ Expected<std::string> NetworkRunner::get_network_group_name(const NetworkParams
Expected<std::shared_ptr<FullAsyncNetworkRunner>> FullAsyncNetworkRunner::create_shared(VDevice &vdevice,
NetworkParams params)
{
TRY(auto infer_model_ptr, vdevice.create_infer_model(params.hef_path));
TRY(auto net_group_name, get_network_group_name(params, infer_model_ptr->hef()));
std::string net_group_name = params.net_group_name;
if (net_group_name.empty()) {
TRY(auto hef, Hef::create(params.hef_path));
TRY(net_group_name, get_network_group_name(params, hef));
}
TRY(auto infer_model_ptr, vdevice.create_infer_model(params.hef_path, net_group_name));
/* Configure Params */
infer_model_ptr->set_batch_size(params.batch_size);
if (params.batch_size == HAILO_DEFAULT_BATCH_SIZE) {
// Changing batch_size to 1 (after configuring the vdevice) - as we iterate over 'params.batch_size' in latency measurements scenarios
params.batch_size = 1;
}
if (params.measure_hw_latency) {
infer_model_ptr->set_hw_latency_measurement_flags(HAILO_LATENCY_MEASURE);
/* Validate params */
for (const auto &vstream_params : params.vstream_params) {
CHECK_AS_EXPECTED((contains(infer_model_ptr->get_input_names(), vstream_params.name)) ||
(contains(infer_model_ptr->get_output_names(), vstream_params.name)),
HAILO_INVALID_ARGUMENT, "The model doesnt have an edge with the given name '{}'", vstream_params.name);
}
/* Configure Params */
infer_model_ptr->set_batch_size(params.batch_size);
if (params.batch_size == HAILO_DEFAULT_BATCH_SIZE) {
// Changing batch_size to 1 (after configuring the vdevice) - as we iterate over 'params.batch_size' in latency measurements scenarios
params.batch_size = 1;
}
if (params.measure_hw_latency) {
infer_model_ptr->set_hw_latency_measurement_flags(HAILO_LATENCY_MEASURE);
}
/* Pipeline Params */
for (const auto &input_name : infer_model_ptr->get_input_names()) {
auto input_params_it = std::find_if(params.vstream_params.begin(), params.vstream_params.end(),
[&input_name](const VStreamParams &params) -> bool {
return params.name == input_name;
});
auto input_params = (input_params_it == params.vstream_params.end()) ? VStreamParams() : *input_params_it;
TRY(auto input_config, infer_model_ptr->input(input_name));
input_config.set_format_order(input_params.params.user_buffer_format.order);
input_config.set_format_type(input_params.params.user_buffer_format.type);
}
for (const auto &output_name : infer_model_ptr->get_output_names()) {
auto output_params_it = std::find_if(params.vstream_params.begin(), params.vstream_params.end(),
[&output_name](const VStreamParams &params) -> bool {
return params.name == output_name;
});
auto output_params = (output_params_it == params.vstream_params.end()) ? VStreamParams() : *output_params_it;
TRY(auto output_config, infer_model_ptr->output(output_name));
output_config.set_format_order(output_params.params.user_buffer_format.order);
output_config.set_format_type(output_params.params.user_buffer_format.type);
}
TRY(auto configured_model, infer_model_ptr->configure());
auto configured_infer_model_ptr = make_shared_nothrow<ConfiguredInferModel>(std::move(configured_model));
CHECK_NOT_NULL_AS_EXPECTED(configured_infer_model_ptr, HAILO_OUT_OF_HOST_MEMORY);
auto res = make_shared_nothrow<FullAsyncNetworkRunner>(params, net_group_name, vdevice,
infer_model_ptr, configured_infer_model_ptr);
CHECK_NOT_NULL_AS_EXPECTED(res, HAILO_OUT_OF_HOST_MEMORY);
if (params.measure_overall_latency || params.measure_hw_latency) {
CHECK_AS_EXPECTED((1 == res->get_input_names().size()), HAILO_INVALID_OPERATION,
"Latency measurement over multiple inputs network is not supported");
if (params.measure_overall_latency) {
auto overall_latency_meter = make_shared_nothrow<LatencyMeter>(std::set<std::string>{ "INFERENCE" }, // Since we check 'infer()' with single callback, we only address 1 output
OVERALL_LATENCY_TIMESTAMPS_LIST_LENGTH);
CHECK_NOT_NULL_AS_EXPECTED(overall_latency_meter, HAILO_OUT_OF_HOST_MEMORY);
res->set_overall_latency_meter(overall_latency_meter);
}
/* Pipeline Params */
for (const auto &input_name : infer_model_ptr->get_input_names()) {
auto input_params_it = std::find_if(params.vstream_params.begin(), params.vstream_params.end(),
[&input_name](const VStreamParams &params) -> bool {
return params.name == input_name;
});
auto input_params = (input_params_it == params.vstream_params.end()) ? VStreamParams() : *input_params_it;
TRY(auto input_config, infer_model_ptr->input(input_name));
input_config.set_format_order(input_params.params.user_buffer_format.order);
input_config.set_format_type(input_params.params.user_buffer_format.type);
}
for (const auto &output_name : infer_model_ptr->get_output_names()) {
auto output_params_it = std::find_if(params.vstream_params.begin(), params.vstream_params.end(),
[&output_name](const VStreamParams &params) -> bool {
return params.name == output_name;
});
auto output_params = (output_params_it == params.vstream_params.end()) ? VStreamParams() : *output_params_it;
TRY(auto output_config, infer_model_ptr->output(output_name));
output_config.set_format_order(output_params.params.user_buffer_format.order);
output_config.set_format_type(output_params.params.user_buffer_format.type);
}
TRY(auto configured_model, infer_model_ptr->configure());
auto configured_infer_model_ptr = make_shared_nothrow<ConfiguredInferModel>(std::move(configured_model));
CHECK_NOT_NULL_AS_EXPECTED(configured_infer_model_ptr, HAILO_OUT_OF_HOST_MEMORY);
auto res = make_shared_nothrow<FullAsyncNetworkRunner>(params, net_group_name, vdevice,
infer_model_ptr, configured_infer_model_ptr);
CHECK_NOT_NULL_AS_EXPECTED(res, HAILO_OUT_OF_HOST_MEMORY);
if (params.measure_overall_latency || params.measure_hw_latency) {
CHECK_AS_EXPECTED((1 == res->get_input_names().size()), HAILO_INVALID_OPERATION,
"Latency measurement over multiple inputs network is not supported");
if (params.measure_overall_latency) {
auto overall_latency_meter = make_shared_nothrow<LatencyMeter>(std::set<std::string>{ "INFERENCE" }, // Since we check 'infer()' with single callback, we only address 1 output
OVERALL_LATENCY_TIMESTAMPS_LIST_LENGTH);
CHECK_NOT_NULL_AS_EXPECTED(overall_latency_meter, HAILO_OUT_OF_HOST_MEMORY);
res->set_overall_latency_meter(overall_latency_meter);
}
// We use a barrier for both hw and overall latency
auto latency_barrier = make_shared_nothrow<Barrier>(1); // Only 1 frame at a time
CHECK_NOT_NULL_AS_EXPECTED(latency_barrier, HAILO_OUT_OF_HOST_MEMORY);
res->set_latency_barrier(latency_barrier);
}
// We use a barrier for both hw and overall latency
auto latency_barrier = make_shared_nothrow<Barrier>(1); // Only 1 frame at a time
CHECK_NOT_NULL_AS_EXPECTED(latency_barrier, HAILO_OUT_OF_HOST_MEMORY);
res->set_latency_barrier(latency_barrier);
}
return res;
}
@@ -263,6 +274,14 @@ Expected<std::shared_ptr<NetworkRunner>> NetworkRunner::create_shared(VDevice &v
auto output_streams = cfgr_net_group->get_output_streams();
CHECK_AS_EXPECTED(output_streams.size() > 0, HAILO_INTERNAL_FAILURE);
/* Validate params */
for (const auto &stream_param : final_net_params.stream_params) {
CHECK_AS_EXPECTED(
(std::any_of(input_streams.begin(), input_streams.end(), [name = stream_param.name] (const auto &stream) { return name == stream.get().name(); })) ||
(std::any_of(output_streams.begin(), output_streams.end(), [name = stream_param.name] (const auto &stream) { return name == stream.get().name(); })),
HAILO_INVALID_ARGUMENT, "The model doesnt have an edge with the given name '{}'", stream_param.name);
}
auto net_runner = make_shared_nothrow<RawNetworkRunner>(final_net_params, net_group_name, vdevice,
std::move(input_streams), std::move(output_streams), cfgr_net_group);
CHECK_NOT_NULL_AS_EXPECTED(net_runner, HAILO_OUT_OF_HOST_MEMORY);
@@ -370,13 +389,20 @@ double NetworkRunner::get_last_measured_fps()
Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> NetworkRunner::create_vstreams(
ConfiguredNetworkGroup &net_group, const std::map<std::string, hailo_vstream_params_t> &params)
{//TODO: support network name
size_t match_count = 0;
/* Validate params */
TRY(auto input_vstreams_info, net_group.get_input_vstream_infos());
TRY(auto output_vstreams_info, net_group.get_output_vstream_infos());
for (const auto &pair : params) {
CHECK_AS_EXPECTED(
(std::any_of(input_vstreams_info.begin(), input_vstreams_info.end(), [name = pair.first] (const auto &info) { return name == std::string(info.name); })) ||
(std::any_of(output_vstreams_info.begin(), output_vstreams_info.end(), [name = pair.first] (const auto &info) { return name == std::string(info.name); })),
HAILO_INVALID_ARGUMENT, "The model doesnt have an edge with the given name '{}'", pair.first);
}
std::map<std::string, hailo_vstream_params_t> input_vstreams_params;
TRY(auto input_vstreams_info, net_group.get_input_vstream_infos());
for (auto &input_vstream_info : input_vstreams_info) {
if (params.end() != params.find(input_vstream_info.name)) {
match_count++;
input_vstreams_params.emplace(input_vstream_info.name, params.at(input_vstream_info.name));
} else {
input_vstreams_params.emplace(input_vstream_info.name, HailoRTDefaults::get_vstreams_params());
@@ -384,18 +410,14 @@ Expected<std::pair<std::vector<InputVStream>, std::vector<OutputVStream>>> Netwo
}
std::map<std::string, hailo_vstream_params_t> output_vstreams_params;
TRY(auto output_vstreams_info, net_group.get_output_vstream_infos());
for (auto &output_vstream_info : output_vstreams_info) {
if (params.end() != params.find(output_vstream_info.name)) {
match_count++;
output_vstreams_params.emplace(output_vstream_info.name, params.at(output_vstream_info.name));
} else {
output_vstreams_params.emplace(output_vstream_info.name, HailoRTDefaults::get_vstreams_params());
}
}
CHECK(match_count == params.size(), make_unexpected(HAILO_INVALID_ARGUMENT), "One of the params has an invalid vStream name");
TRY(auto input_vstreams, VStreamsBuilder::create_input_vstreams(net_group, input_vstreams_params));
TRY(auto output_vstreams, VStreamsBuilder::create_output_vstreams(net_group, output_vstreams_params));

View File

@@ -739,18 +739,15 @@ Expected<std::vector<std::shared_ptr<NetworkRunner>>> Run2::init_and_run_net_run
if (get_measure_power() || get_measure_current() || get_measure_temp()) {
TRY(auto physical_devices, vdevice->get_physical_devices());
for (auto &device : physical_devices) {
TRY(const auto identity, device.get().identify());
CHECK_AS_EXPECTED(HailoRTCommon::is_power_measurement_supported(identity.device_architecture) || !(get_measure_power()),
HAILO_INVALID_OPERATION, "HW arch {} does not support power measurement. Disable the power-measure option",
HailoRTCommon::get_device_arch_str(identity.device_architecture));
CHECK_AS_EXPECTED(HailoRTCommon::is_current_measurement_supported(identity.device_architecture) || !(get_measure_current()),
HAILO_INVALID_OPERATION, "HW arch {} does not support current measurement. Disable the current-measure option",
HailoRTCommon::get_device_arch_str(identity.device_architecture));
CHECK_AS_EXPECTED(HailoRTCommon::is_temp_measurement_supported(identity.device_architecture) || !(get_measure_temp()),
HAILO_INVALID_OPERATION, "HW arch {} does not support temperature measurement. Disable the temp-measure option",
HailoRTCommon::get_device_arch_str(identity.device_architecture));
TRY(auto caps, device.get().get_capabilities(), "Failed getting device capabilities");
CHECK_AS_EXPECTED((caps.power_measurements || (get_measure_power())),
HAILO_INVALID_OPERATION, "Power measurement not supported. Disable the power-measure option");
CHECK_AS_EXPECTED((caps.current_measurements || !(get_measure_current())),
HAILO_INVALID_OPERATION, "Current measurement not supported. Disable the current-measure option");
CHECK_AS_EXPECTED((caps.temperature_measurements || !(get_measure_temp())),
HAILO_INVALID_OPERATION, "Temperature measurement not supported. Disable the temp-measure option");
TRY(auto measurement_live_track, MeasurementLiveTrack::create_shared(device.get(),
get_measure_power(), get_measure_current(), get_measure_temp()));

View File

@@ -90,5 +90,4 @@ private:
NetworkParams m_params;
};
#endif /* _HAILO_HAILORTCLI_RUN2_RUN2_COMMAND_HPP_ */

View File

@@ -107,7 +107,7 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
// TODO: init values in RunCommand ctor
params.measure_latency = false;
params.measure_overall_latency = false;
params.power_measurement.measure_power = false;
params.power_measurement.measure_power = ShouldMeasurePower::NO;
params.power_measurement.measure_current = false;
params.show_progress = true;
params.time_to_run = 0;
@@ -167,8 +167,8 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
run_subcommand->add_option("--dot", params.dot_output,
"If set print the pipeline graph as a .dot file at the specified path")
->check(FileSuffixValidator(DOT_SUFFIX));
CLI::Option *measure_power_opt = run_subcommand->add_flag("--measure-power",
params.power_measurement.measure_power, "Measure power consumption");
auto measure_power_cb = [&params] (bool measure_power) { params.power_measurement.measure_power = measure_power ? ShouldMeasurePower::YES : ShouldMeasurePower::NO; };
CLI::Option *measure_power_opt = run_subcommand->add_flag( "--measure-power", measure_power_cb, "Measure power consumption");
CLI::Option *measure_current_opt = run_subcommand->add_flag("--measure-current",
params.power_measurement.measure_current, "Measure current")->excludes(measure_power_opt);
measure_power_opt->excludes(measure_current_opt);
@@ -271,7 +271,7 @@ static void add_run_command_params(CLI::App *run_subcommand, inference_runner_pa
"--batch-size should be a divisor of --frames-count if provided");
// TODO HRT-5363 support multiple devices
PARSE_CHECK((params.vdevice_params.device_count == 1) || params.csv_output.empty() ||
!(params.power_measurement.measure_power || params.power_measurement.measure_current || params.measure_temp),
!((ShouldMeasurePower::YES == params.power_measurement.measure_power) || params.power_measurement.measure_current || params.measure_temp),
"Writing measurements in csv format is not supported for multiple devices");
if ((0 == params.time_to_run) && (0 == params.frames_count)) {
@@ -1036,10 +1036,12 @@ Expected<InferResult> activate_and_run_single_device(
CHECK_AS_EXPECTED(1 == network_groups.size(), HAILO_INVALID_OPERATION, "Inference is not supported on HEFs with multiple network groups");
TRY(auto activated_net_group, network_groups[0]->activate(), "Failed activate network_group");
TRY(auto input_dataset, create_dataset(network_groups, params));
TRY(auto caps, device.get_capabilities());
hailo_power_measurement_types_t measurement_type = HAILO_POWER_MEASUREMENT_TYPES__MAX_ENUM;
bool should_measure_power = false;
if (params.power_measurement.measure_power) {
if ((ShouldMeasurePower::YES == params.power_measurement.measure_power) ||
((ShouldMeasurePower::AUTO_DETECT == params.power_measurement.measure_power) && caps.power_measurements)) {
measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
should_measure_power = true;
} else if (params.power_measurement.measure_current) {
@@ -1079,6 +1081,7 @@ Expected<InferResult> activate_and_run_single_device(
status = inference_result.set_power_measurement(device.get_dev_id(), std::move(long_power_measurement_ptr));
CHECK_SUCCESS_AS_EXPECTED(status);
}
inference_result.power_measurements_are_valid = true;
}
if (should_measure_temp) {
@@ -1157,10 +1160,20 @@ Expected<InferResult> activate_and_run_vdevice(
}
TRY(const auto input_dataset, create_dataset(network_groups, params), "Failed creating input dataset");
// we currently support all devices or none for power measurements
auto all_phy_devices_support_power_measurements = true;
for (const auto &device : physical_devices) {
TRY(const auto caps, device.get().get_capabilities(), "Failed getting device capabilities");
if (!caps.power_measurements) {
all_phy_devices_support_power_measurements = false;
break;
}
}
hailo_power_measurement_types_t measurement_type = HAILO_POWER_MEASUREMENT_TYPES__MAX_ENUM;
bool should_measure_power = false;
if (params.power_measurement.measure_power) {
if ((ShouldMeasurePower::YES == params.power_measurement.measure_power) ||
((ShouldMeasurePower::AUTO_DETECT == params.power_measurement.measure_power) && all_phy_devices_support_power_measurements)) {
measurement_type = HAILO_POWER_MEASUREMENT_TYPES__POWER;
should_measure_power = true;
} else if (params.power_measurement.measure_current) {
@@ -1215,6 +1228,7 @@ Expected<InferResult> activate_and_run_vdevice(
}
}
CHECK_SUCCESS_AS_EXPECTED(status);
inference_result.power_measurements_are_valid = true;
}
if (params.measure_temp) {
@@ -1261,23 +1275,18 @@ Expected<InferResult> run_command_hef_vdevice(const inference_runner_params &par
}
TRY(const auto interface, vdevice->get_default_streams_interface(), "Failed to get default streams interface");
TRY(auto configure_params, get_configure_params(params, hef, interface));
TRY(auto configure_params, get_configure_params(params, hef, interface), "Failed getting configure params");
TRY(auto network_group_list, vdevice->configure(hef, configure_params), "Failed configure vdevice from hef");
for (auto &device : physical_devices) {
TRY(const auto identity, device.get().identify());
CHECK_AS_EXPECTED((HailoRTCommon::is_power_measurement_supported(identity.device_architecture) ||
!(params.power_measurement.measure_power)), HAILO_INVALID_OPERATION,
"HW arch {} does not support power measurement. Disable the power-measure option",
HailoRTCommon::get_device_arch_str(identity.device_architecture));
CHECK_AS_EXPECTED((HailoRTCommon::is_current_measurement_supported(identity.device_architecture) ||
!(params.power_measurement.measure_current)), HAILO_INVALID_OPERATION,
"HW arch {} does not support current measurement. Disable the current-measure option",
HailoRTCommon::get_device_arch_str(identity.device_architecture));
CHECK_AS_EXPECTED((HailoRTCommon::is_temp_measurement_supported(identity.device_architecture) ||
!(params.measure_temp)), HAILO_INVALID_OPERATION,
"HW arch {} does not support temperature measurement. Disable the temp-measure option",
HailoRTCommon::get_device_arch_str(identity.device_architecture));
TRY(auto caps, device.get().get_capabilities(), "Failed getting device capabilities");
CHECK_AS_EXPECTED((caps.power_measurements || (params.power_measurement.measure_power != ShouldMeasurePower::YES)),
HAILO_INVALID_OPERATION, "Power measurement not supported. Disable the power-measure option");
CHECK_AS_EXPECTED((caps.current_measurements || !(params.power_measurement.measure_current)),
HAILO_INVALID_OPERATION, "Current measurement not supported. Disable the current-measure option");
CHECK_AS_EXPECTED((caps.temperature_measurements || !(params.measure_temp)),
HAILO_INVALID_OPERATION, "Temperature measurement not supported. Disable the temp-measure option");
if (use_batch_to_measure_opt(params)) {
status = DownloadActionListCommand::set_batch_to_measure(device.get(), params.runtime_data.batch_to_measure);

View File

@@ -30,7 +30,7 @@ struct transformation_params {
};
struct measure_power_params {
bool measure_power;
ShouldMeasurePower measure_power;
bool measure_current;
uint32_t sampling_period;
uint32_t averaging_factor;

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
set(HRPC_IMPL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/os")
if(WIN32)

View File

@@ -42,7 +42,7 @@ hailo_status ResultEvent::wait(std::chrono::milliseconds timeout)
Client::~Client()
{
is_running = false;
m_is_running = false;
(void)m_connection.close();
if (m_thread.joinable()) {
m_thread.join();
@@ -51,7 +51,7 @@ Client::~Client()
hailo_status Client::connect()
{
TRY(m_conn_context, ConnectionContext::create_shared(false));
TRY(m_conn_context, ConnectionContext::create_client_shared(m_device_id));
TRY(auto conn, RawConnection::create_shared(m_conn_context));
auto status = conn->connect();
CHECK_SUCCESS(status);
@@ -68,7 +68,7 @@ hailo_status Client::connect()
hailo_status Client::message_loop()
{
while (is_running) {
while (m_is_running) {
rpc_message_header_t header;
TRY_WITH_ACCEPTABLE_STATUS(HAILO_COMMUNICATION_CLOSED, auto message, m_connection.read_message(header));
@@ -80,9 +80,16 @@ hailo_status Client::message_loop()
continue;
}
std::unique_lock<std::mutex> lock(m_message_mutex);
auto event = m_events[header.message_id];
lock.unlock();
std::shared_ptr<ResultEvent> event = nullptr;
{
std::unique_lock<std::mutex> lock(m_events_mutex);
m_events_cv.wait(lock, [this, &header] () {
return contains(m_events, header.message_id);
});
event = m_events[header.message_id];
m_events.erase(header.message_id);
}
auto status = event->signal(std::move(message));
CHECK_SUCCESS(status);
}
@@ -93,27 +100,32 @@ hailo_status Client::message_loop()
Expected<Buffer> Client::execute_request(HailoRpcActionID action_id, const MemoryView &request,
std::function<hailo_status(RpcConnection)> write_buffers_callback)
{
std::unique_lock<std::mutex> lock(m_message_mutex);
rpc_message_header_t header;
header.size = static_cast<uint32_t>(request.size());
header.message_id = m_messages_sent++;
header.action_id = static_cast<uint32_t>(action_id);
{
std::unique_lock<std::mutex> lock(m_write_mutex);
header.size = static_cast<uint32_t>(request.size());
header.message_id = m_messages_sent++;
header.action_id = static_cast<uint32_t>(action_id);
auto status = m_connection.write_message(header, request);
CHECK_SUCCESS_AS_EXPECTED(status);
if (write_buffers_callback) {
status = write_buffers_callback(m_connection);
auto status = m_connection.write_message(header, request);
CHECK_SUCCESS_AS_EXPECTED(status);
if (write_buffers_callback) {
status = write_buffers_callback(m_connection);
CHECK_SUCCESS_AS_EXPECTED(status);
}
}
TRY(auto event, ResultEvent::create_shared());
m_events[header.message_id] = event;
std::shared_ptr<ResultEvent> event = nullptr;
{
std::unique_lock<std::mutex> events_lock(m_events_mutex);
TRY(event, ResultEvent::create_shared());
m_events[header.message_id] = event;
}
m_events_cv.notify_all();
lock.unlock();
status = event->wait(REQUEST_TIMEOUT);
auto status = event->wait(REQUEST_TIMEOUT);
CHECK_SUCCESS_AS_EXPECTED(status);
m_events.erase(header.message_id);
return event->release();
}

View File

@@ -42,7 +42,7 @@ private:
class Client
{
public:
Client() = default;
Client(const std::string &device_id) : m_device_id(device_id), m_is_running(true) {}
~Client();
hailo_status connect();
@@ -53,14 +53,17 @@ public:
protected:
hailo_status message_loop();
bool is_running = true;
std::string m_device_id;
bool m_is_running;
std::shared_ptr<ConnectionContext> m_conn_context;
RpcConnection m_connection;
std::thread m_thread;
std::unordered_map<uint32_t, std::shared_ptr<ResultEvent>> m_events;
std::unordered_map<HailoRpcActionID, std::function<hailo_status(const MemoryView&, RpcConnection)>> m_custom_callbacks;
uint32_t m_messages_sent = 0;
std::mutex m_message_mutex;
std::mutex m_write_mutex;
std::condition_variable m_events_cv;
std::mutex m_events_mutex;
};
} // namespace hrpc

View File

@@ -10,44 +10,59 @@
#include "hrpc/os/pcie/raw_connection_internal.hpp"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include "common/internal_env_vars.hpp"
#include "hailo/hailort.h"
#include "vdma/driver/hailort_driver.hpp"
// TODO: Remove this after we can choose ports in the driver
#define PCIE_PORT (1213355091)
#define DEFAULT_PCIE_PORT (12133)
uint16_t get_pcie_port()
{
auto port_str = get_env_variable(HAILO_CONNECTION_PCIE_PORT_ENV_VAR);
if (port_str) {
return static_cast<uint16_t>(std::stoi(port_str.value()));
}
return DEFAULT_PCIE_PORT;
}
using namespace hrpc;
Expected<std::shared_ptr<ConnectionContext>> PcieConnectionContext::create_shared(bool is_accepting)
Expected<std::shared_ptr<ConnectionContext>> PcieConnectionContext::create_client_shared(const std::string &device_id)
{
const auto max_size = PcieSession::max_transfer_size();
TRY(auto write_buffer, Buffer::create(static_cast<size_t>(max_size), BufferStorageParams::create_dma()));
TRY(auto read_buffer, Buffer::create(static_cast<size_t>(max_size), BufferStorageParams::create_dma()));
std::shared_ptr<PcieConnectionContext> ptr = nullptr;
if (is_accepting) {
// Server side
TRY(auto driver, HailoRTDriver::create_pcie_ep());
ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), is_accepting,
if (device_id.size() > 0) {
TRY(auto driver, HailoRTDriver::create_pcie(device_id));
auto ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), false,
std::move(write_buffer), std::move(read_buffer));
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
} else {
// Client side
TRY(auto device_infos, HailoRTDriver::scan_devices());
CHECK(device_infos.size() > 0, HAILO_NOT_FOUND, "No devices found");
for (auto &device_info : device_infos) {
if (HailoRTDriver::AcceleratorType::SOC_ACCELERATOR == device_info.accelerator_type) {
TRY(auto driver, HailoRTDriver::create(device_info.device_id, device_info.dev_path));
ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), is_accepting,
std::move(write_buffer), std::move(read_buffer));
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
}
}
LOGGER__ERROR("No suitable device found");
return make_unexpected(HAILO_NOT_FOUND);
TRY(auto device_infos, HailoRTDriver::scan_devices(HailoRTDriver::AcceleratorType::SOC_ACCELERATOR));
CHECK(device_infos.size() > 0, HAILO_NOT_FOUND, "No devices found");
TRY(auto driver, HailoRTDriver::create(device_infos[0].device_id, device_infos[0].dev_path));
auto ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), false,
std::move(write_buffer), std::move(read_buffer));
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
Expected<std::shared_ptr<ConnectionContext>> PcieConnectionContext::create_server_shared()
{
const auto max_size = PcieSession::max_transfer_size();
TRY(auto write_buffer, Buffer::create(static_cast<size_t>(max_size), BufferStorageParams::create_dma()));
TRY(auto read_buffer, Buffer::create(static_cast<size_t>(max_size), BufferStorageParams::create_dma()));
TRY(auto driver, HailoRTDriver::create_pcie_ep());
auto ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), true,
std::move(write_buffer), std::move(read_buffer));
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
hailo_status PcieConnectionContext::wait_for_available_connection()
@@ -86,7 +101,7 @@ Expected<std::shared_ptr<RawConnection>> PcieRawConnection::accept()
auto new_conn = make_shared_nothrow<PcieRawConnection>(m_context);
CHECK_NOT_NULL_AS_EXPECTED(new_conn, HAILO_OUT_OF_HOST_MEMORY);
TRY(auto session, PcieSession::accept(m_context->driver(), PCIE_PORT));
TRY(auto session, PcieSession::accept(m_context->driver(), get_pcie_port()));
status = new_conn->set_session(std::move(session));
CHECK_SUCCESS(status);
@@ -103,14 +118,14 @@ hailo_status PcieRawConnection::set_session(PcieSession &&session)
hailo_status PcieRawConnection::connect()
{
TRY(auto session, PcieSession::connect(m_context->driver(), PCIE_PORT));
TRY(auto session, PcieSession::connect(m_context->driver(), get_pcie_port()));
auto status = set_session(std::move(session));
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status PcieRawConnection::write(const uint8_t *buffer, size_t size)
hailo_status PcieRawConnection::write(const uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
if (0 == size) {
return HAILO_SUCCESS;
@@ -126,7 +141,7 @@ hailo_status PcieRawConnection::write(const uint8_t *buffer, size_t size)
auto size_left = size - bytes_written;
if (is_aligned) {
amount_to_write = std::min(static_cast<size_t>(size_left), static_cast<size_t>(max_size));
auto status = m_session->write(buffer + bytes_written, amount_to_write, m_timeout);
auto status = m_session->write(buffer + bytes_written, amount_to_write, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
@@ -134,7 +149,7 @@ hailo_status PcieRawConnection::write(const uint8_t *buffer, size_t size)
} else {
amount_to_write = std::min(static_cast<size_t>(size_left), m_context->write_buffer().size());
memcpy(m_context->write_buffer().data(), buffer + bytes_written, amount_to_write);
auto status = m_session->write(m_context->write_buffer().data(), amount_to_write, m_timeout);
auto status = m_session->write(m_context->write_buffer().data(), amount_to_write, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
@@ -147,7 +162,7 @@ hailo_status PcieRawConnection::write(const uint8_t *buffer, size_t size)
return HAILO_SUCCESS;
}
hailo_status PcieRawConnection::read(uint8_t *buffer, size_t size)
hailo_status PcieRawConnection::read(uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
if (0 == size) {
return HAILO_SUCCESS;
@@ -163,14 +178,14 @@ hailo_status PcieRawConnection::read(uint8_t *buffer, size_t size)
auto size_left = size - bytes_read;
if (is_aligned) {
amount_to_read = std::min(static_cast<size_t>(size_left), static_cast<size_t>(max_size));
auto status = m_session->read(buffer + bytes_read, amount_to_read, m_timeout);
auto status = m_session->read(buffer + bytes_read, amount_to_read, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
} else {
amount_to_read = std::min(static_cast<size_t>(size_left), m_context->read_buffer().size());
auto status = m_session->read(m_context->read_buffer().data(), amount_to_read, m_timeout);
auto status = m_session->read(m_context->read_buffer().data(), amount_to_read, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}

View File

@@ -25,7 +25,8 @@ namespace hrpc
class PcieConnectionContext : public ConnectionContext
{
public:
static Expected<std::shared_ptr<ConnectionContext>> create_shared(bool is_accepting);
static Expected<std::shared_ptr<ConnectionContext>> create_client_shared(const std::string &device_id);
static Expected<std::shared_ptr<ConnectionContext>> create_server_shared();
PcieConnectionContext(std::shared_ptr<HailoRTDriver> &&driver, bool is_accepting,
Buffer &&write_buffer, Buffer &&read_buffer)
@@ -61,8 +62,10 @@ public:
virtual Expected<std::shared_ptr<RawConnection>> accept() override;
virtual hailo_status connect() override;
virtual hailo_status write(const uint8_t *buffer, size_t size) override;
virtual hailo_status read(uint8_t *buffer, size_t size) override;
virtual hailo_status write(const uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_WRITE_TIMEOUT) override;
virtual hailo_status read(uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_READ_TIMEOUT) override;
virtual hailo_status close() override;
explicit PcieRawConnection(std::shared_ptr<PcieConnectionContext> context) : m_context(context) {}

View File

@@ -13,9 +13,11 @@
#include <sys/un.h>
#include <string>
#include <unistd.h>
#include <common/logger_macros.hpp>
#include <common/utils.hpp>
#include <hailo/hailort.h>
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include "common/internal_env_vars.hpp"
#include "hailo/hailort.h"
using namespace hrpc;
@@ -27,35 +29,120 @@ Expected<std::shared_ptr<ConnectionContext>> OsConnectionContext::create_shared(
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
Expected<std::shared_ptr<OsRawConnection>> OsRawConnection::create_localhost_server(std::shared_ptr<OsConnectionContext> context)
{
int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
CHECK_AS_EXPECTED(fd >= 0, HAILO_OPEN_FILE_FAILURE, "Socket creation error, errno = {}", errno);
struct sockaddr_un server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
std::string addr = "/tmp/unix_socket";
strncpy(server_addr.sun_path, addr.c_str(), addr.size());
unlink(addr.c_str());
int result = ::bind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
CHECK_AS_EXPECTED(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Bind error, errno = {}", errno);
result = ::listen(fd, 5);
CHECK_AS_EXPECTED(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Listen error, errno = {}", errno);
auto ptr = make_shared_nothrow<OsRawConnection>(fd, context);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
Expected<std::shared_ptr<OsRawConnection>> OsRawConnection::create_localhost_client(std::shared_ptr<OsConnectionContext> context)
{
int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
CHECK_AS_EXPECTED(fd >= 0, HAILO_OPEN_FILE_FAILURE, "Socket creation error, errno = {}", errno);
auto ptr = make_shared_nothrow<OsRawConnection>(fd, context);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
Expected<std::shared_ptr<OsRawConnection>> OsRawConnection::create_by_addr_server(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port)
{
int fd = ::socket(AF_INET, SOCK_STREAM, 0);
CHECK_AS_EXPECTED(fd >= 0, HAILO_OPEN_FILE_FAILURE, "Socket creation error, errno = {}", errno);
sockaddr_in server_addr = {};
socklen_t addr_len = sizeof(server_addr);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
auto inet_rc = inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr);
CHECK_AS_EXPECTED(1 == inet_rc, HAILO_ETH_FAILURE,
"Failed to run 'inet_pton', errno = {}. make sure 'HAILO_SOCKET_COM_ADDR_SERVER' is set correctly (ip:port)", errno);
int result = ::bind(fd, (struct sockaddr*)&server_addr, addr_len);
CHECK_AS_EXPECTED(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Bind error, errno = {}", errno);
result = ::listen(fd, 5);
CHECK_AS_EXPECTED(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Listen error, errno = {}", errno);
auto res = make_shared_nothrow<OsRawConnection>(fd, context);
CHECK_NOT_NULL_AS_EXPECTED(res, HAILO_OUT_OF_HOST_MEMORY);
return res;
}
Expected<std::shared_ptr<OsRawConnection>> OsRawConnection::create_by_addr_client(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port)
{
int fd = ::socket(AF_INET, SOCK_STREAM, 0);
CHECK_AS_EXPECTED(fd >= 0, HAILO_OPEN_FILE_FAILURE, "Socket creation error, errno = {}", errno);
sockaddr_in server_addr = {};
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
auto inet_rc = inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr);
CHECK_AS_EXPECTED(1 == inet_rc, HAILO_ETH_FAILURE,
"Failed to run 'inet_pton', errno = {}. make sure 'HAILO_SOCKET_COM_ADDR_CLIENT' is set correctly (ip:port)", errno);
auto res = make_shared_nothrow<OsRawConnection>(fd, context);
CHECK_NOT_NULL_AS_EXPECTED(res, HAILO_OUT_OF_HOST_MEMORY);
return res;
}
Expected<std::pair<std::string, uint16_t>> OsRawConnection::parse_ip_port(const std::string &ip_port)
{
std::istringstream ss(ip_port);
std::string ip;
uint16_t port;
if (std::getline(ss, ip, ':') && (ss >> port)) {
return std::make_pair(ip, port);
}
CHECK_AS_EXPECTED(false, HAILO_INVALID_ARGUMENT ,"Failed to parse ip and port. Format should be as follows: 'X.X.X.X:PP' (e.g. 127.0.0.1:2000)");
}
Expected<std::shared_ptr<RawConnection>> OsRawConnection::create_shared(std::shared_ptr<OsConnectionContext> context)
{
std::shared_ptr<RawConnection> ptr;
if (context->is_accepting()) {
int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
CHECK_AS_EXPECTED(fd >= 0, HAILO_OPEN_FILE_FAILURE, "Socket creation error, errno = {}", errno);
struct sockaddr_un server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
std::string addr = "/tmp/unix_socket";
strncpy(server_addr.sun_path, addr.c_str(), addr.size());
unlink(addr.c_str());
int result = ::bind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
CHECK_AS_EXPECTED(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Bind error, errno = {}", errno);
result = ::listen(fd, 5);
CHECK_AS_EXPECTED(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Listen error, errno = {}", errno);
ptr = make_shared_nothrow<OsRawConnection>(fd, context);
auto force_socket_com_value = get_env_variable(HAILO_SOCKET_COM_ADDR_SERVER_ENV_VAR);
CHECK_EXPECTED(force_socket_com_value); // We know its set, otherwise we'll be working with PCIeRawCon
if (HAILO_SOCKET_COM_ADDR_UNIX_SOCKET == force_socket_com_value.value()) {
TRY(ptr, create_localhost_server(context));
} else {
TRY(auto ip_port_pair, parse_ip_port(force_socket_com_value.value()));
TRY(ptr, create_by_addr_server(context, std::get<0>(ip_port_pair), std::get<1>(ip_port_pair)));
}
} else {
int fd = ::socket(AF_UNIX, SOCK_STREAM, 0);
CHECK_AS_EXPECTED(fd >= 0, HAILO_OPEN_FILE_FAILURE, "Socket creation error, errno = {}", errno);
ptr = make_shared_nothrow<OsRawConnection>(fd, context);
auto force_socket_com_value = get_env_variable(HAILO_SOCKET_COM_ADDR_CLIENT_ENV_VAR);
CHECK_EXPECTED(force_socket_com_value); // We know its set, otherwise we'll be working with PCIeRawCon
if (HAILO_SOCKET_COM_ADDR_UNIX_SOCKET == force_socket_com_value.value()) {
TRY(ptr, create_localhost_client(context));
} else {
TRY(auto ip_port_pair, parse_ip_port(force_socket_com_value.value()));
TRY(ptr, create_by_addr_client(context, std::get<0>(ip_port_pair), std::get<1>(ip_port_pair)));
}
}
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
@@ -70,7 +157,7 @@ Expected<std::shared_ptr<RawConnection>> OsRawConnection::accept()
return ptr;
}
hailo_status OsRawConnection::connect()
hailo_status OsRawConnection::connect_localhost()
{
struct sockaddr_un server_addr;
std::string addr = "/tmp/unix_socket";
@@ -85,7 +172,48 @@ hailo_status OsRawConnection::connect()
return HAILO_SUCCESS;
}
hailo_status OsRawConnection::write(const uint8_t *buffer, size_t size)
hailo_status OsRawConnection::connect_by_addr(const std::string &ip, uint16_t port)
{
sockaddr_in server_addr = {};
socklen_t addr_len = sizeof(server_addr);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
auto inet_rc = inet_pton(AF_INET, ip.c_str(), &server_addr.sin_addr);
CHECK(1 == inet_rc, HAILO_ETH_FAILURE,
"Failed to run 'inet_pton', errno = {}. make sure 'HAILO_SOCKET_COM_ADDR_XX' is set correctly (ip:port)", errno);
auto result = ::connect(m_fd, (struct sockaddr*)&server_addr, addr_len);
CHECK(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Connect error, errno = {}. "
"make sure 'HAILO_SOCKET_COM_ADDR_XX' is set correctly (ip:port)", errno);
return HAILO_SUCCESS;
}
hailo_status OsRawConnection::connect()
{
if (m_context->is_accepting()) {
auto force_socket_com_value = get_env_variable(HAILO_SOCKET_COM_ADDR_SERVER_ENV_VAR);
CHECK_EXPECTED(force_socket_com_value); // We know its set, otherwise we'll be working with PCIeRawCon
if (HAILO_SOCKET_COM_ADDR_UNIX_SOCKET == force_socket_com_value.value()) {
return connect_localhost();
} else {
TRY(auto ip_port_pair, parse_ip_port(force_socket_com_value.value()));
return connect_by_addr(std::get<0>(ip_port_pair), std::get<1>(ip_port_pair));
}
} else {
auto force_socket_com_value = get_env_variable(HAILO_SOCKET_COM_ADDR_CLIENT_ENV_VAR);
CHECK_EXPECTED(force_socket_com_value); // We know its set, otherwise we'll be working with PCIeRawCon
if (HAILO_SOCKET_COM_ADDR_UNIX_SOCKET == force_socket_com_value.value()) {
return connect_localhost();
} else {
TRY(auto ip_port_pair, parse_ip_port(force_socket_com_value.value()));
return connect_by_addr(std::get<0>(ip_port_pair), std::get<1>(ip_port_pair));
}
}
}
hailo_status OsRawConnection::write(const uint8_t *buffer, size_t size, std::chrono::milliseconds /*timeout*/)
{
size_t bytes_written = 0;
while (bytes_written < size) {
@@ -96,7 +224,7 @@ hailo_status OsRawConnection::write(const uint8_t *buffer, size_t size)
return HAILO_SUCCESS;
}
hailo_status OsRawConnection::read(uint8_t *buffer, size_t size)
hailo_status OsRawConnection::read(uint8_t *buffer, size_t size, std::chrono::milliseconds /*timeout*/)
{
size_t bytes_read = 0;
while (bytes_read < size) {

View File

@@ -39,12 +39,26 @@ public:
virtual Expected<std::shared_ptr<RawConnection>> accept() override;
virtual hailo_status connect() override;
virtual hailo_status write(const uint8_t *buffer, size_t size) override;
virtual hailo_status read(uint8_t *buffer, size_t size) override;
virtual hailo_status write(const uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_WRITE_TIMEOUT) override;
virtual hailo_status read(uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_READ_TIMEOUT) override;
virtual hailo_status close() override;
OsRawConnection(int fd, std::shared_ptr<OsConnectionContext> context) : m_fd(fd), m_context(context) {}
private:
static Expected<std::shared_ptr<OsRawConnection>> create_by_addr_server(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port);
static Expected<std::shared_ptr<OsRawConnection>> create_by_addr_client(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port);
static Expected<std::shared_ptr<OsRawConnection>> create_localhost_server(std::shared_ptr<OsConnectionContext> context);
static Expected<std::shared_ptr<OsRawConnection>> create_localhost_client(std::shared_ptr<OsConnectionContext> context);
hailo_status connect_by_addr(const std::string &ip, uint16_t port);
hailo_status connect_localhost();
static Expected<std::pair<std::string, uint16_t>> parse_ip_port(const std::string &ip_port);
int m_fd;
std::shared_ptr<OsConnectionContext> m_context;
};

View File

@@ -37,17 +37,19 @@ hailo_status OsRawConnection::connect()
return HAILO_NOT_IMPLEMENTED;
}
hailo_status OsRawConnection::write(const uint8_t *buffer, size_t size)
hailo_status OsRawConnection::write(const uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
(void)buffer;
(void)size;
(void)timeout;
return HAILO_NOT_IMPLEMENTED;
}
hailo_status OsRawConnection::read(uint8_t *buffer, size_t size)
hailo_status OsRawConnection::read(uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
(void)buffer;
(void)size;
(void)timeout;
return HAILO_NOT_IMPLEMENTED;
}

View File

@@ -36,8 +36,10 @@ public:
virtual Expected<std::shared_ptr<RawConnection>> accept() override;
virtual hailo_status connect() override;
virtual hailo_status write(const uint8_t *buffer, size_t size) override;
virtual hailo_status read(uint8_t *buffer, size_t size) override;
virtual hailo_status write(const uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_WRITE_TIMEOUT) override;
virtual hailo_status read(uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_READ_TIMEOUT) override;
virtual hailo_status close() override;
explicit OsRawConnection(std::shared_ptr<OsConnectionContext> /*context*/) {}

View File

@@ -10,6 +10,7 @@
#include "hailo/vdevice.hpp"
#include "hrpc/raw_connection.hpp"
#include "hrpc/os/pcie/raw_connection_internal.hpp"
#include "common/internal_env_vars.hpp"
#ifdef _WIN32
#include "hrpc/os/windows/raw_connection_internal.hpp"
@@ -17,21 +18,31 @@
#include "hrpc/os/posix/raw_connection_internal.hpp"
#endif
#define HAILO_FORCE_SOCKET_COM_ENV_VAR "HAILO_FORCE_SOCKET_COM"
using namespace hrpc;
Expected<std::shared_ptr<ConnectionContext>> ConnectionContext::create_shared(bool is_accepting)
Expected<std::shared_ptr<ConnectionContext>> ConnectionContext::create_client_shared(const std::string &device_id)
{
// The env var HAILO_FORCE_HRPC_CLIENT_ENV_VAR is supported for debug purposes
char *socket_com = std::getenv(HAILO_FORCE_SOCKET_COM_ENV_VAR); // TODO: Remove duplication
auto force_socket_com = (nullptr != socket_com) && ("1" == std::string(socket_com));
auto should_force_socket_com = get_env_variable(HAILO_SOCKET_COM_ADDR_CLIENT_ENV_VAR);
if (force_socket_com || VDevice::force_hrpc_client()) {// If forcing hrpc service, its because we work without EP driver -> use sockets
return OsConnectionContext::create_shared(is_accepting);
// If forcing hrpc service, its because we work without EP driver -> use sockets
if (should_force_socket_com.has_value() || VDevice::should_force_hrpc_client()) {
return OsConnectionContext::create_shared(false);
} else {
return PcieConnectionContext::create_shared(is_accepting);
return PcieConnectionContext::create_client_shared(device_id);
}
}
Expected<std::shared_ptr<ConnectionContext>> ConnectionContext::create_server_shared()
{
auto should_force_socket_com = get_env_variable(HAILO_SOCKET_COM_ADDR_SERVER_ENV_VAR);
// If forcing hrpc service, its because we work without EP driver -> use sockets
if (should_force_socket_com.has_value() || VDevice::should_force_hrpc_client()) {
return OsConnectionContext::create_shared(true);
} else {
return PcieConnectionContext::create_server_shared();
}
}

View File

@@ -15,6 +15,9 @@
#include <memory>
#define DEFAULT_WRITE_TIMEOUT (std::chrono::milliseconds(10000))
#define DEFAULT_READ_TIMEOUT (std::chrono::milliseconds(HAILO_INFINITE))
using namespace hailort;
namespace hrpc
@@ -23,7 +26,8 @@ namespace hrpc
class ConnectionContext
{
public:
static Expected<std::shared_ptr<ConnectionContext>> create_shared(bool is_accepting);
static Expected<std::shared_ptr<ConnectionContext>> create_client_shared(const std::string &device_id = "");
static Expected<std::shared_ptr<ConnectionContext>> create_server_shared();
bool is_accepting() const { return m_is_accepting; }
@@ -45,12 +49,11 @@ public:
virtual Expected<std::shared_ptr<RawConnection>> accept() = 0;
virtual hailo_status connect() = 0;
virtual hailo_status write(const uint8_t *buffer, size_t size) = 0;
virtual hailo_status read(uint8_t *buffer, size_t size) = 0;
virtual hailo_status write(const uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_WRITE_TIMEOUT) = 0;
virtual hailo_status read(uint8_t *buffer, size_t size,
std::chrono::milliseconds timeout = DEFAULT_READ_TIMEOUT) = 0;
virtual hailo_status close() = 0;
protected:
std::chrono::milliseconds m_timeout = std::chrono::milliseconds(HAILO_INFINITE);
};
} // namespace hrpc

View File

@@ -15,9 +15,10 @@ namespace hrpc
ServerContext::ServerContext(Server &server, RpcConnection connection) :
m_server(server), m_connection(connection) {}
hailo_status ServerContext::trigger_callback(uint32_t callback_id, hailo_status callback_status, std::function<hailo_status(RpcConnection)> write_buffers_callback)
hailo_status ServerContext::trigger_callback(uint32_t callback_id, hailo_status callback_status,
rpc_object_handle_t callback_owner_handle, std::function<hailo_status(RpcConnection)> write_buffers_callback)
{
return m_server.trigger_callback(callback_id, m_connection, callback_status, write_buffers_callback);
return m_server.trigger_callback(callback_id, callback_status, callback_owner_handle, m_connection, write_buffers_callback);
}
RpcConnection &ServerContext::connection()
@@ -36,14 +37,15 @@ Expected<Buffer> Dispatcher::call_action(HailoRpcActionID action_id, const Memor
if (m_actions.find(action_id) != m_actions.end()) {
return m_actions[action_id](request, server_context);
}
LOGGER__ERROR("Failed to find RPC action {}", action_id);
LOGGER__ERROR("Failed to find RPC action {}", static_cast<int>(action_id));
return make_unexpected(HAILO_RPC_FAILED);
}
hailo_status Server::serve()
{
TRY(auto server_connection, RawConnection::create_shared(m_connection_context));
while (true) {
TRY(auto client_connection, create_client_connection());
TRY(auto client_connection, create_client_connection(server_connection));
auto th = std::thread([this, client_connection]() { serve_client(client_connection); });
th.detach();
}
@@ -55,11 +57,9 @@ void Server::set_dispatcher(Dispatcher dispatcher)
m_dispatcher = dispatcher;
}
Expected<RpcConnection> Server::create_client_connection()
Expected<RpcConnection> Server::create_client_connection(std::shared_ptr<hrpc::RawConnection> server_connection)
{
TRY(auto server_connection, RawConnection::create_shared(m_connection_context));
TRY(auto conn, server_connection->accept());
return RpcConnection(conn);
}
@@ -95,10 +95,11 @@ hailo_status Server::serve_client(RpcConnection client_connection)
return HAILO_SUCCESS;
}
hailo_status Server::trigger_callback(uint32_t callback_id, RpcConnection connection, hailo_status callback_status,
std::function<hailo_status(RpcConnection)> write_buffers_callback)
hailo_status Server::trigger_callback(uint32_t callback_id, hailo_status callback_status, rpc_object_handle_t callback_owner_handle,
RpcConnection connection, std::function<hailo_status(RpcConnection)> write_buffers_callback)
{
TRY(auto reply, CallbackCalledSerializer::serialize_reply(callback_status, callback_id));
// TODO: callback handling should be outside of HRPC (HRT-14638)
TRY(auto reply, CallbackCalledSerializer::serialize_reply(callback_status, callback_id, callback_owner_handle));
std::unique_lock<std::mutex> lock(m_write_mutex);
rpc_message_header_t header;

View File

@@ -27,7 +27,7 @@ class ServerContext
public:
ServerContext(Server &server, RpcConnection connection);
hailo_status trigger_callback(uint32_t callback_id, hailo_status callback_status,
std::function<hailo_status(RpcConnection)> write_buffers_callback = nullptr);
rpc_object_handle_t callback_owner_handle, std::function<hailo_status(RpcConnection)> write_buffers_callback = nullptr);
RpcConnection &connection();
private:
@@ -63,10 +63,10 @@ public:
protected:
std::shared_ptr<ConnectionContext> m_connection_context;
private:
Expected<RpcConnection> create_client_connection();
Expected<RpcConnection> create_client_connection(std::shared_ptr<hrpc::RawConnection> server_connection);
hailo_status serve_client(RpcConnection client_connection);
hailo_status trigger_callback(uint32_t callback_id, RpcConnection connection, hailo_status callback_status,
std::function<hailo_status(RpcConnection)> write_buffers_callback = nullptr);
hailo_status trigger_callback(uint32_t callback_id, hailo_status callback_status, rpc_object_handle_t callback_owner_handle,
RpcConnection connection, std::function<hailo_status(RpcConnection)> write_buffers_callback = nullptr);
virtual hailo_status cleanup_client_resources(RpcConnection client_connection) = 0;
Dispatcher m_dispatcher;

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
protobuf_generate_cpp(PROTO_RPC_SRC PROTO_RPC_HEADER rpc.proto)
get_filename_component(PROTO_HEADER_DIRECTORY ${PROTO_RPC_HEADER} DIRECTORY)

View File

@@ -20,6 +20,11 @@ message RpcRequest {
ConfiguredInferModel_Deactivate_Request deactivate_request = 12;
ConfiguredInferModel_Shutdown_Request shutdown_request = 13;
ConfiguredInferModel_AsyncInfer_Request async_infer_request = 14;
Device_Create_Request create_device_request = 15;
Device_Destroy_Request destroy_device_request = 16;
Device_Identify_Request identify_device_request = 17;
Device_ExtendedInfo_Request extended_device_info_request = 18;
}
}
@@ -42,7 +47,13 @@ message RpcReply {
ConfiguredInferModel_Shutdown_Reply shutdown_reply = 13;
ConfiguredInferModel_AsyncInfer_Reply async_infer_reply = 14;
CallbackCalled_Reply callback_called_reply = 15;
Device_Create_Reply create_device_reply = 15;
Device_Destroy_Reply destroy_device_reply = 16;
Device_Identify_Reply identify_device_reply = 17;
Device_ExtendedInfo_Reply extended_device_info_reply = 18;
// Here comes replies that have no matching requests
CallbackCalled_Reply callback_called_reply = 19;
}
}
@@ -79,6 +90,7 @@ message VDevice_Destroy_Reply {
message VDevice_CreateInferModel_Request {
HailoObjectHandle vdevice_handle = 1;
uint64 hef_size = 2;
string name = 3;
// Protocol note: After this message, server expects to get HEF data (buffer of size 'hef_size')
}
@@ -193,6 +205,7 @@ message ConfiguredInferModel_AsyncInfer_Request {
HailoObjectHandle configured_infer_model_handle = 1;
HailoObjectHandle infer_model_handle = 2;
HailoCallbackHandle callback_handle = 3;
repeated uint32 input_buffer_sizes = 4;
// Protocol note: After this messgae, server expects to get the input buffers, one after the other, in order
}
@@ -203,5 +216,92 @@ message ConfiguredInferModel_AsyncInfer_Reply {
message CallbackCalled_Reply {
uint32 status = 1;
HailoCallbackHandle callback_handle = 2;
HailoObjectHandle configured_infer_model_handle = 3;
// Protocol note: After this messgae, and only if status is HAILO_SUCCESS, server expects to get the output buffers, one after the other, in order
}
message Device_Create_Request {
}
message Device_Create_Reply {
uint32 status = 1;
HailoObjectHandle device_handle = 2;
}
message Device_Destroy_Request {
HailoObjectHandle device_handle = 1;
}
message Device_Destroy_Reply {
uint32 status = 1;
}
message Device_Identify_Request {
HailoObjectHandle device_handle = 1;
}
// Added "_value" to the names so that the symbols will not clash with the macros defined in <sys/types.h>
message FirmwareVersionProto {
uint32 major_value = 1;
uint32 minor_value = 2;
uint32 revision_value = 3;
}
enum DeviceArchitectureProto {
HAILO8_A0 = 0;
HAILO8 = 1;
HAILO8L = 2;
HAILO15H = 3;
PLUTO = 4;
HAILO15M = 5;
HAILO10H = 6;
}
message DeviceIdentityProto {
uint32 protocol_version = 1;
FirmwareVersionProto fw_version = 2;
uint32 logger_version = 3;
string board_name = 4;
bool is_release = 5;
bool extended_context_switch_buffer = 6;
DeviceArchitectureProto device_architecture = 7;
repeated uint32 serial_number = 8;
repeated uint32 part_number = 9;
string product_name = 10;
}
message Device_Identify_Reply {
uint32 status = 1;
DeviceIdentityProto identity = 2;
}
message Device_ExtendedInfo_Request {
HailoObjectHandle device_handle = 1;
}
message DeviceSupportedFeaturesProto {
bool ethernet = 1;
bool mipi = 2;
bool pcie = 3;
bool current_monitoring = 4;
bool mdio = 5;
}
enum DeviceBootSourceProto {
BOOT_SOURCE_INVALID = 0;
BOOT_SOURCE_PCIE = 1;
BOOT_SOURCE_FLASH = 2;
BOOT_SOURCE_MAX = 3;
}
message Device_ExtendedInfo_Reply {
uint32 status = 1;
uint32 neural_network_core_clock_rate = 2;
DeviceSupportedFeaturesProto supported_features = 3;
DeviceBootSourceProto boot_source = 4;
repeated uint32 soc_id = 5;
uint32 lcs = 6;
repeated uint32 eth_mac_address = 7;
repeated uint32 unit_level_tracking_id = 8;
repeated uint32 soc_pm_values = 9;
}

View File

@@ -40,7 +40,7 @@ Expected<Buffer> CreateVDeviceSerializer::serialize_request(const hailo_vdevice_
proto_params->set_scheduling_algorithm(params.scheduling_algorithm);
proto_params->set_group_id(params.group_id == nullptr ? "" : std::string(params.group_id));
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
@@ -101,7 +101,7 @@ Expected<Buffer> DestroyVDeviceSerializer::serialize_request(rpc_object_handle_t
auto proto_vdevice_handle= request.mutable_vdevice_handle();
proto_vdevice_handle->set_id(vdevice_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'DestroyVDevice'");
@@ -142,16 +142,17 @@ hailo_status DestroyVDeviceSerializer::deserialize_reply(const MemoryView &seria
return static_cast<hailo_status>(reply.status());
}
Expected<Buffer> CreateInferModelSerializer::serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size)
Expected<Buffer> CreateInferModelSerializer::serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size,
const std::string &name)
{
VDevice_CreateInferModel_Request request;
auto proto_vdevice_handle = request.mutable_vdevice_handle();
proto_vdevice_handle->set_id(vdevice_handle);
request.set_hef_size(hef_size);
request.set_name(name);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'CreateVInferModel'");
@@ -159,14 +160,14 @@ Expected<Buffer> CreateInferModelSerializer::serialize_request(rpc_object_handle
return serialized_request;
}
Expected<std::tuple<rpc_object_handle_t, uint64_t>> CreateInferModelSerializer::deserialize_request(const MemoryView &serialized_request)
Expected<std::tuple<rpc_object_handle_t, uint64_t, std::string>> CreateInferModelSerializer::deserialize_request(const MemoryView &serialized_request)
{
VDevice_CreateInferModel_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'CreateVInferModel'");
return std::make_tuple(request.vdevice_handle().id(), request.hef_size());
return std::make_tuple(request.vdevice_handle().id(), request.hef_size(), request.name());
}
Expected<Buffer> CreateInferModelSerializer::serialize_reply(hailo_status status, rpc_object_handle_t infer_model_handle)
@@ -202,7 +203,7 @@ Expected<Buffer> DestroyInferModelSerializer::serialize_request(rpc_object_handl
auto proto_infer_model_handle = request.mutable_infer_model_handle();
proto_infer_model_handle->set_id(infer_model_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'DestroyInferModel'");
@@ -279,7 +280,7 @@ Expected<Buffer> CreateConfiguredInferModelSerializer::serialize_request(rpc_cre
request.set_power_mode(static_cast<uint32_t>(params.power_mode));
request.set_latency_flag(static_cast<uint32_t>(params.latency_flag));
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'CreateConfiguredInferModel'");
@@ -363,7 +364,7 @@ Expected<Buffer> DestroyConfiguredInferModelSerializer::serialize_request(rpc_ob
auto proto_infer_model_handle = request.mutable_configured_infer_model_handle();
proto_infer_model_handle->set_id(configured_infer_model_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'DestroyConfiguredInferModel'");
@@ -413,7 +414,7 @@ Expected<Buffer> SetSchedulerTimeoutSerializer::serialize_request(rpc_object_han
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
request.set_timeout(static_cast<uint32_t>(timeout.count()));
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'SetSchedulerTimeout'");
@@ -463,7 +464,7 @@ Expected<Buffer> SetSchedulerThresholdSerializer::serialize_request(rpc_object_h
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
request.set_threshold(threshold);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'SetSchedulerThreshold'");
@@ -513,7 +514,7 @@ Expected<Buffer> SetSchedulerPrioritySerializer::serialize_request(rpc_object_ha
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
request.set_priority(priority);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'SetSchedulerPriority'");
@@ -562,7 +563,7 @@ Expected<Buffer> GetHwLatencyMeasurementSerializer::serialize_request(rpc_object
auto proto_configured_infer_model_handle = request.mutable_configured_infer_model_handle();
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'GetHwLatencyMeasurement'");
@@ -611,7 +612,7 @@ Expected<Buffer> ActivateSerializer::serialize_request(rpc_object_handle_t confi
auto proto_configured_infer_model_handle = request.mutable_configured_infer_model_handle();
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'Activate'");
@@ -659,7 +660,7 @@ Expected<Buffer> DeactivateSerializer::serialize_request(rpc_object_handle_t con
auto proto_configured_infer_model_handle = request.mutable_configured_infer_model_handle();
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'Deactivate'");
@@ -707,7 +708,7 @@ Expected<Buffer> ShutdownSerializer::serialize_request(rpc_object_handle_t confi
auto proto_configured_infer_model_handle = request.mutable_configured_infer_model_handle();
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'Shutdown'");
@@ -748,21 +749,22 @@ hailo_status ShutdownSerializer::deserialize_reply(const MemoryView &serialized_
return static_cast<hailo_status>(reply.status());
}
Expected<Buffer> RunAsyncSerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle, rpc_object_handle_t infer_model_handle,
rpc_object_handle_t callback_handle)
Expected<Buffer> RunAsyncSerializer::serialize_request(const RunAsyncSerializer::Request &request_struct)
{
ConfiguredInferModel_AsyncInfer_Request request;
auto proto_configured_infer_model_handle = request.mutable_configured_infer_model_handle();
proto_configured_infer_model_handle->set_id(configured_infer_model_handle);
proto_configured_infer_model_handle->set_id(request_struct.configured_infer_model_handle);
auto proto_infer_model_handle = request.mutable_infer_model_handle();
proto_infer_model_handle->set_id(infer_model_handle);
proto_infer_model_handle->set_id(request_struct.infer_model_handle);
auto proto_cb_handle = request.mutable_callback_handle();
proto_cb_handle->set_id(callback_handle);
proto_cb_handle->set_id(request_struct.callback_handle);
// TODO (HRT-13983) - check if we can use GetCachedSize
*request.mutable_input_buffer_sizes() = {request_struct.input_buffer_sizes.begin(), request_struct.input_buffer_sizes.end()};
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'RunAsync'");
@@ -770,7 +772,7 @@ Expected<Buffer> RunAsyncSerializer::serialize_request(rpc_object_handle_t confi
return serialized_request;
}
Expected<std::tuple<rpc_object_handle_t, rpc_object_handle_t, rpc_object_handle_t>> RunAsyncSerializer::deserialize_request(
Expected<RunAsyncSerializer::Request> RunAsyncSerializer::deserialize_request(
const MemoryView &serialized_request)
{
ConfiguredInferModel_AsyncInfer_Request request;
@@ -778,8 +780,14 @@ Expected<std::tuple<rpc_object_handle_t, rpc_object_handle_t, rpc_object_handle_
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'RunAsync'");
return std::make_tuple(request.configured_infer_model_handle().id(), request.infer_model_handle().id(),
request.callback_handle().id());
std::vector<uint32_t> input_buffer_sizes(request.input_buffer_sizes().begin(), request.input_buffer_sizes().end());
RunAsyncSerializer::Request request_struct;
request_struct.configured_infer_model_handle = request.configured_infer_model_handle().id();
request_struct.infer_model_handle = request.infer_model_handle().id();
request_struct.callback_handle = request.callback_handle().id();
request_struct.input_buffer_sizes = input_buffer_sizes;
return request_struct;
}
Expected<Buffer> RunAsyncSerializer::serialize_reply(hailo_status status)
@@ -805,7 +813,8 @@ hailo_status RunAsyncSerializer::deserialize_reply(const MemoryView &serialized_
return static_cast<hailo_status>(reply.status());
}
Expected<Buffer> CallbackCalledSerializer::serialize_reply(hailo_status status, rpc_object_handle_t callback_handle)
Expected<Buffer> CallbackCalledSerializer::serialize_reply(hailo_status status, rpc_object_handle_t callback_handle,
rpc_object_handle_t configured_infer_model_handle)
{
CallbackCalled_Reply reply;
@@ -813,6 +822,9 @@ Expected<Buffer> CallbackCalledSerializer::serialize_reply(hailo_status status,
auto proto_callback_handle = reply.mutable_callback_handle();
proto_callback_handle->set_id(callback_handle);
auto proto_cim_handle = reply.mutable_configured_infer_model_handle();
proto_cim_handle->set_id(configured_infer_model_handle);
TRY(auto serialized_reply, Buffer::create(reply.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(reply.SerializeToArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
@@ -821,14 +833,319 @@ Expected<Buffer> CallbackCalledSerializer::serialize_reply(hailo_status status,
return serialized_reply;
}
Expected<std::tuple<hailo_status, rpc_object_handle_t>> CallbackCalledSerializer::deserialize_reply(const MemoryView &serialized_reply)
Expected<std::tuple<hailo_status, rpc_object_handle_t, rpc_object_handle_t>>
CallbackCalledSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
CallbackCalled_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'CallbackCalled'");
return std::make_tuple(static_cast<hailo_status>(reply.status()), reply.callback_handle().id());
return std::make_tuple(static_cast<hailo_status>(reply.status()), reply.callback_handle().id(),
reply.configured_infer_model_handle().id());
}
Expected<Buffer> CreateDeviceSerializer::serialize_request()
{
Device_Create_Request request;
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'CreateDevice'");
return serialized_request;
}
hailo_status CreateDeviceSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_Create_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'CreateDevice'");
return HAILO_SUCCESS;
}
Expected<Buffer> CreateDeviceSerializer::serialize_reply(hailo_status status, rpc_object_handle_t device_handle)
{
Device_Create_Reply reply;
reply.set_status(status);
auto proto_device_handle = reply.mutable_device_handle();
proto_device_handle->set_id(device_handle);
TRY(auto serialized_reply, Buffer::create(reply.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(reply.SerializeToArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to serialize 'CreateDevice'");
return serialized_reply;
}
Expected<std::tuple<hailo_status, rpc_object_handle_t>> CreateDeviceSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
Device_Create_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'CreateDevice'");
return std::make_tuple(static_cast<hailo_status>(reply.status()), reply.device_handle().id());
}
Expected<Buffer> DestroyDeviceSerializer::serialize_request(rpc_object_handle_t device_handle)
{
Device_Destroy_Request request;
auto proto_device_handle= request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'DestroyDevice'");
return serialized_request;
}
Expected<rpc_object_handle_t> DestroyDeviceSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_Destroy_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'DestroyDevice'");
return request.device_handle().id();
}
Expected<Buffer> DestroyDeviceSerializer::serialize_reply(hailo_status status)
{
Device_Destroy_Reply reply;
reply.set_status(status);
TRY(auto serialized_reply, Buffer::create(reply.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(reply.SerializeToArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to serialize 'DestroyDevice'");
return serialized_reply;
}
hailo_status DestroyDeviceSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
Device_Destroy_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'DestroyDevice'");
return static_cast<hailo_status>(reply.status());
}
Expected<Buffer> IdentifyDeviceSerializer::serialize_request(rpc_object_handle_t device_handle)
{
Device_Identify_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'IdentifyDevice'");
return serialized_request;
}
Expected<rpc_object_handle_t> IdentifyDeviceSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_Identify_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'IdentifyDevice'");
return request.device_handle().id();
}
Expected<Buffer> IdentifyDeviceSerializer::serialize_reply(hailo_status status, const hailo_device_identity_t &identity)
{
Device_Identify_Reply reply;
reply.set_status(status);
auto proto_identity = reply.mutable_identity();
proto_identity->set_protocol_version(identity.protocol_version);
proto_identity->set_logger_version(identity.logger_version);
proto_identity->set_board_name(identity.board_name);
proto_identity->set_is_release(identity.is_release);
proto_identity->set_extended_context_switch_buffer(identity.extended_context_switch_buffer);
proto_identity->set_device_architecture(static_cast<DeviceArchitectureProto>(identity.device_architecture));
auto mut_serial_number = proto_identity->mutable_serial_number();
for (uint8_t i = 0; i < identity.serial_number_length; i++) {
mut_serial_number->Add(identity.serial_number[i]);
}
auto mut_part_number = proto_identity->mutable_part_number();
for (uint8_t i = 0; i < identity.part_number_length; i++) {
mut_part_number->Add(identity.part_number[i]);
}
proto_identity->set_product_name(identity.product_name);
auto fw_version = proto_identity->mutable_fw_version();
fw_version->set_major_value(identity.fw_version.major);
fw_version->set_minor_value(identity.fw_version.minor);
fw_version->set_revision_value(identity.fw_version.revision);
TRY(auto serialized_reply, Buffer::create(reply.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(reply.SerializeToArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to serialize 'IdentifyDevice'");
return serialized_reply;
}
Expected<std::tuple<hailo_status, hailo_device_identity_t>> IdentifyDeviceSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
Device_Identify_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'IdentifyDevice'");
hailo_device_identity_t identity = {};
identity.protocol_version = reply.identity().protocol_version();
identity.logger_version = reply.identity().logger_version();
identity.is_release = reply.identity().is_release();
identity.extended_context_switch_buffer = reply.identity().extended_context_switch_buffer();
identity.device_architecture = static_cast<hailo_device_architecture_t>(reply.identity().device_architecture());
std::memcpy(identity.board_name, reply.identity().board_name().c_str(), reply.identity().board_name().size());
identity.board_name_length = static_cast<uint8_t>(reply.identity().board_name().size());
std::transform(reply.identity().serial_number().begin(), reply.identity().serial_number().end(), identity.serial_number, [](uint32_t val) {
return static_cast<uint8_t>(val);
});
identity.part_number_length = static_cast<uint8_t>(reply.identity().part_number().size());
std::transform(reply.identity().part_number().begin(), reply.identity().part_number().end(), identity.part_number, [](uint32_t val) {
return static_cast<uint8_t>(val);
});
identity.part_number_length = static_cast<uint8_t>(reply.identity().serial_number().size());
std::memcpy(identity.product_name, reply.identity().product_name().c_str(), reply.identity().product_name().size());
identity.product_name_length = static_cast<uint8_t>(reply.identity().product_name().size());
identity.fw_version.major = reply.identity().fw_version().major_value();
identity.fw_version.minor = reply.identity().fw_version().minor_value();
identity.fw_version.revision = reply.identity().fw_version().revision_value();
return std::make_tuple(static_cast<hailo_status>(reply.status()), identity);
}
Expected<Buffer> ExtendedDeviceInfoSerializer::serialize_request(rpc_object_handle_t device_handle)
{
Device_ExtendedInfo_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
// TODO (HRT-14732) - check if we can use GetCachedSize
TRY(auto serialized_request, Buffer::create(request.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(request.SerializeToArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to serialize 'ExtendedDeviceInfo'");
return serialized_request;
}
Expected<rpc_object_handle_t> ExtendedDeviceInfoSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_ExtendedInfo_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'ExtendedDeviceInfo'");
return request.device_handle().id();
}
Expected<Buffer> ExtendedDeviceInfoSerializer::serialize_reply(hailo_status status, const hailo_extended_device_information_t &extended_info)
{
Device_ExtendedInfo_Reply reply;
reply.set_status(status);
reply.set_neural_network_core_clock_rate(extended_info.neural_network_core_clock_rate);
auto supported_features = reply.mutable_supported_features();
supported_features->set_ethernet(extended_info.supported_features.ethernet);
supported_features->set_mipi(extended_info.supported_features.mipi);
supported_features->set_pcie(extended_info.supported_features.pcie);
supported_features->set_current_monitoring(extended_info.supported_features.current_monitoring);
supported_features->set_mdio(extended_info.supported_features.mdio);
reply.set_boot_source(static_cast<DeviceBootSourceProto>(extended_info.boot_source));
auto soc_id = reply.mutable_soc_id();
for (auto i = 0; i < HAILO_SOC_ID_LENGTH; i++) {
soc_id->Add(extended_info.soc_id[i]);
}
reply.set_lcs(extended_info.lcs);
auto eth_mac_address = reply.mutable_eth_mac_address();
for (auto i = 0; i < HAILO_ETH_MAC_LENGTH; i++) {
eth_mac_address->Add(extended_info.eth_mac_address[i]);
}
auto unit_level_tracking_id = reply.mutable_unit_level_tracking_id();
for (auto i = 0; i < HAILO_UNIT_LEVEL_TRACKING_BYTES_LENGTH; i++) {
unit_level_tracking_id->Add(extended_info.unit_level_tracking_id[i]);
}
auto soc_pm_values = reply.mutable_soc_pm_values();
for (auto i = 0; i < HAILO_SOC_PM_VALUES_BYTES_LENGTH; i++) {
soc_pm_values->Add(extended_info.soc_pm_values[i]);
}
TRY(auto serialized_reply, Buffer::create(reply.ByteSizeLong(), BufferStorageParams::create_dma()));
CHECK_AS_EXPECTED(reply.SerializeToArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to serialize 'ExtendedDeviceInfo'");
return serialized_reply;
}
Expected<std::tuple<hailo_status, hailo_extended_device_information_t>> ExtendedDeviceInfoSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
Device_ExtendedInfo_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'ExtendedDeviceInfo'");
hailo_extended_device_information_t extended_info = {};
extended_info.neural_network_core_clock_rate = reply.neural_network_core_clock_rate();
extended_info.supported_features.ethernet = reply.supported_features().ethernet();
extended_info.supported_features.mipi = reply.supported_features().mipi();
extended_info.supported_features.pcie = reply.supported_features().pcie();
extended_info.supported_features.current_monitoring = reply.supported_features().current_monitoring();
extended_info.supported_features.mdio = reply.supported_features().mdio();
extended_info.boot_source = static_cast<hailo_device_boot_source_t>(reply.boot_source());
std::transform(reply.soc_id().begin(), reply.soc_id().end(), extended_info.soc_id, [](uint32_t val) {
return static_cast<uint8_t>(val);
});
extended_info.lcs = static_cast<uint8_t>(reply.lcs());
// Ensure that the sizes of the input and output arrays match before transformation
assert(reply.eth_mac_address().size() == HAILO_ETH_MAC_LENGTH);
std::transform(reply.eth_mac_address().begin(), reply.eth_mac_address().begin() + HAILO_ETH_MAC_LENGTH,
extended_info.eth_mac_address, [](uint32_t val) { return static_cast<uint8_t>(val); });
assert(reply.unit_level_tracking_id().size() == HAILO_UNIT_LEVEL_TRACKING_BYTES_LENGTH);
std::transform(reply.unit_level_tracking_id().begin(), reply.unit_level_tracking_id().begin() + HAILO_UNIT_LEVEL_TRACKING_BYTES_LENGTH,
extended_info.unit_level_tracking_id, [](uint32_t val) { return static_cast<uint8_t>(val); });
assert(reply.soc_pm_values().size() == HAILO_SOC_PM_VALUES_BYTES_LENGTH);
std::transform(reply.soc_pm_values().begin(), reply.soc_pm_values().begin() + HAILO_SOC_PM_VALUES_BYTES_LENGTH,
extended_info.soc_pm_values, [](uint32_t val) { return static_cast<uint8_t>(val); });
return std::make_tuple(static_cast<hailo_status>(reply.status()), extended_info);
}
} /* namespace hailort */

View File

@@ -16,6 +16,7 @@
#include <chrono>
#include <unordered_map>
#include <vector>
namespace hailort
{
@@ -41,6 +42,11 @@ enum class HailoRpcActionID {
CONFIGURED_INFER_MODEL__SHUTDOWN,
CONFIGURED_INFER_MODEL__RUN_ASYNC,
DEVICE__CREATE,
DEVICE__DESTROY,
DEVICE__IDENTIFY,
DEVICE__EXTENDED_INFO,
CALLBACK_CALLED,
MAX_VALUE,
@@ -97,8 +103,8 @@ class CreateInferModelSerializer
public:
CreateInferModelSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size);
static Expected<std::tuple<rpc_object_handle_t, uint64_t>> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size, const std::string &name);
static Expected<std::tuple<rpc_object_handle_t, uint64_t, std::string>> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, rpc_object_handle_t infer_model_handle = INVALID_HANDLE_ID);
static Expected<std::tuple<hailo_status, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
@@ -230,9 +236,16 @@ class RunAsyncSerializer
public:
RunAsyncSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle, rpc_object_handle_t infer_model_handle,
rpc_object_handle_t callback_handle);
static Expected<std::tuple<rpc_object_handle_t, rpc_object_handle_t, rpc_object_handle_t>> deserialize_request(const MemoryView &serialized_request);
struct Request
{
rpc_object_handle_t configured_infer_model_handle;
rpc_object_handle_t infer_model_handle;
rpc_object_handle_t callback_handle;
std::vector<uint32_t> input_buffer_sizes;
};
static Expected<Buffer> serialize_request(const Request &request_struct);
static Expected<Request> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status);
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
@@ -243,10 +256,59 @@ class CallbackCalledSerializer
public:
CallbackCalledSerializer() = delete;
static Expected<Buffer> serialize_reply(hailo_status status, rpc_object_handle_t callback_handle = INVALID_HANDLE_ID);
static Expected<Buffer> serialize_reply(hailo_status status, rpc_object_handle_t callback_handle = INVALID_HANDLE_ID,
rpc_object_handle_t configured_infer_model_handle = INVALID_HANDLE_ID);
static Expected<std::tuple<hailo_status, rpc_object_handle_t, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class CreateDeviceSerializer
{
public:
CreateDeviceSerializer() = delete;
static Expected<Buffer> serialize_request();
static hailo_status deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, rpc_object_handle_t device_handle = INVALID_HANDLE_ID);
static Expected<std::tuple<hailo_status, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class DestroyDeviceSerializer
{
public:
DestroyDeviceSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle);
static Expected<rpc_object_handle_t> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status);
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class IdentifyDeviceSerializer
{
public:
IdentifyDeviceSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle);
static Expected<rpc_object_handle_t> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, const hailo_device_identity_t &identity = {});
static Expected<std::tuple<hailo_status, hailo_device_identity_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class ExtendedDeviceInfoSerializer
{
public:
ExtendedDeviceInfoSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle);
static Expected<rpc_object_handle_t> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, const hailo_extended_device_information_t &extended_info = {});
static Expected<std::tuple<hailo_status, hailo_extended_device_information_t>> deserialize_reply(const MemoryView &serialized_reply);
};
} /* namespace hailort */

View File

@@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
# set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
set(HAILORT_MAJOR_VERSION 4)
set(HAILORT_MINOR_VERSION 18)
set(HAILORT_MINOR_VERSION 19)
set(HAILORT_REVISION_VERSION 0)
# Add the cmake folder so the modules there are found
@@ -27,10 +27,6 @@ target_include_directories(hef_proto
$<BUILD_INTERFACE: ${Protobuf_INCLUDE_DIRS}>
)
if(HAILO_BUILD_PROFILER)
add_definitions( -DHAILO_ENABLE_PROFILER_BUILD )
endif()
protobuf_generate_cpp(PROTO_SCHEDULER_MON_SRC PROTO_SCHEDULER_MON_HEADR scheduler_mon.proto)
add_library(scheduler_mon_proto ${PROTO_SCHEDULER_MON_SRC} ${PROTO_SCHEDULER_MON_HEADR})
target_link_libraries(scheduler_mon_proto libprotobuf-lite)

View File

@@ -1,9 +1,12 @@
cmake_minimum_required(VERSION 3.0.0)
if(HAILO_BUILD_PYBIND)
add_subdirectory(python)
endif()
cmake_minimum_required(VERSION 3.5.0)
# QNX currently doesnt support GStreamer
if(HAILO_BUILD_GSTREAMER AND CMAKE_HOST_UNIX AND NOT CMAKE_SYSTEM_NAME STREQUAL QNX)
if(HAILO_BUILD_GSTREAMER AND NOT CMAKE_SYSTEM_NAME STREQUAL QNX)
add_subdirectory(gstreamer)
endif()
option(HAILO_BUILD_PYHAILORT_INTERNAL OFF)
option(HAILO_BUILD_RAW_CONNECTION OFF)
if(HAILO_BUILD_RAW_CONNECTION OR HAILO_BUILD_PYHAILORT_INTERNAL)
add_subdirectory(python/src/internal/)
endif()

View File

@@ -1,34 +1,24 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
project(gsthailo)
include(GNUInstallDirs)
if(NOT CMAKE_HOST_UNIX)
message(FATAL_ERROR "Only unix hosts are supported, stopping build")
endif()
find_package(HailoRT 4.18.0 EXACT REQUIRED)
find_package(HailoRT 4.19.0 EXACT REQUIRED)
# GST_PLUGIN_DEFINE needs PACKAGE to be defined
set(GST_HAILO_PACKAGE_NAME "hailo")
set(GST_HAILO_VERSION "1.0")
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)
pkg_search_module(GSTREAMER REQUIRED gstreamer-1.0)
pkg_search_module(GSTREAMER_BASE REQUIRED gstreamer-base-1.0)
pkg_search_module(GSTREAMER_VIDEO REQUIRED gstreamer-video-1.0)
pkg_search_module(GSTREAMER_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0)
include(find_libs_for_gstreamer.cmake)
add_library(gsthailo SHARED
set(GSTHAILO_SOURCES
gst-hailo/gsthailoplugin.cpp
gst-hailo/sync_gsthailonet.cpp
gst-hailo/sync_gst_hailosend.cpp
gst-hailo/sync_gst_hailorecv.cpp
gst-hailo/gsthailonet.cpp
gst-hailo/gsthailo_allocator.cpp
gst-hailo/gsthailo_dmabuf_allocator.cpp
gst-hailo/gsthailodevicestats.cpp
gst-hailo/common.cpp
gst-hailo/network_group_handle.cpp
@@ -36,8 +26,18 @@ add_library(gsthailo SHARED
gst-hailo/metadata/tensor_meta.cpp
gst-hailo/hailo_events/hailo_events.cpp)
# dmabuf is supported only on linux
if (UNIX)
list(APPEND GSTHAILO_SOURCES gst-hailo/gsthailo_dmabuf_allocator.cpp gst-hailo/os/linux/dma_buf_allocator_wrapper.cpp)
elseif (MSVC)
list(APPEND GSTHAILO_SOURCES gst-hailo/os/windows/dma_buf_allocator_wrapper.cpp)
endif ()
add_library(gsthailo SHARED ${GSTHAILO_SOURCES})
set_property(TARGET gsthailo PROPERTY CXX_STANDARD 14)
# TODO HRT-14797: After creating a directory containing all the relevant Hailo GST files (tensor_meta.hpp and hailo_gst.h) - update the PUBLIC_HEADER to be that dir
set_target_properties(gsthailo PROPERTIES
PUBLIC_HEADER "gst-hailo/metadata/tensor_meta.hpp"
CXX_STANDARD 14
@@ -48,17 +48,54 @@ set_target_properties(gsthailo PROPERTIES
# VISIBILITY_INLINES_HIDDEN YES
)
target_compile_options(gsthailo PRIVATE
-Werror -Wall -Wextra -Wconversion
-DVERSION="${GST_HAILO_VERSION}"
-DPACKAGE="${GST_HAILO_PACKAGE_NAME}")
if (UNIX)
set(HAILORT_COMPILE_OPTIONS
${HAILORT_COMPILE_OPTIONS}
-DVERSION="${GST_HAILO_VERSION}"
-DPACKAGE="${GST_HAILO_PACKAGE_NAME}"
)
elseif (WIN32)
set(HAILORT_COMPILE_OPTIONS
${HAILORT_COMPILE_OPTIONS}
/DWIN32_LEAN_AND_MEAN
/DNOMINMAX # NOMINMAX is required in order to play nice with std::min/std::max (otherwise Windows.h defines it's own)
/D_HAILO_EXPORTING
/wd4201 # Anonymous union/struct
/wd4251 # C++ ABI with STL
-DVERSION="${GST_HAILO_VERSION}"
-DPACKAGE="${GST_HAILO_PACKAGE_NAME}"
)
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
target_include_directories(gsthailo PRIVATE ${GSTREAMER_VIDEO_INCLUDE_DIRS})
target_link_libraries(gsthailo HailoRT::libhailort ${GSTREAMER_VIDEO_LDFLAGS} -lgstallocators-1.0)
target_compile_options(gsthailo PRIVATE ${HAILORT_COMPILE_OPTIONS})
if (UNIX)
target_include_directories(gsthailo PRIVATE ${GSTREAMER_VIDEO_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo ${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo/os/linux)
target_link_libraries(gsthailo HailoRT::libhailort ${GSTREAMER_VIDEO_LDFLAGS} -lgstallocators-1.0)
else()
target_include_directories(gsthailo PRIVATE ${GSTREAMER_INCLUDE_DIRS} ${GSTREAMER_VIDEO_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${GLIBCONFIG_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo ${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo/os/windows)
target_link_libraries(gsthailo HailoRT::libhailort ${GSTREAMER_LIBRARIES} ${GSTREAMER_BASE_LIBRARIES} ${GSTREAMER_VIDEO_LIBRARIES} ${GLIB_LIBRARIES} ${GOBJECT_LIBRARIES} -lgstallocators-1.0)
endif()
if (UNIX)
set(GSTREAMER_LIB_DEST "${CMAKE_INSTALL_LIBDIR}/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu/gstreamer-1.0/")
set(PUBLIC_HEADER_DEST "${CMAKE_INSTALL_INCLUDEDIR}/gstreamer-1.0/gst/hailo/")
elseif (MSVC)
if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x64")
set(GSTREAMER_DEST "C:\\gstreamer\\1.0\\msvc_x86_64")
else()
message(FATAL_ERROR "HailoRT GStreamer elements installation is not supported on this architecture.")
endif()
set(GSTREAMER_LIB_DEST "${GSTREAMER_DEST}\\lib\\gstreamer-1.0")
set(PUBLIC_HEADER_DEST "${CMAKE_INSTALL_INCLUDEDIR}\\gstreamer-1.0\\gst\\hailo")
endif()
# Install command using the set variables
install(TARGETS gsthailo
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
# TODO: get gstreamer-1.0 in an automate way
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/gstreamer-1.0/gst/hailo/"
RUNTIME DESTINATION "${GSTREAMER_LIB_DEST}"
LIBRARY DESTINATION "${GSTREAMER_LIB_DEST}"
ARCHIVE DESTINATION "${GSTREAMER_LIB_DEST}"
PUBLIC_HEADER DESTINATION "${PUBLIC_HEADER_DEST}"
CONFIGURATIONS Release)

View File

@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 3.0.0)
if (UNIX)
include(find_libs_for_gstreamer_linux.cmake)
elseif (MSVC)
include(find_libs_for_gstreamer_windows.cmake)
else()
message(FATAL_ERROR "HailoRT GStreamer elements compilation is supported only on UNIX or MSVC.")
endif()

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.0.0)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)
pkg_search_module(GSTREAMER REQUIRED gstreamer-1.0)
pkg_search_module(GSTREAMER_BASE REQUIRED gstreamer-base-1.0)
pkg_search_module(GSTREAMER_VIDEO REQUIRED gstreamer-video-1.0)
pkg_search_module(GSTREAMER_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0)

View File

@@ -0,0 +1,87 @@
cmake_minimum_required(VERSION 3.0.0)
# CMake variable GSTREAMER_ROOT_DIR defines the location of the gstreamer files.
# It's default value is C:/gstreamer/1.0/msvc_x86_64.
if (NOT GSTREAMER_ROOT_DIR)
message("Gstreamer Windows compilation - GSTREAMER_ROOT_DIR is not set. default value is C:/gstreamer/1.0/msvc_x86_64")
set(GSTREAMER_ROOT_DIR "C:/gstreamer/1.0/msvc_x86_64")
endif()
set(GLIB_ROOT_DIR ${GSTREAMER_ROOT_DIR})
# Find the GStreamer library and include directories
find_path(GSTREAMER_INCLUDE_DIRS
NAMES gst/gst.h
PATHS ${GSTREAMER_ROOT_DIR}/include/gstreamer-1.0
REQUIRED
)
find_library(GSTREAMER_LIBRARIES
NAMES gstreamer-1.0
PATHS ${GSTREAMER_ROOT_DIR}/lib
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GStreamer DEFAULT_MSG
GSTREAMER_LIBRARIES GSTREAMER_INCLUDE_DIRS
REQUIRED
)
# Find the GStreamer base library and include directories
find_path(GSTREAMER_BASE_INCLUDE_DIRS
NAMES gst/base/base.h
PATHS ${GSTREAMER_ROOT_DIR}/include/gstreamer-1.0
)
find_library(GSTREAMER_BASE_LIBRARIES
NAMES gstbase-1.0
PATHS ${GSTREAMER_ROOT_DIR}/lib
)
find_package_handle_standard_args(GStreamerPluginsBase DEFAULT_MSG
GSTREAMER_BASE_LIBRARIES GSTREAMER_BASE_INCLUDE_DIRS
)
# Find the GStreamer video library and include directories
find_path(GSTREAMER_VIDEO_INCLUDE_DIRS
NAMES gst/video/video.h
PATHS ${GSTREAMER_ROOT_DIR}/include/gstreamer-1.0
)
find_library(GSTREAMER_VIDEO_LIBRARIES
NAMES gstvideo-1.0
PATHS ${GSTREAMER_ROOT_DIR}/lib
)
find_package_handle_standard_args(GStreamerVideo DEFAULT_MSG
GSTREAMER_VIDEO_LIBRARIES GSTREAMER_VIDEO_INCLUDE_DIRS
)
# Find the GLib library and include directories
find_path(GLIB_INCLUDE_DIRS
NAMES glib.h
PATHS ${GLIB_ROOT_DIR}/include/glib-2.0
${GLIB_ROOT_DIR}/lib/glib-2.0/include
REQUIRED
)
find_library(GLIB_LIBRARIES
NAMES glib-2.0
PATHS ${GLIB_ROOT_DIR}/lib
)
find_library(GOBJECT_LIBRARIES
NAMES gobject-2.0
PATHS ${GLIB_ROOT_DIR}/lib
)
# Add the directory containing glibconfig.h to the include directories
find_path(GLIBCONFIG_INCLUDE_DIR
NAMES glibconfig.h
PATHS ${GLIB_ROOT_DIR}/lib/glib-2.0/include
REQUIRED
)
find_package_handle_standard_args(GLib DEFAULT_MSG
GLIB_LIBRARIES GLIB_INCLUDE_DIRS GLIBCONFIG_INCLUDE_DIR
REQUIRED
)

View File

@@ -23,20 +23,22 @@
#include "hailo/device.hpp"
#include "hailo/network_group.hpp"
#include "hailo/vstream.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#include <gst/gst.h>
#pragma GCC diagnostic pop
#include "hailo_gst.h"
#include <vector>
using namespace hailort;
#define ERROR(msg, ...) g_print("HailoNet Error: " msg, ##__VA_ARGS__)
#define GST_HAILO_USE_DMA_BUFFER_ENV_VAR "GST_HAILO_USE_DMA_BUFFER"
#define HAILONET_ERROR(msg, ...) g_print("HailoNet Error: " msg, ##__VA_ARGS__)
#define PLUGIN_AUTHOR "Hailo Technologies Ltd. (\"Hailo\")"
#define MAX_STRING_SIZE (PATH_MAX)
#ifdef _MSC_VER
#define MAX_STRING_SIZE (MAX_PATH)
#else
#define MAX_STRING_SIZE (PATH_MAX)
#endif
#define MAX_QUEUED_BUFFERS_IN_INPUT (16)
#define MAX_QUEUED_BUFFERS_IN_OUTPUT (16)
@@ -115,6 +117,9 @@ using namespace hailort;
#define CHECK_NOT_NULL(arg, status) _CHECK(nullptr != (arg), status, "CHECK_NOT_NULL for %s failed", #arg)
#define CHECK_NOT_NULL_AS_EXPECTED(arg, status) \
_CHECK(nullptr != (arg), make_unexpected(status), "CHECK_NOT_NULL_AS_EXPECTED for %s failed", #arg)
#define _CHECK_SUCCESS(status, ...) \
do { \
const auto &__check_success_status = (status); \
@@ -269,9 +274,6 @@ private:
bool m_was_changed;
};
template<>
HailoElemProperty<gchar*>::~HailoElemProperty();
#define GST_TYPE_SCHEDULING_ALGORITHM (gst_scheduling_algorithm_get_type ())
GType gst_scheduling_algorithm_get_type (void);

View File

@@ -27,33 +27,47 @@ static GstMemory *gst_hailo_allocator_alloc(GstAllocator* allocator, gsize size,
GstHailoAllocator *hailo_allocator = GST_HAILO_ALLOCATOR(allocator);
auto buffer = Buffer::create(size, BufferStorageParams::create_dma());
if (!buffer) {
ERROR("Creating buffer for allocator has failed, status = %d\n", buffer.status());
HAILONET_ERROR("Creating buffer for allocator has failed, status = %d\n", buffer.status());
return nullptr;
}
GstMemory *memory = gst_memory_new_wrapped(static_cast<GstMemoryFlags>(0), buffer->data(),
buffer->size(), 0, buffer->size(), nullptr, nullptr);
if (nullptr == memory) {
ERROR("Creating new GstMemory for allocator has failed!\n");
HAILONET_ERROR("Creating new GstMemory for allocator has failed!\n");
return nullptr;
}
hailo_allocator->buffers[memory] = std::move(buffer.release());
assert(nullptr != hailo_allocator->buffers);
(*hailo_allocator->buffers)[memory] = std::move(buffer.release());
return memory;
}
static void gst_hailo_allocator_free(GstAllocator* allocator, GstMemory *mem) {
GstHailoAllocator *hailo_allocator = GST_HAILO_ALLOCATOR(allocator);
hailo_allocator->buffers.erase(mem);
hailo_allocator->buffers->erase(mem);
}
static void gst_hailo_allocator_dispose(GObject *object) {
GstHailoAllocator *allocator = GST_HAILO_ALLOCATOR(object);
if (allocator->buffers != nullptr) {
delete allocator->buffers;
allocator->buffers = nullptr;
}
G_OBJECT_CLASS(gst_hailo_allocator_parent_class)->dispose(object);
}
static void gst_hailo_allocator_class_init(GstHailoAllocatorClass* klass) {
GstAllocatorClass* allocator_class = GST_ALLOCATOR_CLASS(klass);
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = gst_hailo_allocator_dispose;
GstAllocatorClass* allocator_class = GST_ALLOCATOR_CLASS(klass);
allocator_class->alloc = gst_hailo_allocator_alloc;
allocator_class->free = gst_hailo_allocator_free;
}
static void gst_hailo_allocator_init(GstHailoAllocator* allocator) {
allocator->buffers = std::unordered_map<GstMemory*, Buffer>();
allocator->buffers = new std::unordered_map<GstMemory*, Buffer>();
}

View File

@@ -35,7 +35,7 @@ G_BEGIN_DECLS
struct GstHailoAllocator
{
GstAllocator parent;
std::unordered_map<GstMemory*, Buffer> buffers;
std::unordered_map<GstMemory*, Buffer> *buffers;
};
struct GstHailoAllocatorClass

View File

@@ -39,7 +39,7 @@ static GstMemory *gst_hailo_dmabuf_allocator_alloc(GstAllocator* allocator, gsiz
if (!GstHailoDmaHeapControl::dma_heap_fd_open) {
GstHailoDmaHeapControl::dma_heap_fd = open(DEVPATH, O_RDWR | O_CLOEXEC);
if (GstHailoDmaHeapControl::dma_heap_fd < 0) {
ERROR("open fd failed!\n");
HAILONET_ERROR("open fd failed!\n");
return nullptr;
}
GstHailoDmaHeapControl::dma_heap_fd_open = true;
@@ -55,37 +55,52 @@ static GstMemory *gst_hailo_dmabuf_allocator_alloc(GstAllocator* allocator, gsiz
int ret = ioctl(GstHailoDmaHeapControl::dma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &heap_data);
if (ret < 0) {
ERROR("ioctl DMA_HEAP_IOCTL_ALLOC failed! ret = %d\n", ret);
HAILONET_ERROR("ioctl DMA_HEAP_IOCTL_ALLOC failed! ret = %d\n", ret);
return nullptr;
}
if (GST_IS_DMABUF_ALLOCATOR(hailo_allocator) == false) {
ERROR("hailo_allocator is not dmabuf!\n");
HAILONET_ERROR("hailo_allocator is not dmabuf!\n");
return nullptr;
}
GstMemory *memory = gst_dmabuf_allocator_alloc(allocator, heap_data.fd, size);
if (nullptr == memory) {
ERROR("Creating new GstMemory for allocator has failed!\n");
HAILONET_ERROR("Creating new GstMemory for allocator has failed!\n");
return nullptr;
}
hailo_allocator->dma_buffers[memory] = heap_data;
assert(nullptr != hailo_allocator->dma_buffers);
(*hailo_allocator->dma_buffers)[memory] = heap_data;
return memory;
}
static void gst_hailo_dmabuf_allocator_free(GstAllocator* allocator, GstMemory *mem) {
GstHailoDmabufAllocator *hailo_allocator = GST_HAILO_DMABUF_ALLOCATOR(allocator);
close(hailo_allocator->dma_buffers[mem].fd);
hailo_allocator->dma_buffers.erase(mem);
assert(nullptr != hailo_allocator->dma_buffers);
close((*hailo_allocator->dma_buffers)[mem].fd);
hailo_allocator->dma_buffers->erase(mem);
}
static void gst_hailo_dmabuf_allocator_dispose(GObject *object) {
GstHailoDmabufAllocator *allocator = GST_HAILO_DMABUF_ALLOCATOR(object);
if (nullptr != allocator->dma_buffers) {
delete allocator->dma_buffers;
allocator->dma_buffers = nullptr;
}
G_OBJECT_CLASS(gst_hailo_dmabuf_allocator_parent_class)->dispose(object);
}
static void gst_hailo_dmabuf_allocator_class_init(GstHailoDmabufAllocatorClass* klass) {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
gobject_class->dispose = gst_hailo_dmabuf_allocator_dispose;
GstAllocatorClass* allocator_class = GST_ALLOCATOR_CLASS(klass);
allocator_class->alloc = gst_hailo_dmabuf_allocator_alloc;
allocator_class->free = gst_hailo_dmabuf_allocator_free;
}
static void gst_hailo_dmabuf_allocator_init(GstHailoDmabufAllocator* allocator) {
allocator->dma_buffers = std::unordered_map<GstMemory*, dma_heap_allocation_data>();
allocator->dma_buffers = new std::unordered_map<GstMemory*, dma_heap_allocation_data>();
}

View File

@@ -35,8 +35,6 @@ G_BEGIN_DECLS
#define GST_IS_HAILO_DMABUF_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_HAILO_DMABUF_ALLOCATOR))
#define GST_IS_HAILO_DMABUF_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_HAILO_DMABUF_ALLOCATOR))
#define GST_HAILO_USE_DMA_BUFFER_ENV_VAR "GST_HAILO_USE_DMA_BUFFER"
class GstHailoDmaHeapControl {
public:
static bool dma_heap_fd_open;
@@ -46,7 +44,7 @@ public:
struct GstHailoDmabufAllocator
{
GstDmaBufAllocator parent;
std::unordered_map<GstMemory*, dma_heap_allocation_data> dma_buffers;
std::unordered_map<GstMemory*, dma_heap_allocation_data> *dma_buffers;
};
struct GstHailoDmabufAllocatorClass

View File

@@ -219,8 +219,8 @@ void HailoDeviceStatsImpl::join_thread()
hailo_status HailoDeviceStatsImpl::run_measure_loop()
{
// Checking temperature sensor before starting thread
auto temp_info = m_device->get_chip_temperature();
GST_CHECK_EXPECTED_AS_STATUS(temp_info, m_element, RESOURCE, "Getting chip temperature failed, status = %d", temp_info.status());
auto initial_temp_info = m_device->get_chip_temperature();
GST_CHECK_EXPECTED_AS_STATUS(initial_temp_info, m_element, RESOURCE, "Getting chip temperature failed, status = %d", initial_temp_info.status());
hailo_status status = m_device->stop_power_measurement();
GST_CHECK_SUCCESS(status, m_element, RESOURCE, "Stopping power measurement failed, status = %d", status);

Some files were not shown because too many files have changed in this diff Show More