This commit is contained in:
HailoRT-Automation
2024-12-31 12:38:33 +02:00
committed by GitHub
parent ac19e12b86
commit 542ba8f3cd
515 changed files with 9589 additions and 4211 deletions

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file byte_order.h
* @brief Defines byte order operations.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file context_switch_defs.h
* @brief Declerations of all context switch related structs.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file control_protocol.h
* @brief Defines control protocol.
@@ -160,9 +160,9 @@ extern "C" {
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SET_SLEEP_STATE, false, CPU_ID_APP_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CHANGE_HW_INFER_STATUS, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_SIGNAL_DRIVER_DOWN, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_INIT_CACHE_INFO, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_GET_CACHE_INFO, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_UPDATE_CACHE_READ_OFFSET, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_INIT_CACHE_INFO /* obsolete */, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_GET_CACHE_INFO /* obsolete */, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_UPDATE_CACHE_READ_OFFSET /* obsolete */, false, CPU_ID_CORE_CPU)\
CONTROL_PROTOCOL__OPCODE_X(HAILO_CONTROL_OPCODE_CONTEXT_SWITCH_SIGNAL_CACHE_UPDATED, false, CPU_ID_CORE_CPU)\
typedef enum {
@@ -352,6 +352,7 @@ typedef enum {
CONTROL_PROTOCOL__HAILO8L,
CONTROL_PROTOCOL__HAILO15H,
CONTROL_PROTOCOL__PLUTO,
CONTROL_PROTOCOL__MARS,
/* Must be last!! */
CONTROL_PROTOCOL__DEVICE_ARCHITECTURE_COUNT
} CONTROL_PROTOCOL__device_architecture_t;
@@ -975,27 +976,6 @@ typedef struct {
#pragma warning(pop)
#endif
typedef struct {
uint32_t cache_size;
uint32_t current_read_offset;
int32_t write_offset_delta;
} CONTROL_PROTOCOL__context_switch_cache_info_t;
typedef struct {
uint32_t cache_info_length;
CONTROL_PROTOCOL__context_switch_cache_info_t cache_info;
} CONTROL_PROTOCOL__context_switch_init_cache_info_request_t;
typedef struct {
uint32_t cache_info_length;
CONTROL_PROTOCOL__context_switch_cache_info_t cache_info;
} CONTROL_PROTOCOL__context_switch_get_cache_info_response_t;
typedef struct {
uint32_t read_offset_delta_length;
int32_t read_offset_delta;
} CONTROL_PROTOCOL__context_switch_update_cache_read_offset_request_t;
typedef CONTROL_PROTOCOL__read_memory_request_t CONTROL_PROTOCOL__read_user_config_request_t;
typedef CONTROL_PROTOCOL__read_memory_response_t CONTROL_PROTOCOL__read_user_config_response_t;
typedef CONTROL_PROTOCOL__write_memory_request_t CONTROL_PROTOCOL__write_user_config_request_t;
@@ -1383,7 +1363,6 @@ typedef union {
CONTROL_PROTOCOL__get_overcurrent_state_response_t get_overcurrent_state_response;
CONTROL_PROTOCOL__get_hw_consts_response_t get_hw_consts_response;
CONTROL_PROTOCOL__change_hw_infer_status_response_t change_hw_infer_status_response;
CONTROL_PROTOCOL__context_switch_get_cache_info_response_t context_switch_get_cache_info_response;
// Note: This array is larger than any legal request:
// * Functions in this module won't write more than CONTROL_PROTOCOL__MAX_CONTROL_LENGTH bytes
@@ -1419,8 +1398,6 @@ typedef union {
CONTROL_PROTOCOL__sensor_set_generic_i2c_slave_request_t sensor_set_generic_i2c_slave_request;
CONTROL_PROTOCOL__context_switch_set_network_group_header_request_t context_switch_set_network_group_header_request;
CONTROL_PROTOCOL__context_switch_set_context_info_request_t context_switch_set_context_info_request;
CONTROL_PROTOCOL__context_switch_init_cache_info_request_t context_switch_init_cache_info_request;
CONTROL_PROTOCOL__context_switch_update_cache_read_offset_request_t context_switch_update_cache_read_offset_request;
CONTROL_PROTOCOL__idle_time_set_measurement_request_t idle_time_set_measurement_request;
CONTROL_PROTOCOL__download_context_action_list_request_t download_context_action_list_request;
CONTROL_PROTOCOL__change_context_switch_status_request_t change_context_switch_status_request;

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file d2h_events.h
* @brief Declares all d2h event manager structures relevant in the host.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file firmware_header.h
* @brief Contains definitions needed for generating and handling a firmware header.
@@ -19,7 +19,7 @@ extern "C" {
#define FIRMWARE_HEADER_MAGIC_HAILO8 (0x1DD89DE0)
#define FIRMWARE_HEADER_MAGIC_HAILO15 (0xE905DAAB)
#define FIRMWARE_HEADER_MAGIC_PLUTO (0xF94739AB)
#define FIRMWARE_HEADER_MAGIC_HAILO15L (0xF94739AB)
typedef enum {
FIRMWARE_HEADER_VERSION_INITIAL = 0,
@@ -31,7 +31,7 @@ typedef enum {
typedef enum {
FIRMWARE_TYPE_HAILO8 = 0,
FIRMWARE_TYPE_HAILO15,
FIRMWARE_TYPE_PLUTO
FIRMWARE_TYPE_HAILO15L
} firmware_type_t;
@@ -40,7 +40,7 @@ typedef enum {
#elif defined(HAILO8_B0)
#define COMPILED_FIRMWARE_TYPE (FIRMWARE_TYPE_HAILO8)
#elif defined(PLUTO)
#define COMPILED_FIRMWARE_TYPE (FIRMWARE_TYPE_PLUTO)
#define COMPILED_FIRMWARE_TYPE (FIRMWARE_TYPE_HAILO15L)
#endif /* MERCURY */
typedef struct {

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file firmware_header_utils.h
* @brief Utilities for working with the firmware header.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file firmware_status.h
* @brief Defines firmware status codes.
@@ -661,12 +661,12 @@ Updating rules:
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_RECEIVED_INVALID_ACTION_TYPE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_UNDEFINED_MAPPING_FOR_SHIMFO)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_MISSMATCH_BETWEEN_TRIGGER_DIRECTION_AND_MAPPING_DIRECTION)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_SLICING_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_TRIGGER_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_ACTION_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_CONTEXT_INFO_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_PARSING_ERROR_WHILE_READING_TRIGGER_GROUPS)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_POINTER_REACHED_FORBIDDEN_MEMORY_SPACE)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_SLICING_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_TRIGGER_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_ACTION_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_ADD_CONTEXT_INFO_FUNCTION_REACHED_FORBIDDEN_MEMORY_SPACE)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_PARSING_ERROR_WHILE_READING_TRIGGER_GROUPS)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_POINTER_REACHED_FORBIDDEN_MEMORY_SPACE)/* DEPRECATED */\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_DOWNLOAD_ACTION_LIST_INVALID_CONTEXT_INDEX)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_RECEIVED_INVALID_APPLICATION_COUNT)\
FIRMWARE_STATUS__X(CONTEXT_SWITCH_TASK_STATUS_RECEIVED_INVALID_TOTAL_CONTEXTS_COUNT)\
@@ -770,6 +770,7 @@ Updating rules:
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_STATUS__X(CONTEXT_SWITCH_STATUS_SRAM_MEMORY_FULL)\
\
FIRMWARE_MODULE__X(FIRMWARE_MODULE__D2H_EVENT_MANAGER)\
FIRMWARE_STATUS__X(HAILO_D2H_EVENT_MANAGER_STATUS_MESSAGE_HIGH_PRIORITY_QUEUE_CREATE_FAILED)\

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file firmware_version.h
* @brief Contains information regarding the firmware version.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file logger_level.h
* @brief Contains the possible logger level information.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file sensor_config_exports.h
* @brief Sensor config exported defines.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file status.h
* @brief Declares status enum for hailo c platform.

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file stdfloat.h
* @brief Defines fixed-size float types.

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**

View File

@@ -1,5 +1,5 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file firmware_header_utils.c
* @brief Utilities for working with the firmware header.
@@ -50,8 +50,8 @@ static HAILO_COMMON_STATUS_t firmware_header_utils__validate_fw_header(uintptr_t
case FIRMWARE_TYPE_HAILO15:
firmware_magic = FIRMWARE_HEADER_MAGIC_HAILO15;
break;
case FIRMWARE_TYPE_PLUTO:
firmware_magic = FIRMWARE_HEADER_MAGIC_PLUTO;
case FIRMWARE_TYPE_HAILO15L:
firmware_magic = FIRMWARE_HEADER_MAGIC_HAILO15L;
break;
default:
status = HAILO_STATUS__FIRMWARE_HEADER_UTILS__INVALID_FIRMWARE_TYPE;

View File

@@ -1,7 +1,7 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
**/
/**
* @file firmware_status.c
* @brief Defines firmware status codes.

View File

@@ -29,7 +29,7 @@ endif()
# Set firmware version
add_definitions( -DFIRMWARE_VERSION_MAJOR=4 )
add_definitions( -DFIRMWARE_VERSION_MINOR=19 )
add_definitions( -DFIRMWARE_VERSION_MINOR=20 )
add_definitions( -DFIRMWARE_VERSION_REVISION=0 )
if(HAILO_BUILD_SERVICE)
add_definitions( -DHAILO_SUPPORT_MULTI_PROCESS )
@@ -59,10 +59,7 @@ set(HRPC_DIR ${PROJECT_SOURCE_DIR}/hailort/hrpc)
set(HRPC_PROTOCOL_DIR ${PROJECT_SOURCE_DIR}/hailort/hrpc_protocol)
set(HAILORT_SERVICE_DIR ${PROJECT_SOURCE_DIR}/hailort/hailort_service)
set(HAILORT_SERVER_DIR ${PROJECT_SOURCE_DIR}/hailort/hailort_server)
if(CMAKE_SYSTEM_NAME STREQUAL QNX)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/pevents.cmake)
endif()
set(HAILORT_LIBUSB_DIR ${PROJECT_SOURCE_DIR}/hailort/internals/libusb-wrapper/)
if(HAILO_BUILD_SERVICE)
add_subdirectory(rpc)
@@ -74,9 +71,8 @@ add_subdirectory(hrpc_protocol)
add_subdirectory(libhailort)
add_subdirectory(hailortcli)
if(HAILO_INTERNAL_BUILD)
add_subdirectory(tools/hw_debug)
add_subdirectory(tools/pcie_tunnel)
add_subdirectory(tools/loopback_server)
add_subdirectory(tools)
add_subdirectory(internals)
endif()
if(HAILO_BUILD_SERVICE)

View File

@@ -1,5 +1,5 @@
| Package | Copyright (c) | License | Version | Notes | References |
|:---------------------------------|:----------------------------------|:---------------------------|:---------------|:----------------------------------------------|:------------------------------------------------------------------------------|
|:---------------------------------|:----------------------------------|:-----------------------------------|:---------------|:-----------------------------------------------------|:------------------------------------------------------------------------------|
| CLI11 | University of Cincinnati | 3-Clause BSD | 2.2.0 | Fork | https://github.com/hailo-ai/CLI11 |
| 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 |
@@ -12,6 +12,8 @@
| benchmark | Google Inc. | Apache License 2.0 | 1.6.0 | Cloned entire package | https://github.com/google/benchmark.git |
| md5 | Alexander Peslyak | cut-down BSD | - | Copied code from website | http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 |
| pevents | Mahmoud Al-Qudsi | MIT License | master | Cloned entire package | https://github.com/neosmart/pevents.git |
| grpc | Google Inc. | Apache License 2.0 | 1.46.3 | Cloned entire package | https://github.com/grpc/grpc |
| grpc | Google Inc. | Apache License 2.0 | 1.54.0 | Cloned entire package | https://github.com/grpc/grpc |
| stb | Sean Barrett | MIT License | 0.97 | Copied only the file `stb/stb_image_resize.h` | https://github.com/nothings/stb |
| eigen | | Mozilla Public License 2.0 | 3.4.0 | Cloned entire package | https://gitlab.com/libeigen/eigen |
| libusb | | GNU LESSER GENERAL PUBLIC LICENSE | 1.0.27 | Cloned entire package | https://github.com/libusb/libusb.git |
| xxHash | Yann Collet | 2-Clause BSD | 0.8.2 | Cloned entire package, used as a header-only lib | https://github.com/Cyan4973/xxHash |

View File

@@ -6,7 +6,7 @@ include(FetchContent)
FetchContent_Declare(
grpc
GIT_REPOSITORY https://github.com/grpc/grpc
GIT_TAG 53d69cc581c5b7305708587f4f1939278477c28a # v1.46.3
GIT_TAG 6847e05dbb8088a918f06e2231a405942b5c002d # v1.54.0
GIT_SHALLOW TRUE
SOURCE_DIR ${HAILO_EXTERNAL_DIR}/grpc-src
SUBBUILD_DIR ${HAILO_EXTERNAL_DIR}/grpc-subbuild

256
hailort/cmake/external/libusb.cmake vendored Normal file
View File

@@ -0,0 +1,256 @@
cmake_minimum_required(VERSION 3.11.0)
include(FetchContent)
FetchContent_Declare(
libusb
GIT_REPOSITORY https://github.com/libusb/libusb.git
GIT_TAG d52e355daa09f17ce64819122cb067b8a2ee0d4b # Version 1.0.27
GIT_SHALLOW TRUE
SOURCE_DIR ${HAILO_EXTERNAL_DIR}/libusb-src
SUBBUILD_DIR ${HAILO_EXTERNAL_DIR}/libusb-subbuild
)
# https://stackoverflow.com/questions/65527126/disable-install-for-fetchcontent
# Note this cmakeFile is taken from https://github.com/libusb/libusb-cmake and modified to work with our build system
FetchContent_GetProperties(libusb)
if(NOT libusb_POPULATED)
FetchContent_Populate(libusb)
if (NOT HAILO_EXTERNALS_EXCLUDE_TARGETS)
set(LIBUSB_ROOT ${HAILO_EXTERNAL_DIR}/libusb-src/libusb/)
# Get the version information from version.h ignoring the nano version as it appears in version_nano.h and so we need it?
file(READ "${LIBUSB_ROOT}/version.h" VERSIONHEADERDATA)
string(REGEX MATCH "#define LIBUSB_MAJOR ([0-9]*)" _ ${VERSIONHEADERDATA})
set(LIBUSB_VERSION_MAJOR ${CMAKE_MATCH_1})
string(REGEX MATCH "#define LIBUSB_MINOR ([0-9]*)" _ ${VERSIONHEADERDATA})
set(LIBUSB_VERSION_MINOR ${CMAKE_MATCH_1})
string(REGEX MATCH "#define LIBUSB_MICRO ([0-9]*)" _ ${VERSIONHEADERDATA})
set(LIBUSB_VERSION_MICRO ${CMAKE_MATCH_1})
set(LIBUSB_VERSION "${LIBUSB_VERSION_MAJOR}.${LIBUSB_VERSION_MINOR}.${LIBUSB_VERSION_MICRO}")
project(usb-1.0
DESCRIPTION "A cross-platform library to access USB devices"
VERSION ${LIBUSB_VERSION}
LANGUAGES C
)
if(EMSCRIPTEN)
set(CMAKE_CXX_STANDARD 20)
enable_language(CXX)
endif()
# This function generates all the local variables what end up getting written to config.
# We use a function as any vars set in this context don't mess with the rest of the file.
# e.g. Logging LIBUSB_ENABLE_LOGGING mapps to ENABLE_LOGGING in the config, keeps it clean
function(generate_config_file)
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(CheckStructHasMember)
include(CheckCCompilerFlag)
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
check_function_exists(pthread_condattr_setclock HAVE_PTHREAD_CONDATTR_SETCLOCK)
check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP)
check_function_exists(pthread_threadid_np HAVE_PTHREAD_THREADID_NP)
check_function_exists(eventfd HAVE_EVENTFD)
check_function_exists(pipe2 HAVE_PIPE2)
check_function_exists(syslog HAVE_SYSLOG)
check_include_files(asm/types.h HAVE_ASM_TYPES_H)
check_include_files(sys/eventfd.h HAVE_EVENTFD)
check_include_files(string.h HAVE_STRING_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H)
check_symbol_exists(timerfd_create "sys/timerfd.h" HAVE_TIMERFD)
check_symbol_exists(nfds_t "poll.h" HAVE_NFDS_T)
check_struct_has_member("struct timespec" tv_sec time.h HAVE_STRUCT_TIMESPEC)
if(HAVE_VISIBILITY)
set(DEFAULT_VISIBILITY "__attribute__((visibility(\"default\")))")
else()
set(DEFAULT_VISIBILITY "" )
endif()
# Set vars that will be written into the config file.
if(WIN32)
set(PLATFORM_WINDOWS 1)
else()
set(PLATFORM_POSIX 1)
endif()
if(LIBUSB_ENABLE_LOGGING)
set(ENABLE_LOGGING ${LIBUSB_ENABLE_LOGGING})
endif()
if(LIBUSB_ENABLE_DEBUG_LOGGING)
set(ENABLE_DEBUG_LOGGING ${LIBUSB_ENABLE_DEBUG_LOGGING})
endif()
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
check_c_compiler_flag("-fvisibility=hidden" HAVE_VISIBILITY)
endif()
file(MAKE_DIRECTORY "${LIBUSB_GEN_INCLUDES}")
if(NOT MSVC)
set(_GNU_SOURCE TRUE)
endif()
configure_file("${HAILORT_LIBUSB_DIR}/config.h.in" "${LIBUSB_GEN_INCLUDES}/config.h" @ONLY)
endfunction()
if(BUILD_SHARED_LIBS)
set(LIBUSB_BUILD_SHARED_LIBS_DEFAULT ON)
else()
set(LIBUSB_BUILD_SHARED_LIBS_DEFAULT OFF)
endif()
option(LIBUSB_BUILD_SHARED_LIBS "Build Shared Libraries for libusb" ${LIBUSB_BUILD_SHARED_LIBS_DEFAULT})
option(LIBUSB_BUILD_TESTING "Build Tests" OFF)
if(LIBUSB_BUILD_TESTING)
enable_testing()
endif()
option(LIBUSB_BUILD_EXAMPLES "Build Example Applications" OFF)
option(LIBUSB_INSTALL_TARGETS "Install libusb targets" ON)
option(LIBUSB_TARGETS_INCLUDE_USING_SYSTEM "Make targets include paths System" ON)
option(LIBUSB_ENABLE_LOGGING "Enable Logging" ON)
option(LIBUSB_ENABLE_DEBUG_LOGGING "Enable Debug Logging" OFF)
# Dont use libudev on linux currently
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
option(LIBUSB_ENABLE_UDEV "Enable udev backend for device enumeration" OFF)
endif()
set(LIBUSB_GEN_INCLUDES "${CMAKE_CURRENT_BINARY_DIR}/gen_include")
generate_config_file()
if(LIBUSB_BUILD_SHARED_LIBS)
add_library(usb-1.0 SHARED)
else()
add_library(usb-1.0 STATIC)
endif()
set_target_properties(usb-1.0 PROPERTIES
PREFIX lib # to be consistent with mainline libusb build system(s)
)
# common sources
target_sources(usb-1.0 PRIVATE
"${LIBUSB_GEN_INCLUDES}/config.h"
"${LIBUSB_ROOT}/core.c"
"${LIBUSB_ROOT}/descriptor.c"
"${LIBUSB_ROOT}/hotplug.c"
"${LIBUSB_ROOT}/io.c"
"${LIBUSB_ROOT}/libusb.h"
"${LIBUSB_ROOT}/libusbi.h"
"${LIBUSB_ROOT}/strerror.c"
"${LIBUSB_ROOT}/sync.c"
"${LIBUSB_ROOT}/version.h"
"${LIBUSB_ROOT}/version_nano.h"
)
target_include_directories(usb-1.0
PRIVATE
"${LIBUSB_GEN_INCLUDES}"
"${LIBUSB_ROOT}/os"
)
if (LIBUSB_TARGETS_INCLUDE_USING_SYSTEM)
target_include_directories(usb-1.0 SYSTEM PUBLIC "${LIBUSB_ROOT}")
else()
target_include_directories(usb-1.0 PUBLIC "${LIBUSB_ROOT}")
endif()
if(WIN32)
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/libusb-1.0.def"
"${LIBUSB_ROOT}/os/events_windows.c"
"${LIBUSB_ROOT}/os/events_windows.h"
"${LIBUSB_ROOT}/os/threads_windows.c"
"${LIBUSB_ROOT}/os/threads_windows.h"
"${LIBUSB_ROOT}/os/windows_common.c"
"${LIBUSB_ROOT}/os/windows_common.h"
"${LIBUSB_ROOT}/os/windows_usbdk.c"
"${LIBUSB_ROOT}/os/windows_usbdk.h"
"${LIBUSB_ROOT}/os/windows_winusb.c"
"${LIBUSB_ROOT}/os/windows_winusb.h"
$<$<C_COMPILER_ID:MSVC>:${LIBUSB_ROOT}/libusb-1.0.rc>
)
target_compile_definitions(usb-1.0 PRIVATE $<$<C_COMPILER_ID:MSVC>:_CRT_SECURE_NO_WARNINGS=1>)
target_link_libraries(usb-1.0 PRIVATE windowsapp)
else()
# common POSIX/non-Windows sources
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/events_posix.c"
"${LIBUSB_ROOT}/os/events_posix.h"
"${LIBUSB_ROOT}/os/threads_posix.c"
"${LIBUSB_ROOT}/os/threads_posix.h"
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/linux_usbfs.c"
"${LIBUSB_ROOT}/os/linux_usbfs.h"
)
if(LIBUSB_ENABLE_UDEV)
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/linux_udev.c"
)
target_link_libraries(usb-1.0 PRIVATE udev)
target_compile_definitions(usb-1.0 PRIVATE HAVE_LIBUDEV=1)
else()
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/linux_netlink.c"
)
endif()
find_package(Threads REQUIRED)
target_link_libraries(usb-1.0 PRIVATE Threads::Threads)
elseif(ANDROID)
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/linux_netlink.c"
"${LIBUSB_ROOT}/os/linux_usbfs.c"
"${LIBUSB_ROOT}/os/linux_usbfs.h"
)
target_link_libraries(usb-1.0 PRIVATE android log)
elseif(APPLE)
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/darwin_usb.c"
"${LIBUSB_ROOT}/os/darwin_usb.h"
)
target_link_libraries(usb-1.0 PRIVATE
"-framework Foundation"
"-framework IOKit"
"-framework Security"
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/netbsd_usb.c"
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/openbsd_usb.c"
)
elseif(EMSCRIPTEN)
target_sources(usb-1.0 PRIVATE
"${LIBUSB_ROOT}/os/emscripten_webusb.cpp"
)
target_compile_options(usb-1.0 PRIVATE -pthread)
else()
message(FATAL_ERROR "Unsupported target platform: ${CMAKE_SYSTEM_NAME}")
endif()
endif()
if(LIBUSB_BUILD_TESTING)
add_subdirectory(tests)
endif()
if(LIBUSB_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
if(LIBUSB_INSTALL_TARGETS)
install(TARGETS usb-1.0)
install(FILES "${LIBUSB_ROOT}/libusb.h" DESTINATION "include/libusb-1.0")
endif()
endif()
endif()

23
hailort/cmake/external/xxhash.cmake vendored Normal file
View File

@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.11.0)
include(FetchContent)
FetchContent_Declare(
xxhash
GIT_REPOSITORY https://github.com/Cyan4973/xxHash
GIT_TAG bbb27a5efb85b92a0486cf361a8635715a53f6ba # Version 0.8.2
GIT_SHALLOW TRUE
SOURCE_DIR ${HAILO_EXTERNAL_DIR}/xxhash-src
SUBBUILD_DIR ${HAILO_EXTERNAL_DIR}/xxhash-subbuild
)
# https://stackoverflow.com/questions/65527126/disable-install-for-fetchcontent
FetchContent_GetProperties(xxhash)
if(NOT xxhash_POPULATED)
FetchContent_Populate(xxhash)
if (NOT HAILO_EXTERNALS_EXCLUDE_TARGETS)
# Add xxhash as a header-only library
add_library(xxhash INTERFACE)
target_include_directories(xxhash INTERFACE ${xxhash_SOURCE_DIR})
endif()
endif()

View File

@@ -1,27 +1,15 @@
cmake_minimum_required(VERSION 3.5.0)
if(WIN32)
set(HAILORT_COMMON_OS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/os/windows")
elseif(UNIX)
set(HAILORT_COMMON_OS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/os/posix")
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
set(HAILORT_COMMON_OS_DIR ${HAILORT_COMMON_OS_DIR} PARENT_SCOPE)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/spdlog.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/readerwriterqueue.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/xxhash.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/common_compiler_options.cmake)
set(SRC_FILES
${HAILORT_COMMON_OS_DIR}/ethernet_utils.cpp
${HAILORT_COMMON_OS_DIR}/filesystem.cpp
${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
set(HAILORT_COMMON_CPP_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/utils.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
@@ -30,18 +18,55 @@ set(SRC_FILES
)
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
)
add_subdirectory(os/windows)
elseif(UNIX)
# Unix only modules
set(SRC_FILES ${SRC_FILES}
${HAILORT_COMMON_OS_DIR}/traffic_control.cpp
)
add_subdirectory(os/posix)
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
# Create static library hailort_common
add_library(hailort_common STATIC ${HAILORT_COMMON_CPP_SOURCES})
target_include_directories(hailort_common
PUBLIC
$<BUILD_INTERFACE:${HAILORT_INC_DIR}>
$<BUILD_INTERFACE:${HAILORT_COMMON_DIR}>
$<BUILD_INTERFACE:${COMMON_INC_DIR}>
)
set(HAILORT_COMMON_CPP_SOURCES ${SRC_FILES} PARENT_SCOPE)
target_link_libraries(hailort_common
PUBLIC
spdlog::spdlog
readerwriterqueue
xxhash
)
if(CMAKE_SYSTEM_NAME STREQUAL QNX)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/pevents.cmake)
target_link_libraries(hailort_common PRIVATE pevents pci)
endif()
set_target_properties(hailort_common PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
POSITION_INDEPENDENT_CODE ON
)
target_compile_options(hailort_common PRIVATE ${HAILORT_COMPILE_OPTIONS})
disable_exceptions(hailort_common)
exclude_archive_libs_symbols(hailort_common)
if(WIN32)
target_link_libraries(hailort_common PRIVATE
Ws2_32 # Winsock2 API
Iphlpapi # IP Helper API (i.e GetIpNetTable)
Shlwapi # Shell API (i.e PathIsDirectoryA)
)
elseif(NOT CMAKE_SYSTEM_NAME STREQUAL Android)
# TODO: HRT-14770 fix android build
target_link_libraries(hailort_common PRIVATE
rt # Used for shm api (i.e shm_open)
)
endif()

View File

@@ -55,4 +55,32 @@ size_t BasicBufferPool::buffer_size()
return m_buffer_size;
}
Expected<std::shared_ptr<DmaAbleBufferPool>> DmaAbleBufferPool::create_shared(size_t buffer_size, size_t buffer_count,
EventPtr shutdown_event)
{
TRY(auto free_buffers_queue,
SpscQueue<BufferPtr>::create(buffer_count, shutdown_event, DEFAULT_TRANSFER_TIMEOUT));
std::vector<BufferPtr> buffers;
buffers.reserve(buffer_count);
for (size_t i = 0; i < buffer_count; i++) {
TRY(auto buffer_ptr, Buffer::create_shared(buffer_size, BufferStorageParams::create_dma()));
auto status = free_buffers_queue.enqueue(buffer_ptr);
CHECK_SUCCESS(status);
buffers.emplace_back(buffer_ptr);
}
auto ptr = make_shared_nothrow<DmaAbleBufferPool>(buffer_size, std::move(buffers), std::move(free_buffers_queue), buffer_count);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
DmaAbleBufferPool::DmaAbleBufferPool(size_t buffer_size, std::vector<BufferPtr> &&buffers,
SpscQueue<BufferPtr> &&free_buffers_queue, size_t buffers_count) :
BasicBufferPool(buffer_size, std::move(buffers), std::move(free_buffers_queue), buffers_count)
{}
} /* namespace hailort */

View File

@@ -50,6 +50,23 @@ private:
};
using BasicBufferPoolPtr = std::shared_ptr<BasicBufferPool>;
// TODO: HRT-12690 - DMA buffer pool is also used in the service - code duplication
class DmaAbleBufferPool : public BasicBufferPool
{
public:
static Expected<std::shared_ptr<DmaAbleBufferPool>> create_shared(size_t buffer_size, size_t buffer_count,
EventPtr shutdown_event);
DmaAbleBufferPool(size_t buffer_size, std::vector<BufferPtr> &&buffers,
SpscQueue<BufferPtr> &&m_free_buffers_queue, size_t buffers_count);
DmaAbleBufferPool(DmaAbleBufferPool &&) = delete;
DmaAbleBufferPool(const DmaAbleBufferPool &) = delete;
DmaAbleBufferPool &operator=(DmaAbleBufferPool &&) = delete;
DmaAbleBufferPool &operator=(const DmaAbleBufferPool &) = delete;
virtual ~DmaAbleBufferPool() = default;
};
using DmaAbleBufferPoolPtr = std::shared_ptr<DmaAbleBufferPool>;
} /* namespace hailort */
#endif /* _HAILO_BUFFER_POOL_HPP_ */

View File

@@ -14,29 +14,6 @@
namespace hailort
{
Waitable::Waitable(underlying_waitable_handle_t handle) :
m_handle(handle)
{}
hailo_status Waitable::wait(std::chrono::milliseconds timeout)
{
auto status = wait_for_single_object(m_handle, timeout);
if (HAILO_TIMEOUT == status) {
LOGGER__TRACE("wait_for_single_object failed with timeout (timeout={}ms)", timeout.count());
return status;
}
CHECK_SUCCESS(status);
status = post_wait();
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
underlying_waitable_handle_t Waitable::get_underlying_handle()
{
return m_handle;
}
WaitOrShutdown::WaitOrShutdown(WaitablePtr waitable, EventPtr shutdown_event) :
m_waitable(waitable),

View File

@@ -49,6 +49,30 @@ Expected<Buffer> read_binary_file(const std::string &file_path, const BufferStor
return buffer;
}
Expected<StreamPositionGuard> StreamPositionGuard::create(std::shared_ptr<std::ifstream> stream)
{
CHECK_AS_EXPECTED((nullptr != stream), HAILO_INVALID_ARGUMENT);
const auto beg_pos = stream->tellg();
CHECK_AS_EXPECTED((-1 != beg_pos), HAILO_INTERNAL_FAILURE, "ifstream::tellg() failed");
return StreamPositionGuard(stream, beg_pos);
}
StreamPositionGuard::StreamPositionGuard(std::shared_ptr<std::ifstream> stream, std::streampos beg_pos) :
m_stream(stream),
m_beg_pos(beg_pos)
{}
StreamPositionGuard::~StreamPositionGuard()
{
m_stream->seekg(m_beg_pos, std::ios::beg);
if (!m_stream->good()) {
LOGGER__ERROR("ifstream::seekg() failed");
return;
}
}
Expected<std::shared_ptr<FileReader>> SeekableBytesReader::create_reader(const std::string &file_path)
{
auto ptr = make_shared_nothrow<FileReader>(file_path);

View File

@@ -27,6 +27,20 @@ Expected<size_t> get_istream_size(std::ifstream &s);
Expected<Buffer> read_binary_file(const std::string &file_path,
const BufferStorageParams &output_buffer_params = {});
// This class is an RAII to return to the original stream position
class StreamPositionGuard
{
public:
static Expected<StreamPositionGuard> create(std::shared_ptr<std::ifstream> stream);
~StreamPositionGuard();
private:
StreamPositionGuard(std::shared_ptr<std::ifstream> stream, std::streampos beg_pos);
std::shared_ptr<std::ifstream> m_stream;
const std::streampos m_beg_pos;
};
class FileReader;
class BufferReader;

View File

@@ -40,6 +40,15 @@ public:
static std::string get_home_directory();
static bool is_path_accesible(const std::string &path);
static bool does_file_exists(const std::string &path);
/**
* Gets the path to the temporary directory.
*
* @return Upon success, returns Expected of the temporary directory path string, ending with / on posix systems
* or with \ on windows systems. Otherwise, returns Unexpected of ::hailo_status error.
*/
static Expected<std::string> get_temp_path();
static bool has_suffix(const std::string &file_name, const std::string &suffix)
{
return (file_name.size() >= suffix.size()) && equal(suffix.rbegin(), suffix.rend(), file_name.rbegin());

View File

@@ -33,20 +33,29 @@ namespace hailort
/* 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")
/* Forces Hailo session based on socket to use a specific device. This env var should be set to the iface name (i.e eth0) */
#define HAILO_SOCKET_BIND_TO_INTERFACE_ENV_VAR ("HAILO_SOCKET_BIND_TO_INTERFACE")
/* 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")
/* Overrides hRPC requests timeout. value in seconds */
#define HAILO_REQUEST_TIMEOUT_SECONDS ("HAILO_REQUEST_TIMEOUT_SECONDS")
/* 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`*/
HAILORT_AUTO_UPDATE_CACHE_OFFSET_ENV_VAR_DISABLED, or to a numeric value defining the offset update value in entries`*/
#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")
/* Corresponds to CacheManager::update_cache_offset(check_snapshots, require_changes) */
#define HAILORT_CHECK_CACHE_UPDATE_ENV_VAR ("HAILORT_CHECK_CACHE_UPDATE")
#define HAILORT_REQUIRE_CACHE_CHANGES_ENV_VAR ("HAILORT_REQUIRE_CACHE_CHANGES")
/* Used for the internal CLI mode `measure-nnc-performance` */
#define HAILO_CONFIGURE_FOR_HW_INFER_ENV_VAR ("HAILO_CONFIGURE_FOR_HW_INFER")

View File

@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.5.0)
if (CMAKE_SYSTEM_NAME STREQUAL QNX)
add_subdirectory(qnx)
else()
add_subdirectory(linux)
endif()
set(HAILORT_COMMON_CPP_SOURCES ${HAILORT_COMMON_CPP_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/ethernet_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/filesystem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/socket.cpp
${CMAKE_CURRENT_SOURCE_DIR}/process.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file_descriptor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mmap_buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shared_memory_buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/traffic_control.cpp
PARENT_SCOPE
)

View File

@@ -217,6 +217,11 @@ bool Filesystem::does_file_exists(const std::string &path)
return (0 == stat(path.c_str(), &buffer));
}
Expected<std::string> Filesystem::get_temp_path()
{
return std::string("/tmp/");
}
Expected<TempFile> TempFile::create(const std::string &file_name, const std::string &file_directory)
{
if (!file_directory.empty()) {

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.5.0)
set(HAILORT_COMMON_CPP_SOURCES ${HAILORT_COMMON_CPP_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/event_os_specific.cpp
PARENT_SCOPE
)

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file event_os_specific.cpp
* @brief Event/semaphore OS specific implementation for linux using eventfd
**/
#include "common/event_internal.hpp"
#include "common/utils.hpp"
namespace hailort
{
Expected<size_t> WaitableGroup::wait_any(std::chrono::milliseconds timeout)
{
int poll_ret = -1;
do {
poll_ret = poll(m_waitable_handles.data(), m_waitable_handles.size(), static_cast<int>(timeout.count()));
} while ((0 > poll_ret) && (EINTR == poll_ret));
if (0 == poll_ret) {
LOGGER__TRACE("Timeout");
return make_unexpected(HAILO_TIMEOUT);
}
CHECK_AS_EXPECTED(poll_ret > 0, HAILO_INTERNAL_FAILURE, "poll failed with errno={}", errno);
for (size_t index = 0; index < m_waitable_handles.size(); index++) {
if (m_waitable_handles[index].revents & POLLIN) {
auto status = m_waitables[index].get().post_wait();
CHECK_SUCCESS_AS_EXPECTED(status);
return index;
}
}
LOGGER__ERROR("None of the pollfd are in read state");
return make_unexpected(HAILO_INTERNAL_FAILURE);
}
} /* namespace hailort */

View File

@@ -8,7 +8,6 @@
**/
#include "common/mmap_buffer.hpp"
#include "vdma/driver/hailort_driver.hpp"
#include <sys/ioctl.h>
#include <sys/mman.h>

View File

@@ -15,6 +15,7 @@
#include <unistd.h>
#include <signal.h>
#include <sched.h>
#include <sys/syscall.h>
#if defined(__QNX__)
#define OS_UTILS__QNX_PAGE_SIZE (4096)
@@ -36,6 +37,11 @@ uint32_t OsUtils::get_curr_pid()
return getpid();
}
uint32_t OsUtils::get_curr_tid()
{
return static_cast<uint32_t>(syscall(SYS_gettid));
}
bool OsUtils::is_pid_alive(uint32_t pid)
{
return (0 == kill(pid, EXISTENCE_CHECK_SIGNAL));

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.5.0)
set(HAILORT_COMMON_CPP_SOURCES ${HAILORT_COMMON_CPP_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/event_os_specific.cpp
PARENT_SCOPE
)

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file event_os_specific.cpp
* @brief Event/semaphore OS specific implementation for qnx using pevents
**/
#include "common/event_internal.hpp"
#include "common/utils.hpp"
#define WFMO
#include "pevents.h"
#undef WFMO
namespace hailort
{
Expected<size_t> WaitableGroup::wait_any(std::chrono::milliseconds timeout)
{
int wait_index = -1;
const uint64_t timeout_ms = (timeout.count() > INT_MAX) ? INT_MAX : static_cast<uint64_t>(timeout.count());
const bool WAIT_FOR_ANY = false;
const auto wait_result = neosmart::WaitForMultipleEvents(m_waitable_handles.data(),
static_cast<int>(m_waitable_handles.size()), WAIT_FOR_ANY, timeout_ms, wait_index);
if (0 != wait_result) {
if (ETIMEDOUT == wait_result) {
return make_unexpected(HAILO_TIMEOUT);
} else {
LOGGER__ERROR("WaitForMultipleEvents Failed, error: {}", wait_result);
return make_unexpected(HAILO_INTERNAL_FAILURE);
}
}
auto status = m_waitables[wait_index].get().post_wait();
CHECK_SUCCESS_AS_EXPECTED(status);
return wait_index;
}
} /* namespace hailort */

View File

@@ -34,11 +34,7 @@ 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(auto module_wrapper_ptr, SocketModuleWrapper::create_shared());
TRY(const auto socket_fd, create_socket_fd(af, type, protocol));
auto obj = Socket(module_wrapper_ptr, socket_fd);
@@ -73,6 +69,7 @@ hailo_status Socket::close_socket_fd()
if (INVALID_SOCKET != m_socket_fd) {
int socket_rc = close(m_socket_fd);
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed to close socket. errno={}", errno);
m_socket_fd = INVALID_SOCKET;
}
return HAILO_SUCCESS;
@@ -147,20 +144,6 @@ Expected<size_t> Socket::send(const uint8_t *buffer, size_t size, int flags)
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);
@@ -180,9 +163,9 @@ hailo_status Socket::pton(int af, const char *src, void *dst)
CHECK_ARG_NOT_NULL(dst);
inet_rc = inet_pton(af, reinterpret_cast<const char*>(src), dst);
if (1 != inet_rc) {
return HAILO_ETH_FAILURE;
}
CHECK(0 != inet_rc, HAILO_ETH_FAILURE,
"Failed to run 'inet_pton'. src is not a valid network address in the specified address family");
CHECK(1 == inet_rc, HAILO_ETH_FAILURE, "Failed to run 'inet_pton', errno = {}.", errno);
return HAILO_SUCCESS;
}
@@ -269,6 +252,13 @@ hailo_status Socket::allow_reuse_address()
return HAILO_SUCCESS;
}
hailo_status Socket::bind_to_device(const std::string &device_name)
{
int socket_rc = setsockopt(m_socket_fd, SOL_SOCKET, SO_BINDTODEVICE, device_name.c_str(), static_cast<socklen_t>(device_name.size()));
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Cannot bind socket to device {}", device_name);
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

@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.5.0)
set(HAILORT_COMMON_CPP_SOURCES ${HAILORT_COMMON_CPP_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/ethernet_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/filesystem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/socket.cpp
${CMAKE_CURRENT_SOURCE_DIR}/process.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_utils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/file_descriptor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mmap_buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shared_memory_buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/string_conversion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/virtual_alloc_guard.cpp
${CMAKE_CURRENT_SOURCE_DIR}/named_mutex_guard.cpp
${CMAKE_CURRENT_SOURCE_DIR}/event_os_specific.cpp
PARENT_SCOPE
)

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 event_os_specific.cpp
* @brief Event/semaphore OS specific implementation for windows using event/semaphore HANDLE
**/
#include "common/event_internal.hpp"
#include "common/utils.hpp"
namespace hailort
{
static DWORD timeout_millies(long long value)
{
DWORD millies = static_cast<DWORD>(value);
if (UINT_MAX < value) {
millies = INFINITE;
}
return millies;
}
Expected<size_t> WaitableGroup::wait_any(std::chrono::milliseconds timeout)
{
DWORD wait_millies = timeout_millies(timeout.count());
const auto WAIT_OBJECT_N = WAIT_OBJECT_0 + m_waitable_handles.size();
const bool WAIT_FOR_ANY = false;
const auto wait_result = WaitForMultipleObjects(static_cast<DWORD>(m_waitable_handles.size()),
m_waitable_handles.data(), WAIT_FOR_ANY, wait_millies);
if (wait_result == WAIT_TIMEOUT) {
return make_unexpected(HAILO_TIMEOUT);
} else if ((wait_result >= WAIT_OBJECT_0) && (wait_result < WAIT_OBJECT_N)) {
// Object is signaled.
// Note! On windows there is no need to call post_wait() because it is done automatically.
return wait_result - WAIT_OBJECT_0;
} else {
LOGGER__ERROR("WaitForMultipleObjects returned {}, last_error={}", wait_result, GetLastError());
return make_unexpected(HAILO_INTERNAL_FAILURE);
}
}
} /* namespace hailort */

View File

@@ -243,4 +243,13 @@ bool Filesystem::does_file_exists(const std::string &path)
return ((GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES) && (GetLastError() == ERROR_FILE_NOT_FOUND));
}
Expected<std::string> Filesystem::get_temp_path()
{
char temp_path[MAX_PATH + 1];
DWORD path_len = GetTempPathA(MAX_PATH + 1, temp_path);
CHECK_AS_EXPECTED(path_len > 0 && path_len <= (MAX_PATH + 1), HAILO_FILE_OPERATION_FAILURE,
"Failed to get temporary directory path");
return std::string(temp_path);
}
} /* namespace hailort */

View File

@@ -32,6 +32,11 @@ uint32_t OsUtils::get_curr_pid()
return static_cast<uint32_t>(GetCurrentProcessId());
}
uint32_t OsUtils::get_curr_tid()
{
return static_cast<uint32_t>(GetCurrentThreadId());
}
bool OsUtils::is_pid_alive(uint32_t pid)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);

View File

@@ -40,11 +40,7 @@ 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(auto module_wrapper_ptr, SocketModuleWrapper::create_shared());
TRY(const auto socket_fd, create_socket_fd(af, type, protocol));
auto obj = Socket(std::move(module_wrapper_ptr), socket_fd);
@@ -76,7 +72,11 @@ Expected<socket_t> Socket::create_socket_fd(int af, int type, int protocol)
hailo_status Socket::abort()
{
return HAILO_NOT_IMPLEMENTED;
int socket_rc = shutdown(m_socket_fd, SD_BOTH);
CHECK((0 == socket_rc) || ((-1 == socket_rc) && (WSAENOTCONN == WSAGetLastError())), HAILO_ETH_FAILURE,
"Failed to shutdown (abort) socket. WSALE={}", WSAGetLastError());
return HAILO_SUCCESS;
}
hailo_status Socket::close_socket_fd()
@@ -84,6 +84,7 @@ hailo_status Socket::close_socket_fd()
if (INVALID_SOCKET != m_socket_fd) {
int socket_rc = closesocket(m_socket_fd);
CHECK(0 == socket_rc, HAILO_ETH_FAILURE, "Failed to close socket. WSALE={}", WSAGetLastError());
m_socket_fd = INVALID_SOCKET;
}
return HAILO_SUCCESS;
@@ -150,26 +151,12 @@ Expected<size_t> Socket::send(const uint8_t *buffer, size_t size, int flags)
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);
CHECK_ARG_NOT_NULL(dst);
TRY(const auto module_wrapper, SocketModuleWrapper::create());
TRY(const auto module_wrapper_ptr, SocketModuleWrapper::create_shared());
const char *inet_result = inet_ntop(af, src, dst, size);
CHECK(nullptr != inet_result, HAILO_ETH_FAILURE, "Failed inet_ntop. WSALE={}", WSAGetLastError());
@@ -184,12 +171,12 @@ hailo_status Socket::pton(int af, const char *src, void *dst)
CHECK_ARG_NOT_NULL(src);
CHECK_ARG_NOT_NULL(dst);
TRY(const auto module_wrapper, SocketModuleWrapper::create());
TRY(const auto module_wrapper_ptr, SocketModuleWrapper::create_shared());
inet_result = inet_pton(af, src, dst);
if (1 != inet_result) {
return HAILO_ETH_FAILURE;
}
CHECK(0 != inet_result, HAILO_ETH_FAILURE,
"Failed to run 'inet_pton'. src is not a valid network address in the specified address family");
CHECK(1 == inet_result, HAILO_ETH_FAILURE, "Failed to run 'inet_pton', WSALE = {}.", WSAGetLastError());
return HAILO_SUCCESS;
}
@@ -255,6 +242,13 @@ hailo_status Socket::allow_reuse_address()
return HAILO_SUCCESS;
}
hailo_status Socket::bind_to_device(const std::string &device_name)
{
(void)device_name;
LOGGER__ERROR("bind_to_device is not implemented for Windows");
return HAILO_NOT_IMPLEMENTED;
}
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

@@ -61,6 +61,7 @@ public:
OsUtils() = delete;
static uint32_t get_curr_pid();
static uint32_t get_curr_tid();
static bool is_pid_alive(uint32_t pid);
static void set_current_thread_name(const std::string &name);
static hailo_status set_current_thread_affinity(uint8_t cpu_index);

View File

@@ -24,7 +24,7 @@ namespace hailort
#define INVALID_SHARED_MEMORY_CHAR '/'
#if defined(_MSC_VER)
#define SHARED_MEMORY_NAME_PREFIX "Global\\"
#define SHARED_MEMORY_NAME_PREFIX "Local\\"
#else
#define SHARED_MEMORY_NAME_PREFIX '/'
#endif

View File

@@ -56,13 +56,14 @@ public:
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 bind_to_device(const std::string &device_name);
hailo_status abort();
hailo_status close_socket_fd();
// TODO: Should these be in udp.cpp?
// TODO: Work with const Buffer& instead of uint8_t*
@@ -72,6 +73,32 @@ public:
sockaddr *src_addr, socklen_t src_addr_size, size_t *bytes_received, bool log_timeouts_in_debug = false);
hailo_status has_data(sockaddr *src_addr, socklen_t src_addr_size, bool log_timeouts_in_debug = false);
hailo_status sendall(const uint8_t *buffer, size_t size, int flags = 0)
{
size_t offset = 0;
while (offset < size) {
TRY(auto bytes_written, send(buffer + offset, size - offset, flags));
if (bytes_written == 0) {
return HAILO_ETH_SEND_FAILURE;
}
offset += bytes_written;
}
return HAILO_SUCCESS;
}
hailo_status recvall(uint8_t* buffer, size_t size, int flags = 0)
{
size_t offset = 0;
while (offset < size) {
TRY(auto bytes_read, recv(buffer + offset, size - offset, flags));
if (bytes_read == 0) {
return HAILO_COMMUNICATION_CLOSED;
}
offset += bytes_read;
}
return HAILO_SUCCESS;
}
private:
class SocketModuleWrapper final {
public:
@@ -83,6 +110,15 @@ private:
return obj;
}
static Expected<std::shared_ptr<SocketModuleWrapper>> create_shared()
{
auto status = HAILO_UNINITIALIZED;
auto ptr = make_shared_nothrow<SocketModuleWrapper>(status);
CHECK_SUCCESS_AS_EXPECTED(status);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
SocketModuleWrapper(hailo_status &status)
{
status = init_module();
@@ -107,7 +143,6 @@ private:
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
std::shared_ptr<SocketModuleWrapper> m_module_wrapper;

View File

@@ -1,39 +0,0 @@
/**
* Copyright (c) 2020-2022 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file string_utils.hpp
* @brief Defines utilities methods for string.
**/
#ifndef _HAILO_STRING_UTILS_HPP_
#define _HAILO_STRING_UTILS_HPP_
#include "hailo/expected.hpp"
#include <string>
#include <algorithm>
namespace hailort
{
class StringUtils {
public:
static Expected<int32_t> to_int32(const std::string &str, int base);
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="");
};
} /* namespace hailort */
#endif /* _HAILO_STRING_UTILS_HPP_ */

View File

@@ -3,11 +3,10 @@
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file string_utils.cpp
* @brief Utilities for string
* @file utils.cpp
* @brief Utilities for libhailort
**/
#include "common/string_utils.hpp"
#include "common/utils.hpp"
#include <sstream>

View File

@@ -16,9 +16,13 @@
#include "hailo/expected.hpp"
#include "hailo/buffer.hpp"
#include "common/file_utils.hpp"
#include "common/logger_macros.hpp"
#include <spdlog/fmt/bundled/core.h>
#define XXH_INLINE_ALL 1
#include "xxhash.h"
#include <assert.h>
#include <map>
#include <set>
@@ -39,6 +43,7 @@ namespace hailort
static const uint32_t POLYNOMIAL = 0xEDB88320;
static const size_t MB = 1024 * 1024;
static const size_t XXH3_CHUNK_SIZE = 1024 * 1024 / 4; // We got best performance with this chunk_size for xxh3 algorithm
template <typename T>
static inline bool contains(const std::vector<T> &container, const T &value)
@@ -70,6 +75,24 @@ static inline bool contains(const std::unordered_set<T> &container, T value)
return (container.find(value) != container.end());
}
template <typename T, typename Q>
static inline std::set<Q> get_key_set(const std::map<Q, T> &map)
{
std::set<Q> keys;
std::transform(map.begin(), map.end(), std::inserter(keys, keys.end()),
[](const auto &pair) { return pair.first; });
return keys;
}
template <typename T, typename Q>
static inline std::unordered_set<Q> get_key_set(const std::unordered_map<Q, T> &map)
{
std::unordered_set<Q> keys;
std::transform(map.begin(), map.end(), std::inserter(keys, keys.end()),
[](const auto &pair) { return pair.first; });
return keys;
}
// From https://stackoverflow.com/questions/57092289/do-stdmake-shared-and-stdmake-unique-have-a-nothrow-version
template <class T, class... Args>
static inline std::unique_ptr<T> make_unique_nothrow(Args&&... args)
@@ -396,8 +419,10 @@ public:
generate_table();
}
uint32_t calculate(std::ifstream &s, size_t buffer_size) const {
auto beg_pos = s.tellg(); // Saves current position
Expected<uint32_t> calculate(std::shared_ptr<std::ifstream> stream, size_t buffer_size) const
{
TRY(auto stream_guard, StreamPositionGuard::create(stream));
uint32_t crc = 0xFFFFFFFF;
std::vector<char> buffer(MB);
@@ -405,16 +430,15 @@ public:
while (total_bytes_read < buffer_size) {
size_t bytes_to_read = std::min(buffer_size - total_bytes_read, MB);
s.read(buffer.data(), bytes_to_read);
stream->read(buffer.data(), bytes_to_read);
size_t bytes_read = s.gcount();
size_t bytes_read = stream->gcount();
total_bytes_read += bytes_read;
for (size_t i = 0; i < bytes_read; ++i) {
crc = (crc >> 8) ^ table[(crc ^ static_cast<uint8_t>(buffer[i])) & 0xFF];
}
}
s.seekg(beg_pos, std::ios::beg); // Return to the original position
return crc ^ 0xFFFFFFFF;
}
@@ -435,10 +459,10 @@ public:
return crcCalculator.calculate(buffer);
}
static Expected<uint32_t> calc_crc_on_stream(std::ifstream &s, size_t size)
static Expected<uint32_t> calc_crc_on_stream(std::shared_ptr<std::ifstream> stream, size_t size)
{
CRC32 crcCalculator;
return crcCalculator.calculate(s, size);
return crcCalculator.calculate(stream, size);
}
private:
@@ -455,6 +479,65 @@ private:
}
};
class Xxhash final
{
public:
Xxhash() = delete;
static Expected<uint64_t> calc_xxh3_on_buffer(const MemoryView &buffer)
{
return XXH3_64bits(buffer.data(), buffer.size());
}
static Expected<uint64_t> calc_xxh3_on_stream(std::shared_ptr<std::ifstream> stream, size_t size)
{
TRY(auto stream_guard, StreamPositionGuard::create(stream));
// TODO: HRT-15783 - Try improve performance with multiple buffers and threads
auto state = std::unique_ptr<XXH3_state_t, decltype(&XXH3_freeState)>(
XXH3_createState(),
&XXH3_freeState
);
// XXH3_64bits_reset resets a state to begin a new hash, must be called before XXH3_64bits_update
CHECK_AS_EXPECTED(XXH3_64bits_reset(state.get()) != XXH_ERROR, HAILO_INTERNAL_FAILURE, "Failed to reset XXH3 state");
char buffer[XXH3_CHUNK_SIZE];
size_t total_bytes_read = 0;
while (total_bytes_read < size) {
size_t bytes_to_read = std::min(size - total_bytes_read, XXH3_CHUNK_SIZE);
stream->read(buffer, bytes_to_read);
CHECK_AS_EXPECTED(stream->good(), HAILO_FILE_OPERATION_FAILURE, "ifstream::read() failed");
size_t bytes_read = stream->gcount();
auto res = XXH3_64bits_update(state.get(), buffer, bytes_read);
CHECK_AS_EXPECTED(res != XXH_ERROR, HAILO_INTERNAL_FAILURE, "Failed to update XXH3 state");
total_bytes_read += bytes_read;
}
return XXH3_64bits_digest(state.get());
}
};
class StringUtils final
{
public:
StringUtils() = delete;
static Expected<int32_t> to_int32(const std::string &str, int base);
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="");
};
class BufferUtils final
{
public:
@@ -483,6 +566,16 @@ public:
print_range(range_start, buffer.size(), current_value, os);
}
static void format_buffer(const Buffer &buffer, std::ostream& os)
{
format_buffer(buffer.data(), buffer.size(), os);
}
static void format_buffer(const MemoryView &mem_view, std::ostream& os)
{
format_buffer(mem_view.data(), mem_view.size(), os);
}
private:
static void print_range(size_t range_start, size_t range_end_exclusive, uint8_t value, std::ostream& os)
{
@@ -490,6 +583,22 @@ private:
range_start, range_end_exclusive - 1, static_cast<int>(value), range_end_exclusive - range_start);
os << message << std::endl;
}
static void format_buffer(const uint8_t *buffer, size_t size, std::ostream& os)
{
assert(nullptr != buffer);
os << "[addr = " << static_cast<const void *>(buffer) << ", size = " << size << "]" << std::endl;
static const bool UPPERCASE = true;
static const size_t BYTES_PER_LINE = 32;
static const char *BYTE_DELIM = " ";
for (size_t offset = 0; offset < size; offset += BYTES_PER_LINE) {
const size_t line_size = std::min(BYTES_PER_LINE, size - offset);
os << fmt::format("0x{:08X}", offset) << BYTE_DELIM; // 32 bit offset into a buffer should be enough
os << StringUtils::to_hex_string(buffer + offset, line_size, UPPERCASE, BYTE_DELIM) << std::endl;
}
}
};
} /* namespace hailort */

View File

@@ -7,7 +7,7 @@
#define _HAILO_IOCTL_COMMON_H_
#define HAILO_DRV_VER_MAJOR 4
#define HAILO_DRV_VER_MINOR 19
#define HAILO_DRV_VER_MINOR 20
#define HAILO_DRV_VER_REVISION 0
#define _STRINGIFY_EXPANDED( x ) #x
@@ -22,6 +22,7 @@
#define MAX_VDMA_ENGINES (3)
#define SIZE_OF_VDMA_DESCRIPTOR (16)
#define VDMA_DEST_CHANNELS_START (16)
#define MAX_SG_DESCS_COUNT (64 * 1024u)
#define HAILO_VDMA_MAX_ONGOING_TRANSFERS (128)
#define HAILO_VDMA_MAX_ONGOING_TRANSFERS_MASK (HAILO_VDMA_MAX_ONGOING_TRANSFERS - 1)
@@ -38,6 +39,10 @@
#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)
// HRT-15790 TODO: separate nnc interrupts and soc interrupts
#define FW_ACCESS_SOFT_RESET_SHIFT (3)
#define FW_ACCESS_SOFT_RESET_MASK (1 << FW_ACCESS_SOFT_RESET_SHIFT)
#define FW_ACCESS_SOC_CONTROL_SHIFT (3)
#define FW_ACCESS_SOC_CONTROL_MASK (1 << FW_ACCESS_SOC_CONTROL_SHIFT)
@@ -184,7 +189,6 @@ enum hailo_dma_data_direction {
};
// Enum that states what type of buffer we are working with in the driver
// TODO: HRT-13580 - Add specific type for user allocated and for driver allocated
enum hailo_dma_buffer_type {
HAILO_DMA_USER_PTR_BUFFER = 0,
HAILO_DMA_DMABUF_BUFFER = 1,
@@ -399,7 +403,7 @@ struct hailo_d2h_notification {
enum hailo_board_type {
HAILO_BOARD_TYPE_HAILO8 = 0,
HAILO_BOARD_TYPE_HAILO15,
HAILO_BOARD_TYPE_PLUTO,
HAILO_BOARD_TYPE_HAILO15L,
HAILO_BOARD_TYPE_HAILO10H,
HAILO_BOARD_TYPE_HAILO10H_LEGACY,
HAILO_BOARD_TYPE_COUNT,

View File

@@ -1,8 +1,5 @@
cmake_minimum_required(VERSION 3.5.0)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/spdlog.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/readerwriterqueue.cmake)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
@@ -11,7 +8,6 @@ set(HAILORT_SERVER_SOURCES
${HRPC_CPP_SOURCES}
${HRPC_PROTOCOL_CPP_SOURCES}
${HAILORT_SERVICE_DIR}/cng_buffer_pool.cpp
${HAILO_FULL_OS_DIR}/event.cpp # TODO HRT-10681: move to common
${DRIVER_OS_DIR}/driver_os_specific.cpp
${HAILORT_SRC_DIR}/vdma/pcie_session.cpp
${HAILORT_SRC_DIR}/vdma/memory/descriptor_list.cpp
@@ -23,8 +19,6 @@ set(HAILORT_SERVER_SOURCES
${HAILORT_SRC_DIR}/vdma/channel/boundary_channel.cpp
${HAILORT_SRC_DIR}/vdma/channel/channels_group.cpp
${HAILORT_SRC_DIR}/vdma/channel/transfer_common.cpp
${HAILORT_COMMON_CPP_SOURCES}
)
add_executable(hailort_server ${HAILORT_SERVER_SOURCES})
@@ -40,12 +34,5 @@ target_link_libraries(hailort_server PRIVATE
libhailort
Threads::Threads
rpc_proto
spdlog::spdlog
readerwriterqueue
hailort_common
)
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

@@ -8,12 +8,15 @@
**/
#include "hailort_server.hpp"
#include "hailo/hailort.h"
#include "hrpc/server.hpp"
#include "hailo/vdevice.hpp"
#include "hailo/infer_model.hpp"
#include "hrpc_protocol/serializer.hpp"
#include "net_flow/ops/nms_post_process.hpp"
#include "hailort_service/service_resource_manager.hpp"
#include "common/thread_safe_queue.hpp"
#include "hrpc/connection_context.hpp"
#include "vdma/pcie_session.hpp"
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>
@@ -67,7 +70,9 @@ using namespace hailort;
#else
#define LOGGER_PATTERN ("[%Y-%m-%d %X.%e] [%P] [%t] [%n] [%^%l%$] [%s:%#] [%!] %v")
#endif
#define BUFFER_POOL_SIZE (10) // TODO: this may hurt performance, should be configurable
// TODO: Benchmark this factor (HRT-15727)
#define ASYNC_QUEUE_SIZE_FACTOR (2) // double buffer
struct InferModelInfo
{
@@ -85,7 +90,7 @@ void init_logger(const std::string &name)
spdlog::set_default_logger(make_shared_nothrow<spdlog::logger>(name, console_sink));
}
void hrpc::HailoRTServer::cleanup_infer_model_hef_buffers(const std::vector<uint32_t> &infer_model_handles)
void HailoRTServer::cleanup_infer_model_hef_buffers(const std::vector<uint32_t> &infer_model_handles)
{
for (const auto &infer_model_handle : infer_model_handles) {
auto hef_buffers_iter = m_hef_buffers_per_infer_model.find(infer_model_handle);
@@ -95,17 +100,15 @@ void hrpc::HailoRTServer::cleanup_infer_model_hef_buffers(const std::vector<uint
}
}
void hrpc::HailoRTServer::cleanup_cim_buffer_pools(const std::vector<uint32_t> &cim_handles)
void HailoRTServer::cleanup_cim_buffer_pools(const std::vector<uint32_t> &cim_handles)
{
std::lock_guard<std::mutex> lock(m_buffer_pool_mutex);
for (const auto &cim_handle : cim_handles) {
auto buffer_pool_iter = m_buffer_pool_per_cim.find(cim_handle);
if (m_buffer_pool_per_cim.end() != buffer_pool_iter) {
m_buffer_pool_per_cim.erase(cim_handle);
}
}
}
hailo_status hrpc::HailoRTServer::cleanup_client_resources(RpcConnection client_connection)
hailo_status HailoRTServer::cleanup_client_resources(RpcConnection client_connection)
{
std::set<uint32_t> pids = {SINGLE_CLIENT_PID};
auto cim_handles = ServiceResourceManager<ConfiguredInferModel>::get_instance().resources_handles_by_pids(pids);
@@ -123,32 +126,104 @@ hailo_status hrpc::HailoRTServer::cleanup_client_resources(RpcConnection client_
return HAILO_SUCCESS;
}
Expected<std::unique_ptr<hrpc::HailoRTServer>> hrpc::HailoRTServer::create_unique()
Expected<std::unique_ptr<HailoRTServer>> HailoRTServer::create_unique()
{
TRY(auto connection_context, ConnectionContext::create_server_shared());
auto res = make_unique_nothrow<HailoRTServer>(connection_context);
TRY(auto callbacks_queue_shutdown_event, Event::create_shared(Event::State::not_signalled));
auto callbacks_done_queue = SpscQueue<FinishedInferRequest>::create_shared(PcieSession::MAX_ONGOING_TRANSFERS, callbacks_queue_shutdown_event);
CHECK_NOT_NULL_AS_EXPECTED(callbacks_done_queue, HAILO_OUT_OF_HOST_MEMORY);
auto res = make_unique_nothrow<HailoRTServer>(connection_context, callbacks_done_queue, callbacks_queue_shutdown_event);
CHECK_NOT_NULL(res, HAILO_OUT_OF_HOST_MEMORY);
return res;
}
HailoRTServer::HailoRTServer(std::shared_ptr<ConnectionContext> connection_context,
std::shared_ptr<SpscQueue<FinishedInferRequest>> callbacks_done_queue,
EventPtr callbacks_queue_shutdown_event) : Server(connection_context), m_callbacks_done_queue(callbacks_done_queue),
m_callbacks_queue_shutdown_event(callbacks_queue_shutdown_event)
{
m_callbacks_thread = std::thread([this] {
auto status = callbacks_thread_loop();
if (HAILO_SUCCESS != status) {
LOGGER__CRITICAL("Callback thread has failed with status {}. Server should restart!", status);
}
});
}
hailo_status HailoRTServer::callbacks_thread_loop()
{
while (true) {
auto request = m_callbacks_done_queue->dequeue(std::chrono::milliseconds(HAILO_INFINITE));
if (HAILO_SHUTDOWN_EVENT_SIGNALED == request.status()) {
break;
}
CHECK_EXPECTED_AS_STATUS(request);
auto status = trigger_callback(request->callback_id, request->completion_info.status, request->configured_infer_model_handle,
request->connection, [this, &request] (RpcConnection connection) -> hailo_status {
if (HAILO_SUCCESS == request->completion_info.status) {
for (auto output : request->outputs) {
auto status = connection.wait_for_write_buffer_async_ready(output->size(), SERVER_TIMEOUT);
CHECK_SUCCESS(status);
status = connection.write_buffer_async(MemoryView(*output), [output] (hailo_status status) {
(void)output; // capturing output so it won't be freed before the callback is called
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to write buffer, status = {}", status);
}
});
CHECK_SUCCESS(status);
}
std::lock_guard<std::mutex> lock(m_buffer_pool_mutex);
for (uint32_t i = 0; i < request->outputs.size(); i++) {
if (m_buffer_pool_per_cim.contains(request->configured_infer_model_handle)) {
auto status = m_buffer_pool_per_cim.at(request->configured_infer_model_handle)->return_to_pool(request->outputs_names[i], request->outputs[i]);
CHECK_SUCCESS(status);
}
}
}
return HAILO_SUCCESS;
});
// HAILO_COMMUNICATION_CLOSED means the client disconnected. Server doesn't need to restart in this case.
if (status != HAILO_COMMUNICATION_CLOSED) {
CHECK_SUCCESS(status);
}
}
return HAILO_SUCCESS;
}
HailoRTServer::~HailoRTServer()
{
auto status = m_callbacks_queue_shutdown_event->signal();
if (HAILO_SUCCESS != status) {
LOGGER__CRITICAL("Failed to signal shutdown event, status = {}", status);
}
if (m_callbacks_thread.joinable()) {
m_callbacks_thread.join();
}
}
int main()
{
init_logger("HailoRT-Server");
TRY(auto server, hrpc::HailoRTServer::create_unique());
hrpc::Dispatcher dispatcher;
TRY(auto server, HailoRTServer::create_unique());
Dispatcher dispatcher;
// TODO: add a server implementation class, with resources heiracrhy and more
auto &infer_model_to_info_id = server->get_infer_model_to_info_id();
auto &buffer_pool_per_cim = server->get_buffer_pool_per_cim();
auto &infer_model_to_info_id = server->infer_model_to_info_id();
auto &buffer_pool_per_cim = server->buffer_pool_per_cim();
// Because the infer model is created with a hef buffer, we need to keep the buffer until the configure stage.
// Here I keep it until the infer model is destroyed
auto &hef_buffers = server->get_hef_buffers();
auto &hef_buffers = server->hef_buffers();
dispatcher.register_action(HailoRpcActionID::VDEVICE__CREATE,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
TRY_AS_HRPC_STATUS(auto vdevice_params, CreateVDeviceSerializer::deserialize_request(request), CreateVDeviceSerializer);
TRY_AS_HRPC_STATUS(auto vdevice, VDevice::create(vdevice_params), CreateVDeviceSerializer);
TRY_AS_HRPC_STATUS(auto vdevice, VDevice::create(vdevice_params.get()), CreateVDeviceSerializer);
auto &manager = ServiceResourceManager<VDevice>::get_instance();
auto id = manager.register_resource(SINGLE_CLIENT_PID, std::move(vdevice));
@@ -156,7 +231,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::VDEVICE__DESTROY,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &manager = ServiceResourceManager<VDevice>::get_instance();
TRY_AS_HRPC_STATUS(auto vdevice_handle, DestroyVDeviceSerializer::deserialize_request(request), DestroyVDeviceSerializer);
(void)manager.release_resource(vdevice_handle, SINGLE_CLIENT_PID);
@@ -164,14 +239,15 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::VDEVICE__CREATE_INFER_MODEL,
[&hef_buffers] (const MemoryView &request, hrpc::ServerContextPtr server_context) -> Expected<Buffer> {
[&hef_buffers] (const MemoryView &request, ServerContextPtr server_context) -> Expected<Buffer> {
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);
TRY_AS_HRPC_STATUS(auto hef_buffer, Buffer::create(static_cast<size_t>(hef_size), BufferStorageParams::create_dma()),
CreateInferModelSerializer);
auto status = server_context->connection().read_buffer(MemoryView(hef_buffer));
CHECK_SUCCESS_AS_HRPC_STATUS(status, CreateInferModelSerializer);
@@ -191,7 +267,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::INFER_MODEL__DESTROY,
[&hef_buffers] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[&hef_buffers] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &manager = ServiceResourceManager<InferModel>::get_instance();
TRY_AS_HRPC_STATUS(auto infer_model_handle, DestroyInferModelSerializer::deserialize_request(request), DestroyInferModelSerializer);
hef_buffers.erase(infer_model_handle);
@@ -201,7 +277,7 @@ int main()
});
dispatcher.register_action(HailoRpcActionID::INFER_MODEL__CREATE_CONFIGURED_INFER_MODEL,
[&buffer_pool_per_cim, &infer_model_to_info_id]
(const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
(const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &infer_model_manager = ServiceResourceManager<InferModel>::get_instance();
TRY_AS_HRPC_STATUS(auto request_params, CreateConfiguredInferModelSerializer::deserialize_request(request), CreateConfiguredInferModelSerializer);
@@ -225,6 +301,9 @@ int main()
if (static_cast<uint32_t>(INVALID_NMS_CONFIG) != input_stream_format.second.nms_max_proposals_per_class) {
input.set_nms_max_proposals_per_class(input_stream_format.second.nms_max_proposals_per_class);
}
if (static_cast<uint32_t>(INVALID_NMS_CONFIG) != input_stream_format.second.nms_max_proposals_total) {
input.set_nms_max_proposals_total(input_stream_format.second.nms_max_proposals_total);
}
if (static_cast<uint32_t>(INVALID_NMS_CONFIG) != input_stream_format.second.nms_max_accumulated_mask_size) {
input.set_nms_max_accumulated_mask_size(input_stream_format.second.nms_max_accumulated_mask_size);
}
@@ -243,6 +322,9 @@ int main()
if (static_cast<uint32_t>(INVALID_NMS_CONFIG) != output_stream_format.second.nms_max_proposals_per_class) {
output.set_nms_max_proposals_per_class(output_stream_format.second.nms_max_proposals_per_class);
}
if (static_cast<uint32_t>(INVALID_NMS_CONFIG) != output_stream_format.second.nms_max_proposals_total) {
output.set_nms_max_proposals_total(output_stream_format.second.nms_max_proposals_total);
}
if (static_cast<uint32_t>(INVALID_NMS_CONFIG) != output_stream_format.second.nms_max_accumulated_mask_size) {
output.set_nms_max_accumulated_mask_size(output_stream_format.second.nms_max_accumulated_mask_size);
}
@@ -295,12 +377,12 @@ int main()
for (const auto &input_name : infer_model_info->inputs_names) {
auto status = buffer_pool_ptr->allocate_pool(input_name, HAILO_DMA_BUFFER_DIRECTION_D2H,
infer_model_info->input_streams_sizes[input_name], BUFFER_POOL_SIZE);
infer_model_info->input_streams_sizes[input_name], async_queue_size * ASYNC_QUEUE_SIZE_FACTOR);
CHECK_SUCCESS_AS_HRPC_STATUS(status, CreateConfiguredInferModelSerializer);
}
for (const auto &output_name : infer_model_info->outputs_names) {
auto status = buffer_pool_ptr->allocate_pool(output_name, HAILO_DMA_BUFFER_DIRECTION_H2D,
infer_model_info->output_streams_sizes[output_name], BUFFER_POOL_SIZE);
infer_model_info->output_streams_sizes[output_name], async_queue_size * ASYNC_QUEUE_SIZE_FACTOR);
CHECK_SUCCESS_AS_HRPC_STATUS(status, CreateConfiguredInferModelSerializer);
}
buffer_pool_per_cim.emplace(cim_id, buffer_pool_ptr);
@@ -312,7 +394,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__DESTROY,
[&buffer_pool_per_cim] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[&server] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
TRY_AS_HRPC_STATUS(auto configured_infer_model_handle, DestroyConfiguredInferModelSerializer::deserialize_request(request), DestroyInferModelSerializer);
@@ -321,13 +403,13 @@ int main()
return HAILO_SUCCESS;
};
manager.execute<hailo_status>(configured_infer_model_handle, shutdown_lambda);
buffer_pool_per_cim.erase(configured_infer_model_handle);
server->cleanup_cim_buffer_pools({ configured_infer_model_handle });
(void)manager.release_resource(configured_infer_model_handle, SINGLE_CLIENT_PID);
TRY_AS_HRPC_STATUS(auto reply, DestroyConfiguredInferModelSerializer::serialize_reply(HAILO_SUCCESS), DestroyInferModelSerializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__SET_SCHEDULER_TIMEOUT,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
TRY_AS_HRPC_STATUS(auto tuple, SetSchedulerTimeoutSerializer::deserialize_request(request), SetSchedulerTimeoutSerializer);
const auto &configured_infer_model_handle = std::get<0>(tuple);
@@ -341,7 +423,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__SET_SCHEDULER_THRESHOLD,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
TRY_AS_HRPC_STATUS(auto tuple, SetSchedulerThresholdSerializer::deserialize_request(request), SetSchedulerThresholdSerializer);
const auto &configured_infer_model_handle = std::get<0>(tuple);
@@ -355,7 +437,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__SET_SCHEDULER_PRIORITY,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
TRY_AS_HRPC_STATUS(auto tuple, SetSchedulerPrioritySerializer::deserialize_request(request), SetSchedulerPrioritySerializer);
const auto &configured_infer_model_handle = std::get<0>(tuple);
@@ -369,7 +451,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__GET_HW_LATENCY_MEASUREMENT,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
auto configured_infer_model_handle = GetHwLatencyMeasurementSerializer::deserialize_request(request);
@@ -391,7 +473,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__ACTIVATE,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
auto configured_infer_model_handle = ActivateSerializer::deserialize_request(request);
@@ -407,7 +489,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__DEACTIVATE,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
auto configured_infer_model_handle = DeactivateSerializer::deserialize_request(request);
@@ -423,7 +505,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__SHUTDOWN,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
auto configured_infer_model_handle = ShutdownSerializer::deserialize_request(request);
@@ -439,8 +521,8 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::CONFIGURED_INFER_MODEL__RUN_ASYNC,
[&infer_model_to_info_id, &buffer_pool_per_cim]
(const MemoryView &request, hrpc::ServerContextPtr server_context) -> Expected<Buffer> {
[&infer_model_to_info_id, &buffer_pool_per_cim, callbacks_done_queue = server->callbacks_done_queue()]
(const MemoryView &request, ServerContextPtr server_context) -> Expected<Buffer> {
auto &cim_manager = ServiceResourceManager<ConfiguredInferModel>::get_instance();
auto bindings_lambda = [] (std::shared_ptr<ConfiguredInferModel> configured_infer_model) {
return configured_infer_model->create_bindings();
@@ -468,7 +550,7 @@ int main()
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),
TRY_AS_HRPC_STATUS(auto buffer_ptr, buffer_pool_per_cim.at(configured_infer_model_handle)->acquire_buffer(input_name),
RunAsyncSerializer);
uint32_t read_size = 0;
@@ -491,7 +573,7 @@ int main()
std::vector<BufferPtr> outputs; // TODO: add infer vector pool
outputs.reserve(infer_model_info->outputs_names.size());
for (const auto &output_name : infer_model_info->outputs_names) {
TRY_AS_HRPC_STATUS(auto buffer_ptr, buffer_pool_per_cim[configured_infer_model_handle]->acquire_buffer(output_name),
TRY_AS_HRPC_STATUS(auto buffer_ptr, buffer_pool_per_cim.at(configured_infer_model_handle)->acquire_buffer(output_name),
RunAsyncSerializer);
auto output = bindings->output(output_name);
@@ -505,41 +587,29 @@ int main()
auto infer_lambda =
[bindings = bindings.release(), callback_id, server_context, inputs, outputs, &buffer_pool_per_cim, configured_infer_model_handle,
infer_model_info]
infer_model_info, callbacks_done_queue]
(std::shared_ptr<ConfiguredInferModel> configured_infer_model) {
return configured_infer_model->run_async(bindings,
[callback_id, server_context, inputs, outputs, &buffer_pool_per_cim, configured_infer_model_handle, infer_model_info]
[callback_id, server_context, inputs, outputs, &buffer_pool_per_cim, configured_infer_model_handle, infer_model_info,
callbacks_done_queue]
(const AsyncInferCompletionInfo &completion_info) {
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 = buffer_pool_per_cim.at(configured_infer_model_handle)->return_to_pool(infer_model_info->inputs_names[i], inputs[i]);
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to return buffer to pool, status = {}", status);
}
}
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));
CHECK_SUCCESS(status);
}
}
return HAILO_SUCCESS;
});
// HAILO_COMMUNICATION_CLOSED means the client disconnected. Server doesn't need to restart in this case.
if ((status != HAILO_SUCCESS) && (status != HAILO_COMMUNICATION_CLOSED)) {
LOGGER__CRITICAL("Error {} returned from connection.write(). Server Should restart!", status);
}
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) {
LOGGER__CRITICAL("return_to_pool failed for output {}, status = {}. Server should restart!", infer_model_info->outputs_names[i], status);
return;
}
FinishedInferRequest request;
request.connection = server_context->connection();
request.completion_info = completion_info;
request.callback_id = callback_id;
request.configured_infer_model_handle = configured_infer_model_handle;
request.outputs = std::move(outputs);
request.outputs_names = infer_model_info->outputs_names;
auto status = callbacks_done_queue->enqueue(std::move(request));
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to enqueue to infer requests queue, status = {}", status);
}
});
};
@@ -552,7 +622,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__CREATE,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
auto status = CreateDeviceSerializer::deserialize_request(request);
CHECK_SUCCESS_AS_HRPC_STATUS(status, CreateDeviceSerializer);
@@ -564,7 +634,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__DESTROY,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, 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);
@@ -572,7 +642,7 @@ int main()
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__IDENTIFY,
[] (const MemoryView &request, hrpc::ServerContextPtr /*server_context*/) -> Expected<Buffer> {
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
TRY_AS_HRPC_STATUS(auto device_handle, IdentifyDeviceSerializer::deserialize_request(request), IdentifyDeviceSerializer);
auto &manager = ServiceResourceManager<Device>::get_instance();
@@ -585,16 +655,145 @@ int main()
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);
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
using Serializer = ExtendedDeviceInfoSerializer;
using ActionReturnType = hailo_extended_device_information_t;
TRY_AS_HRPC_STATUS(auto device_handle, Serializer::deserialize_request(request), Serializer);
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);
manager.execute<Expected<ActionReturnType>>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS, extended_info), Serializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__GET_CHIP_TEMPERATURE,
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
using Serializer = GetChipTemperatureSerializer;
using ActionReturnType = hailo_chip_temperature_info_t;
TRY_AS_HRPC_STATUS(auto device_handle, Serializer::deserialize_request(request), Serializer);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [] (std::shared_ptr<Device> device) {
return device->get_chip_temperature();
};
TRY_AS_HRPC_STATUS(auto info, manager.execute<Expected<ActionReturnType>>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS, info), Serializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__POWER_MEASUREMENT,
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
using Serializer = PowerMeasurementSerializer;
using ActionReturnType = float32_t;
TRY_AS_HRPC_STATUS(auto tuple, Serializer::deserialize_request(request), Serializer);
auto device_handle = std::get<0>(tuple);
auto dvm = std::get<1>(tuple);
auto power_measurement_type = std::get<2>(tuple);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [dvm, power_measurement_type] (std::shared_ptr<Device> device) {
return device->power_measurement(
static_cast<hailo_dvm_options_t>(dvm),
static_cast<hailo_power_measurement_types_t>(power_measurement_type));
};
TRY_AS_HRPC_STATUS(auto info, manager.execute<Expected<ActionReturnType>>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS, info), Serializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__SET_POWER_MEASUREMENT,
[] (const MemoryView &request, ServerContextPtr /*server_context*/) -> Expected<Buffer> {
using Serializer = SetPowerMeasurementSerializer;
using ActionReturnType = hailo_status;
TRY_AS_HRPC_STATUS(auto tuple, Serializer::deserialize_request(request), Serializer);
auto device_handle = std::get<0>(tuple);
auto dvm = std::get<1>(tuple);
auto power_measurement_type = std::get<2>(tuple);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [dvm, power_measurement_type] (std::shared_ptr<Device> device) {
constexpr hailo_measurement_buffer_index_t not_used_buffer_index = HAILO_MEASUREMENT_BUFFER_INDEX_MAX_ENUM;
return device->set_power_measurement(
not_used_buffer_index, /* Relevant only for H8. Not used in H10 */
static_cast<hailo_dvm_options_t>(dvm),
static_cast<hailo_power_measurement_types_t>(power_measurement_type));
};
CHECK_SUCCESS_AS_HRPC_STATUS(manager.execute<ActionReturnType>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS), Serializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__START_POWER_MEASUREMENT,
[] (const MemoryView &request, ServerContextPtr) -> Expected<Buffer> {
using Serializer = SetPowerMeasurementSerializer;
using ActionReturnType = hailo_status;
TRY_AS_HRPC_STATUS(auto tuple, Serializer::deserialize_request(request), Serializer);
auto device_handle = std::get<0>(tuple);
auto averaging_factor = std::get<1>(tuple);
auto sampling_period = std::get<2>(tuple);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [sampling_period, averaging_factor] (std::shared_ptr<Device> device) {
return device->start_power_measurement(
static_cast<hailo_averaging_factor_t>(averaging_factor),
static_cast<hailo_sampling_period_t>(sampling_period));
};
CHECK_SUCCESS_AS_HRPC_STATUS(manager.execute<ActionReturnType>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS), Serializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__GET_POWER_MEASUREMENT,
[] (const MemoryView &request, ServerContextPtr) -> Expected<Buffer> {
using Serializer = GetPowerMeasurementSerializer;
using ActionReturnType = hailo_power_measurement_data_t;
TRY_AS_HRPC_STATUS(auto tuple, Serializer::deserialize_request(request), Serializer);
auto device_handle = std::get<0>(tuple);
auto should_clear = std::get<1>(tuple);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [should_clear] (std::shared_ptr<Device> device) {
constexpr hailo_measurement_buffer_index_t unused_buffer_index = HAILO_MEASUREMENT_BUFFER_INDEX_MAX_ENUM;
return device->get_power_measurement(unused_buffer_index, should_clear);
};
TRY_AS_HRPC_STATUS(auto info, manager.execute<Expected<ActionReturnType>>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS, info), Serializer);
return reply;
});
dispatcher.register_action(HailoRpcActionID::DEVICE__STOP_POWER_MEASUREMENT,
[] (const MemoryView &request, ServerContextPtr) -> Expected<Buffer> {
using Serializer = StopPowerMeasurementSerializer;
using ActionReturnType = hailo_status;
TRY_AS_HRPC_STATUS(auto device_handle, Serializer::deserialize_request(request), Serializer);
auto &manager = ServiceResourceManager<Device>::get_instance();
auto device_lambda = [] (std::shared_ptr<Device> device) {
return device->stop_power_measurement();
};
CHECK_SUCCESS_AS_HRPC_STATUS(manager.execute<ActionReturnType>(device_handle, device_lambda), Serializer);
TRY_AS_HRPC_STATUS(auto reply, Serializer::serialize_reply(HAILO_SUCCESS), Serializer);
return reply;
});

View File

@@ -12,33 +12,57 @@
#include "hrpc/server.hpp"
#include "hailort_service/cng_buffer_pool.hpp"
#include "hailo/infer_model.hpp"
#include "utils/thread_safe_map.hpp"
namespace hrpc
namespace hailort
{
using infer_model_handle_t = uint32_t;
struct FinishedInferRequest
{
public:
FinishedInferRequest() : completion_info(HAILO_UNINITIALIZED) {}
RpcConnection connection;
hailort::AsyncInferCompletionInfo completion_info;
uint32_t callback_id;
uint32_t configured_infer_model_handle;
std::vector<BufferPtr> outputs;
std::vector<std::string> outputs_names;
};
class Server;
class HailoRTServer : public Server {
public:
static Expected<std::unique_ptr<HailoRTServer>> create_unique();
explicit HailoRTServer(std::shared_ptr<ConnectionContext> connection_context) : Server(connection_context) {};
explicit HailoRTServer(std::shared_ptr<ConnectionContext> connection_context,
std::shared_ptr<SpscQueue<FinishedInferRequest>> callbacks_done_queue,
EventPtr callbacks_queue_shutdown_event);
virtual ~HailoRTServer();
std::unordered_map<uint32_t, uint32_t> &get_infer_model_to_info_id() { return m_infer_model_to_info_id; };
std::unordered_map<uint32_t, std::shared_ptr<ServiceNetworkGroupBufferPool>> &get_buffer_pool_per_cim() { return m_buffer_pool_per_cim; };
std::unordered_map<infer_model_handle_t, Buffer> &get_hef_buffers() { return m_hef_buffers_per_infer_model; };
std::unordered_map<uint32_t, uint32_t> &infer_model_to_info_id() { return m_infer_model_to_info_id; };
ThreadSafeMap<uint32_t, std::shared_ptr<ServiceNetworkGroupBufferPool>> &buffer_pool_per_cim() { return m_buffer_pool_per_cim; };
std::unordered_map<infer_model_handle_t, Buffer> &hef_buffers() { return m_hef_buffers_per_infer_model; };
std::shared_ptr<SpscQueue<FinishedInferRequest>> &callbacks_done_queue() { return m_callbacks_done_queue; };
void cleanup_cim_buffer_pools(const std::vector<uint32_t> &cim_handles);
private:
virtual hailo_status cleanup_client_resources(RpcConnection client_connection) override;
void cleanup_infer_model_hef_buffers(const std::vector<uint32_t> &infer_model_handles);
hailo_status callbacks_thread_loop();
std::unordered_map<uint32_t, uint32_t> m_infer_model_to_info_id;
std::unordered_map<uint32_t, std::shared_ptr<ServiceNetworkGroupBufferPool>> m_buffer_pool_per_cim;
ThreadSafeMap<uint32_t, std::shared_ptr<ServiceNetworkGroupBufferPool>> m_buffer_pool_per_cim;
std::mutex m_buffer_pool_mutex;
std::unordered_map<infer_model_handle_t, Buffer> m_hef_buffers_per_infer_model;
virtual hailo_status cleanup_client_resources(RpcConnection client_connection) override;
void cleanup_cim_buffer_pools(const std::vector<uint32_t> &cim_handles);
void cleanup_infer_model_hef_buffers(const std::vector<uint32_t> &infer_model_handles);
std::shared_ptr<SpscQueue<FinishedInferRequest>> m_callbacks_done_queue;
EventPtr m_callbacks_queue_shutdown_event;
std::thread m_callbacks_thread;
};
} // namespace hrpc
} // namespace hailort
#endif // HAILORT_SERVER_HPP_

View File

@@ -1,39 +0,0 @@
#! /bin/bash
### BEGIN INIT INFO
# Provides: hailort_server
# Required-Start: $local_fs $network
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: hailort_server service
# Description: Run hailort_server daemon
### END INIT INFO
# TODO: Remove this file once the hailort_server will use systemd
# Carry out specific functions when asked to by the system
case "$1" in
start)
echo "Starting hailort_server"
bash -c "cd /usr/bin && hailort_server &"
;;
stop)
echo "Stopping hailort_server..."
bash -c "killall hailort_server"
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: /etc/init.d/hailort_server {start|stop|restart}"
exit 1
;;
esac
exit 0

View File

@@ -1,7 +1,5 @@
cmake_minimum_required(VERSION 3.5.0)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/spdlog.cmake)
if(WIN32)
set(HAILORT_SERVICE_OS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/windows")
elseif(UNIX)
@@ -15,30 +13,20 @@ add_executable(hailort_service
cng_buffer_pool.cpp
service_resource_manager.hpp
${HAILORT_SERVICE_OS_DIR}/hailort_service.cpp
${HAILORT_COMMON_CPP_SOURCES}
${HAILO_FULL_OS_DIR}/event.cpp # TODO HRT-10681: move event.cpp to common
)
target_compile_options(hailort_service PRIVATE ${HAILORT_COMPILE_OPTIONS})
set_property(TARGET hailort_service PROPERTY CXX_STANDARD 14)
target_link_libraries(hailort_service
libhailort
spdlog::spdlog
hailort_common
grpc++_unsecure
hailort_rpc_grpc_proto
readerwriterqueue
)
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
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${HAILORT_INC_DIR}
${HAILORT_COMMON_DIR}
${HAILORT_SRC_DIR}
${COMMON_INC_DIR}
${RPC_DIR}

View File

@@ -156,6 +156,11 @@ void HailoRtRpcService::remove_disconnected_clients()
}
}
// Only for performance optimization (notice code is inside a locked mutex here)
if (pids_to_remove.empty()) {
return;
}
// We abort vstreams before releasing them to avoid cases where the vstream is stuck in execute of a
// 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.
@@ -295,6 +300,21 @@ grpc::Status HailoRtRpcService::VDevice_release(grpc::ServerContext*, const Rele
return grpc::Status::OK;
}
void HailoRtRpcService::release_resources_on_error(std::vector<uint32_t> ng_handles, std::vector<uint32_t> buffer_pool_handles, uint32_t pid)
{
auto &networks_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
for (auto &current_ng_handle : ng_handles) {
networks_manager.release_resource(current_ng_handle, pid);
}
for (auto &buffer_pool_handle : buffer_pool_handles) {
auto status = shutdown_cng_buffer_pool(buffer_pool_handle);
if (status != HAILO_SUCCESS) {
LOGGER__ERROR("Failed to shutdown cng buffer pool with handle={}, status={}", buffer_pool_handle, status);
}
networks_manager.release_resource(buffer_pool_handle, pid);
}
}
grpc::Status HailoRtRpcService::VDevice_configure(grpc::ServerContext*, const VDevice_configure_Request *request,
VDevice_configure_Reply *reply)
{
@@ -351,9 +371,12 @@ grpc::Status HailoRtRpcService::VDevice_configure(grpc::ServerContext*, const VD
CHECK_EXPECTED_AS_RPC_STATUS(networks, reply);
auto &networks_manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
std::vector<uint32_t> ng_handles;
std::vector<uint32_t> buffer_pool_handles;
for (auto network : networks.value()) {
auto ng_handle = networks_manager.register_resource(request->pid(), network);
reply->add_networks_handles(ng_handle);
ng_handles.push_back(ng_handle);
bool allocate_for_raw_streams = false;
// The network_group's buffer pool is used for the read's buffers,
@@ -363,16 +386,36 @@ grpc::Status HailoRtRpcService::VDevice_configure(grpc::ServerContext*, const VD
// We assume that if 1 stream is marked as ASYNC, they all are
allocate_for_raw_streams = true;
}
auto status = create_buffer_pools_for_ng(request->identifier().vdevice_handle(), ng_handle, request->pid(), allocate_for_raw_streams);
auto cng_buffer_pool_handle_exp = create_buffer_pool_for_ng(request->identifier().vdevice_handle(), request->pid());
// We check status like this, since need to release all the resources if one of the buffer pools failed to create
if (cng_buffer_pool_handle_exp.status() != HAILO_SUCCESS) {
release_resources_on_error(ng_handles, buffer_pool_handles, request->pid());
}
CHECK_EXPECTED_AS_RPC_STATUS(cng_buffer_pool_handle_exp, reply);
buffer_pool_handles.push_back(cng_buffer_pool_handle_exp.value());
if (cng_buffer_pool_handle_exp.value() != ng_handle) {
LOGGER__ERROR("cng_buffer_pool_handle = {} must be different from network_group_handle = {}", cng_buffer_pool_handle_exp.value(), ng_handle);
release_resources_on_error(ng_handles, buffer_pool_handles, request->pid());
CHECK_SUCCESS_AS_RPC_STATUS(HAILO_INTERNAL_FAILURE, reply);
}
if (allocate_for_raw_streams) {
auto status = allocate_pool_for_raw_streams(ng_handle);
// We check status like this, since need to release all the resources if one of the buffer pools failed to create
if (status != HAILO_SUCCESS) {
release_resources_on_error(ng_handles, buffer_pool_handles, request->pid());
}
CHECK_SUCCESS_AS_RPC_STATUS(status, reply);
}
reply->add_networks_handles(ng_handle);
}
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
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)
Expected<uint32_t> HailoRtRpcService::create_buffer_pool_for_ng(uint32_t vdevice_handle, uint32_t request_pid)
{
auto &cng_buffer_pool_manager = ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance();
@@ -380,15 +423,17 @@ hailo_status HailoRtRpcService::create_buffer_pools_for_ng(uint32_t vdevice_hand
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();
return make_unexpected(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);
return cng_buffer_pool_handle;
}
if (allocate_for_raw_streams) {
hailo_status HailoRtRpcService::allocate_pool_for_raw_streams(uint32_t ng_handle)
{
auto &cng_buffer_pool_manager = ServiceResourceManager<ServiceNetworkGroupBufferPool>::get_instance();
// For Async API - The buffer size in the pool will be the stream's hw frame size as used in the infer_model pipeline
TRY(const auto min_buffer_pool_size, get_min_buffer_pool_size(ng_handle));
TRY(const auto streams_infos, get_all_stream_infos(ng_handle));
@@ -402,7 +447,6 @@ hailo_status HailoRtRpcService::create_buffer_pools_for_ng(uint32_t vdevice_hand
CHECK_SUCCESS(cng_buffer_pool_manager.execute(ng_handle, allocate_lambda));
}
}
}
return HAILO_SUCCESS;
}
@@ -523,14 +567,14 @@ ProtoCallbackIdentifier serialize_callback_identifier_shm(uint32_t vdevice_handl
return cb_identifier;
}
hailo_status HailoRtRpcService::shutdown_cng_buffer_pool(uint32_t network_group_handle)
hailo_status HailoRtRpcService::shutdown_cng_buffer_pool(uint32_t buffer_pool_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(network_group_handle, buffer_shutdown_lambda);
auto status = buffer_pool_manager.execute(buffer_pool_handle, buffer_shutdown_lambda);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
@@ -674,11 +718,10 @@ 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) {
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);
} else if (status != HAILO_SUCCESS) {
LOGGER__ERROR("Failed to enqueue callback to VDeviceCallbacksQueue '{}' with status={}", vdevice_handle, status);
}
}
@@ -907,10 +950,15 @@ void serialize_vstream_info(const hailo_vstream_info_t &info, ProtoVStreamInfo *
format_proto->set_flags(info.format.flags);
format_proto->set_order(info.format.order);
format_proto->set_type(info.format.type);
if (info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
if (HailoRTCommon::is_nms(info.format.order)) {
auto nms_shape_proto = info_proto->mutable_nms_shape();
nms_shape_proto->set_number_of_classes(info.nms_shape.number_of_classes);
nms_shape_proto->set_max_bbox_per_class(info.nms_shape.max_bboxes_per_class);
if (info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS_BY_SCORE) {
nms_shape_proto->set_max_bboxes_total(info.nms_shape.max_bboxes_total);
} else {
nms_shape_proto->set_max_bboxes_per_class(info.nms_shape.max_bboxes_per_class);
}
nms_shape_proto->set_max_accumulated_mask_size(info.nms_shape.max_accumulated_mask_size);
} else {
auto shape_proto = info_proto->mutable_shape();
@@ -1225,7 +1273,11 @@ void serialize_op_matadata(hailort::net_flow::OpMetadata &op_metadata, ProtoOpMe
auto nms_config_proto = op_metadata_proto->mutable_nms_post_process_config();
nms_config_proto->set_nms_score_th(nms_config.nms_score_th);
nms_config_proto->set_nms_iou_th(nms_config.nms_iou_th);
if (HAILO_NMS_RESULT_ORDER_BY_SCORE == nms_config.order_type) {
nms_config_proto->set_max_proposals_total(nms_config.max_proposals_total);
} else {
nms_config_proto->set_max_proposals_per_class(nms_config.max_proposals_per_class);
}
nms_config_proto->set_number_of_classes(nms_config.number_of_classes);
nms_config_proto->set_background_removal(nms_config.background_removal);
nms_config_proto->set_background_removal_index(nms_config.background_removal_index);
@@ -1719,10 +1771,11 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_get_all_stream_infos(grpc
auto proto_stream_infos = reply->mutable_stream_infos();
for (const auto &stream_info : expected_stream_infos.value()) {
ProtoStreamInfo proto_stream_info;
if (stream_info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS) {
if (stream_info.format.order == HAILO_FORMAT_ORDER_HAILO_NMS_ON_CHIP) {
auto proto_nms_info = proto_stream_info.mutable_nms_info();
proto_nms_info->set_number_of_classes(stream_info.nms_info.number_of_classes);
proto_nms_info->set_max_bboxes_per_class(stream_info.nms_info.max_bboxes_per_class);
proto_nms_info->set_order_type(HAILO_NMS_RESULT_ORDER_HW);
proto_nms_info->set_bbox_size(stream_info.nms_info.bbox_size);
proto_nms_info->set_chunks_per_frame(stream_info.nms_info.chunks_per_frame);
proto_nms_info->set_is_defused(stream_info.nms_info.is_defused);
@@ -1928,6 +1981,36 @@ grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_nms_max_bboxes_per_cl
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_nms_max_bboxes_total(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_max_bboxes_total_Request *request,
ConfiguredNetworkGroup_set_nms_max_bboxes_total_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, const std::string &edge_name, uint32_t max_bboxes) {
return cng->set_nms_max_bboxes_total(edge_name, max_bboxes);
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto status = manager.execute(request->identifier().network_group_handle(), lambda,
request->edge_name(), request->nms_max_bboxes_total());
CHECK_SUCCESS_AS_RPC_STATUS(status, reply);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_nms_result_order_type(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_result_order_type_Request *request,
ConfiguredNetworkGroup_set_nms_result_order_type_Reply *reply)
{
auto lambda = [](std::shared_ptr<ConfiguredNetworkGroup> cng, const std::string &edge_name, hailo_nms_result_order_type_t order_type) {
return cng->set_nms_result_order_type(edge_name, order_type);
};
auto &manager = ServiceResourceManager<ConfiguredNetworkGroup>::get_instance();
auto status = manager.execute(request->identifier().network_group_handle(), lambda,
request->edge_name(), static_cast<hailo_nms_result_order_type_t>(request->nms_result_order_type()));
CHECK_SUCCESS_AS_RPC_STATUS(status, reply);
reply->set_status(static_cast<uint32_t>(HAILO_SUCCESS));
return grpc::Status::OK;
}
grpc::Status HailoRtRpcService::ConfiguredNetworkGroup_set_nms_max_accumulated_mask_size(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_max_accumulated_mask_size_Request *request,
ConfiguredNetworkGroup_set_nms_max_accumulated_mask_size_Reply *reply)

View File

@@ -208,6 +208,12 @@ public:
virtual grpc::Status ConfiguredNetworkGroup_set_nms_max_bboxes_per_class(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_max_bboxes_per_class_Request *request,
ConfiguredNetworkGroup_set_nms_max_bboxes_per_class_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_set_nms_max_bboxes_total(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_max_bboxes_total_Request *request,
ConfiguredNetworkGroup_set_nms_max_bboxes_total_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_set_nms_result_order_type(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_result_order_type_Request *request,
ConfiguredNetworkGroup_set_nms_result_order_type_Reply *reply) override;
virtual grpc::Status ConfiguredNetworkGroup_set_nms_max_accumulated_mask_size(grpc::ServerContext*,
const ConfiguredNetworkGroup_set_nms_max_accumulated_mask_size_Request *request,
ConfiguredNetworkGroup_set_nms_max_accumulated_mask_size_Reply *reply) override;
@@ -234,8 +240,9 @@ private:
Expected<std::vector<hailo_stream_info_t>> get_all_stream_infos(uint32_t ng_handle);
Expected<std::vector<hailo_vstream_info_t>> get_all_vstream_infos(uint32_t ng_handle);
Expected<std::string> output_vstream_name(uint32_t vstream_handle);
hailo_status create_buffer_pools_for_ng(uint32_t vdevice_handle, uint32_t ng_handle, uint32_t request_pid,
bool allocate_for_raw_streams);
Expected<uint32_t> create_buffer_pool_for_ng(uint32_t vdevice_handle, uint32_t request_pid);
hailo_status allocate_pool_for_raw_streams(uint32_t ng_handle);
void release_resources_on_error(std::vector<uint32_t> ng_handles, std::vector<uint32_t> buffer_pool_handles, uint32_t pid);
Expected<NamedBuffersCallbacks> prepare_named_buffers_callbacks(uint32_t vdevice_handle,
uint32_t ng_handle, std::shared_ptr<ConfiguredNetworkGroup_infer_async_Request> infer_async_request);
hailo_status add_input_named_buffer(const ProtoTransferRequest &proto_stream_transfer_request, uint32_t vdevice_handle,

View File

@@ -3,8 +3,6 @@ cmake_minimum_required(VERSION 3.5.0)
include(GNUInstallDirs)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/cli11.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/json.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/spdlog.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/readerwriterqueue.cmake)
include(${HAILO_EXTERNALS_CMAKE_SCRIPTS}/dotwriter.cmake)
set(HAILORTCLI_CPP_FILES
@@ -56,11 +54,9 @@ configure_file(${CONFIG_DEFENITIONS_IN} ${config_definitions_header})
add_executable(hailortcli
${config_definitions_header}
${HAILORTCLI_CPP_FILES}
${HAILORT_COMMON_CPP_SOURCES}
${PROJECT_SOURCE_DIR}/common/src/firmware_header_utils.c
${PROJECT_SOURCE_DIR}/common/src/md5.c
${HAILORT_SRC_DIR}/net_flow/pipeline/pipeline.cpp # TODO: link dynamically with libhailort
${HAILO_FULL_OS_DIR}/event.cpp # TODO: link dynamically with libhailort
)
target_compile_options(hailortcli PRIVATE ${HAILORT_COMPILE_OPTIONS})
@@ -74,20 +70,14 @@ target_link_libraries(hailortcli
libhailort
CLI11::CLI11
nlohmann_json
spdlog::spdlog
readerwriterqueue
hailort_common
eigen
DotWriter
scheduler_mon_proto
profiler_proto)
if(WIN32)
target_link_libraries(hailortcli Ws2_32 Iphlpapi Shlwapi winmm.lib)
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)
target_link_libraries(hailortcli winmm.lib) # Used for timeBeginPeriod, timeEndPeriod
endif()
target_include_directories(hailortcli

View File

@@ -31,8 +31,6 @@ 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);
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,

View File

@@ -0,0 +1,49 @@
/**
* Copyright (c) 2020-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file buffer_utils.hpp
* @brief Common buffer utility functions.
**/
#ifndef _HAILO_HAILORTCLI_BUFFER_UTILS_HPP_
#define _HAILO_HAILORTCLI_BUFFER_UTILS_HPP_
#include "hailo/buffer.hpp"
#include "hailo/expected.hpp"
#include <random>
using namespace hailort;
inline Expected<Buffer> create_uniformed_buffer(size_t size, BufferStorageParams params = BufferStorageParams::create_dma(), uint32_t seed = 0)
{
auto buffer = Buffer::create(size, params);
if (buffer) {
// https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
std::mt19937 gen(seed); // mersenne_twister_engine seeded with 'seed'
std::uniform_int_distribution<> distrib(0, std::numeric_limits<uint8_t>::max());
for (size_t i = 0; i < size; i++) {
buffer->data()[i] = static_cast<uint8_t>(distrib(gen));
}
}
return buffer;
}
inline Expected<std::shared_ptr<Buffer>> create_uniformed_buffer_shared(size_t size, BufferStorageParams params = BufferStorageParams::create_dma(), uint32_t seed = 0)
{
auto buffer = create_uniformed_buffer(size, params, seed);
if (buffer) {
auto buffer_ptr = std::make_shared<Buffer>(buffer.release());
if (nullptr == buffer_ptr) {
return make_unexpected(HAILO_OUT_OF_HOST_MEMORY);
}
return buffer_ptr;
}
return make_unexpected(buffer.status());
}
#endif /* _HAILO_HAILORTCLI_BUFFER_UTILS_HPP_ */

View File

@@ -10,7 +10,7 @@
#include "download_action_list_command.hpp"
#include "common.hpp"
#include "common/file_utils.hpp"
#include "common/string_utils.hpp"
#include "common/utils.hpp"
#include <iostream>
#include <iomanip>
@@ -71,7 +71,7 @@ Expected<ordered_json> DownloadActionListCommand::init_json_object(Device &devic
unsigned int clock_cycle = 0;
// TODO - HRT-8046 Implement extended device info for hailo15
if (HAILO_ARCH_HAILO15H == chip_arch) {
if ((HAILO_ARCH_HAILO15H == chip_arch) || (HAILO_ARCH_HAILO15L == chip_arch)) {
clock_cycle = HAILO15_VPU_CORE_CPU_DEFAULT_FREQ_MHZ;
} else {
TRY(auto extended_info, device.get_extended_device_information());

View File

@@ -12,7 +12,7 @@
#include "hailo/hailort.h"
#include "user_config_common.h"
#include "common/file_utils.hpp"
#include "common/string_utils.hpp"
#include "common/utils.hpp"
#include <fstream>
#include <sstream>

View File

@@ -9,7 +9,7 @@
#include "fw_control_command.hpp"
#include "firmware_header_utils.h"
#include "common/string_utils.hpp"
#include "common/utils.hpp"
static const char *NOT_CONFIGURED_ATTR = "<N/A>";
@@ -138,8 +138,8 @@ static std::string identity_arch_string(const hailo_device_identity_t &identity)
return "HAILO8L";
case HAILO_ARCH_HAILO15H:
return "HAILO15H";
case HAILO_ARCH_PLUTO:
return "PLUTO";
case HAILO_ARCH_HAILO15L:
return "HAILO15L";
case HAILO_ARCH_HAILO15M:
return "HAILO15M";
case HAILO_ARCH_HAILO10H:

View File

@@ -111,20 +111,19 @@ Expected<LongPowerMeasurement> PowerMeasurementSubcommand::start_power_measureme
return make_unexpected(HAILO_NOT_FOUND);
}
hailo_status status = hailo_stop_power_measurement(reinterpret_cast<hailo_device>(&device));
hailo_status status = device.stop_power_measurement();
if (HAILO_SUCCESS != status) {
std::cerr << "Failed initial power measurement stop, status " << status << std::endl;
return make_unexpected(status);
}
status = hailo_set_power_measurement(reinterpret_cast<hailo_device>(&device), HAILO_MEASUREMENT_BUFFER_INDEX_0, dvm, measurement_type);
status = device.set_power_measurement(HAILO_MEASUREMENT_BUFFER_INDEX_0, dvm, measurement_type);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to set power measurement parameters, status " << status << std::endl;
return make_unexpected(status);
}
status = hailo_start_power_measurement(reinterpret_cast<hailo_device>(&device),
averaging_factor_enum, sampling_period_enum);
status = device.start_power_measurement(averaging_factor_enum, sampling_period_enum);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to start power measurement, status " << status << std::endl;
return make_unexpected(status);
@@ -140,17 +139,13 @@ LongPowerMeasurement::LongPowerMeasurement(Device &device,
hailo_status LongPowerMeasurement::stop()
{
hailo_status status = hailo_stop_power_measurement(reinterpret_cast<hailo_device>(&m_device));
hailo_status status = m_device.stop_power_measurement();
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to stop power measurement, status " << status << std::endl;
return status;
}
status = hailo_get_power_measurement(reinterpret_cast<hailo_device>(&m_device), HAILO_MEASUREMENT_BUFFER_INDEX_0, true, &m_data);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to get power measurement results, status " << status << std::endl;
return status;
}
TRY(m_data, m_device.get_power_measurement(HAILO_MEASUREMENT_BUFFER_INDEX_0, true));
const char *power_units = PowerMeasurementSubcommand::get_power_units(m_measurement_type);
if (nullptr == power_units) {
@@ -255,13 +250,7 @@ const char *PowerMeasurementSubcommand::get_power_units(hailo_power_measurement_
hailo_status PowerMeasurementSubcommand::run_single_power_measurement(Device &device)
{
float32_t measurement = 0.0f;
hailo_status status = hailo_power_measurement(reinterpret_cast<hailo_device>(&device), m_params.dvm_option, m_params.measurement_type,
&measurement);
if (HAILO_SUCCESS != status) {
std::cerr << "Failed to get power measurement results, status " << status << std::endl;
return status;
}
TRY(auto measurement, device.power_measurement(m_params.dvm_option, m_params.measurement_type));
const char *power_units = get_power_units(m_params.measurement_type);
if (nullptr == power_units) {

View File

@@ -13,6 +13,8 @@
#include "network_live_track.hpp"
#include "../buffer_utils.hpp"
#include "common/file_utils.hpp"
#include "common/latency_meter.hpp"
@@ -143,20 +145,18 @@ private:
static Expected<std::vector<BufferPtr>> create_dataset(Writer &writer, const WriterParams &params)
{
if (params.input_file_path.empty()) {
return create_constant_dataset(writer.get_frame_size());
return create_random_dataset(writer.get_frame_size());
} else {
return create_dataset_from_input_file(params.input_file_path, writer.get_frame_size());
}
}
static Expected<std::vector<BufferPtr>> create_constant_dataset(size_t frame_size)
static Expected<std::vector<BufferPtr>> create_random_dataset(size_t frame_size)
{
const uint8_t const_byte = 0xAB;
TRY(auto buffer,
create_uniformed_buffer_shared(frame_size, BufferStorageParams::create_dma()));
TRY(auto constant_buffer,
Buffer::create_shared(frame_size, const_byte, BufferStorageParams::create_dma()));
return std::vector<BufferPtr>{ constant_buffer };
return std::vector<BufferPtr>{ buffer };
}
static Expected<std::vector<BufferPtr>> create_dataset_from_input_file(const std::string &file_path, size_t frame_size)

View File

@@ -596,14 +596,13 @@ hailo_status FullAsyncNetworkRunner::run_single_thread_async_infer(EventPtr shut
std::vector<Buffer> output_buffers;
std::vector<DmaMappedBuffer> dma_mapped_buffers;
const uint8_t const_byte = 0xAB;
for (const auto &name : get_input_names()) {
TRY(auto input_config, m_infer_model->input(name));
auto params = get_params(name);
Buffer buffer {};
if (params.input_file_path.empty()) {
TRY(buffer, Buffer::create(input_config.get_frame_size(), const_byte, BufferStorageParams::create_dma()));
TRY(buffer, create_uniformed_buffer(input_config.get_frame_size(), BufferStorageParams::create_dma()));
} else {
TRY(buffer, read_binary_file(params.input_file_path, BufferStorageParams::create_dma()));
}

View File

@@ -315,7 +315,7 @@ protected:
private:
static const std::vector<hailo_status> ALLOWED_INFERENCE_RETURN_VALUES;
static hailo_status wait_for_threads(std::vector<AsyncThreadPtr<hailo_status>> &threads);
static Expected<BufferPtr> create_constant_dataset(size_t size);
static Expected<BufferPtr> create_random_dataset(size_t size);
static Expected<BufferPtr> create_dataset_from_input_file(const std::string &file_path, size_t size);
};

View File

@@ -8,6 +8,7 @@
**/
#include "run2_command.hpp"
#include "common/utils.hpp"
#include "live_stats.hpp"
#include "timer_live_track.hpp"
#include "measurement_live_track.hpp"
@@ -200,6 +201,8 @@ VStreamApp::VStreamApp(const std::string &description, const std::string &name,
{ "bayer_rgb", HAILO_FORMAT_ORDER_BAYER_RGB },
{ "12_bit_bayer_rgb", HAILO_FORMAT_ORDER_12_BIT_BAYER_RGB },
{ "hailo_nms", HAILO_FORMAT_ORDER_HAILO_NMS },
{ "hailo_nms_by_class", HAILO_FORMAT_ORDER_HAILO_NMS_BY_CLASS },
{ "hailo_nms_by_score", HAILO_FORMAT_ORDER_HAILO_NMS_BY_SCORE },
{ "nchw", HAILO_FORMAT_ORDER_NCHW },
{ "yuy2", HAILO_FORMAT_ORDER_YUY2 },
{ "nv12", HAILO_FORMAT_ORDER_NV12 },
@@ -303,9 +306,9 @@ public:
std::chrono::seconds get_time_to_run();
std::vector<hailo_device_id_t> get_dev_ids();
uint32_t get_device_count();
bool get_measure_power();
bool get_measure_current();
bool get_measure_temp();
bool user_requested_power_measurement();
bool user_requested_current_measurement();
bool user_requested_temperature_measurement();
bool get_measure_hw_latency();
bool get_measure_overall_latency();
bool get_multi_process_service();
@@ -478,17 +481,17 @@ std::chrono::seconds Run2::get_time_to_run()
return std::chrono::seconds(m_time_to_run);
}
bool Run2::get_measure_power()
bool Run2::user_requested_power_measurement()
{
return m_measure_power;
}
bool Run2::get_measure_current()
bool Run2::user_requested_current_measurement()
{
return m_measure_current;
}
bool Run2::get_measure_temp()
bool Run2::user_requested_temperature_measurement()
{
return m_measure_temp;
}
@@ -737,20 +740,20 @@ Expected<std::vector<std::shared_ptr<NetworkRunner>>> Run2::init_and_run_net_run
activation_barrier.arrive_and_wait();
if (get_measure_power() || get_measure_current() || get_measure_temp()) {
if (user_requested_power_measurement() || user_requested_current_measurement() || user_requested_temperature_measurement()) {
TRY(auto physical_devices, vdevice->get_physical_devices());
for (auto &device : physical_devices) {
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 supported_features, device.get().get_capabilities(), "Failed getting device capabilities");
CHECK_AS_EXPECTED(!user_requested_power_measurement() || supported_features.power_measurements,
HAILO_INVALID_OPERATION, "Power measurement not supported. Disable the measure-power option");
CHECK_AS_EXPECTED(!user_requested_current_measurement() || supported_features.current_measurements,
HAILO_INVALID_OPERATION, "Current measurement not supported. Disable the measure-current option");
CHECK_AS_EXPECTED(!user_requested_temperature_measurement() || supported_features.temperature_measurements,
HAILO_INVALID_OPERATION, "Temperature measurement not supported. Disable the measure-temp option");
TRY(auto measurement_live_track, MeasurementLiveTrack::create_shared(device.get(),
get_measure_power(), get_measure_current(), get_measure_temp()));
user_requested_power_measurement(), user_requested_current_measurement(),
user_requested_temperature_measurement()));
live_stats->add(measurement_live_track, 2);
}

View File

@@ -14,8 +14,9 @@
#include "graph_printer.hpp"
#include "download_action_list_command.hpp"
#include "common.hpp"
#include "buffer_utils.hpp"
#include "common/string_utils.hpp"
#include "common/utils.hpp"
#include "common/file_utils.hpp"
#include "common/async_thread.hpp"
#include "common/barrier.hpp"
@@ -898,32 +899,31 @@ static Expected<InferResult> run_inference(const std::vector<std::shared_ptr<Con
}
}
static Expected<std::map<std::string, BufferPtr>> create_constant_dataset(
static Expected<std::map<std::string, BufferPtr>> create_uniformed_dataset(
const std::pair<std::vector<hailo_stream_info_t>, std::vector<hailo_vstream_info_t>> &input_infos, const hailo_transform_params_t &trans_params,
InferMode mode)
{
const uint8_t const_byte = 0xAB;
std::map<std::string, BufferPtr> dataset;
if (InferMode::HW_ONLY == mode) {
for (const auto &input_stream_info : input_infos.first) {
const auto frame_size = input_stream_info.hw_frame_size;
auto constant_buffer = Buffer::create_shared(frame_size, const_byte);
if (!constant_buffer) {
auto buffer = create_uniformed_buffer_shared(frame_size);
if (!buffer) {
std::cerr << "Out of memory, tried to allocate " << frame_size << std::endl;
return make_unexpected(constant_buffer.status());
return make_unexpected(buffer.status());
}
dataset.emplace(std::string(input_stream_info.name), constant_buffer.release());
dataset.emplace(std::string(input_stream_info.name), buffer.release());
}
} else {
for (const auto &input_vstream_info : input_infos.second) {
const auto frame_size = HailoRTCommon::get_frame_size(input_vstream_info, trans_params.user_buffer_format);
auto constant_buffer = Buffer::create_shared(frame_size, const_byte);
if (!constant_buffer) {
auto buffer = create_uniformed_buffer_shared(frame_size);
if (!buffer) {
std::cerr << "Out of memory, tried to allocate " << frame_size << std::endl;
return make_unexpected(constant_buffer.status());
return make_unexpected(buffer.status());
}
dataset.emplace(std::string(input_vstream_info.name), constant_buffer.release());
dataset.emplace(std::string(input_vstream_info.name), buffer.release());
}
}
@@ -1021,7 +1021,7 @@ static Expected<std::vector<std::map<std::string, BufferPtr>>> create_dataset(
}
} else {
for (auto &group_input_infos : input_infos) {
TRY(auto network_group_dataset, create_constant_dataset(group_input_infos, trans_params, params.mode));
TRY(auto network_group_dataset, create_uniformed_dataset(group_input_infos, trans_params, params.mode));
results.emplace_back(std::move(network_group_dataset));
}
}

View File

@@ -1,20 +1,13 @@
cmake_minimum_required(VERSION 3.5.0)
set(HRPC_IMPL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/os")
if(WIN32)
set(HRPC_OS_DIR "${HRPC_IMPL_DIR}/windows")
elseif(UNIX)
set(HRPC_OS_DIR "${HRPC_IMPL_DIR}/posix")
else()
message(FATAL_ERROR "Unexpeced host, stopping build")
endif()
set(RAW_CONN_IMPL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/raw_connection_internal")
set(SRC_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rpc_connection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/raw_connection.cpp
${HRPC_IMPL_DIR}/pcie/raw_connection_internal.cpp
${HRPC_OS_DIR}/raw_connection_internal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hailo_session.cpp
${RAW_CONN_IMPL_DIR}/pcie/hailo_session_internal.cpp
${RAW_CONN_IMPL_DIR}/socket/hailo_session_internal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/connection_context.cpp
${CMAKE_CURRENT_SOURCE_DIR}/client.cpp
${CMAKE_CURRENT_SOURCE_DIR}/server.cpp
)

View File

@@ -8,12 +8,23 @@
**/
#include "client.hpp"
#include "connection_context.hpp"
using namespace hrpc;
namespace hailort
{
std::chrono::milliseconds get_request_timeout()
{
auto timeout_seconds = get_env_variable(HAILO_REQUEST_TIMEOUT_SECONDS);
if (timeout_seconds) {
return std::chrono::seconds(std::stoi(timeout_seconds.value()));
}
return REQUEST_TIMEOUT;
}
Expected<std::shared_ptr<ResultEvent>> ResultEvent::create_shared()
{
TRY(auto event, hailort::Event::create_shared(hailort::Event::State::not_signalled));
TRY(auto event, Event::create_shared(Event::State::not_signalled));
auto ptr = make_shared_nothrow<ResultEvent>(event);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
@@ -47,16 +58,20 @@ Client::~Client()
if (m_thread.joinable()) {
m_thread.join();
}
for (const auto &callback : m_replies_callbacks) {
Buffer buffer;
callback.second(HAILO_COMMUNICATION_CLOSED, std::move(buffer));
}
}
hailo_status Client::connect()
{
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);
auto port = get_pcie_port();
TRY(auto conn, Session::connect(m_conn_context, port));
m_connection = RpcConnection(conn);
TRY(m_connection, RpcConnection::create(conn));
m_thread = std::thread([this] {
auto status = message_loop();
if ((status != HAILO_SUCCESS) && (status != HAILO_COMMUNICATION_CLOSED)) { // TODO: Use this to prevent future requests
@@ -69,36 +84,78 @@ hailo_status Client::connect()
hailo_status Client::message_loop()
{
while (m_is_running) {
rpc_message_header_t header;
TRY_WITH_ACCEPTABLE_STATUS(HAILO_COMMUNICATION_CLOSED, auto message, m_connection.read_message(header));
TRY_WITH_ACCEPTABLE_STATUS(HAILO_COMMUNICATION_CLOSED, auto message, m_connection.read_message());
assert(header.action_id < static_cast<uint32_t>(HailoRpcActionID::MAX_VALUE));
auto action_id_enum = static_cast<HailoRpcActionID>(header.action_id);
assert(message.header.action_id < static_cast<uint32_t>(HailoRpcActionID::MAX_VALUE));
auto action_id_enum = static_cast<HailoRpcActionID>(message.header.action_id);
if (m_custom_callbacks.find(action_id_enum) != m_custom_callbacks.end()) {
auto status = m_custom_callbacks[action_id_enum](MemoryView(message), m_connection);
auto status = m_custom_callbacks[action_id_enum](MemoryView(message.buffer), m_connection);
CHECK_SUCCESS(status);
continue;
}
std::shared_ptr<ResultEvent> event = nullptr;
std::function<void(hailo_status, Buffer&&)> reply_received_callback = nullptr;
{
std::unique_lock<std::mutex> lock(m_events_mutex);
m_events_cv.wait(lock, [this, &header] () {
return contains(m_events, header.message_id);
std::unique_lock<std::mutex> lock(m_replies_mutex);
m_replies_cv.wait(lock, [this, &message] () {
return contains(m_replies_callbacks, message.header.message_id);
});
event = m_events[header.message_id];
m_events.erase(header.message_id);
reply_received_callback = m_replies_callbacks[message.header.message_id];
m_replies_callbacks.erase(message.header.message_id);
}
auto status = event->signal(std::move(message));
CHECK_SUCCESS(status);
reply_received_callback(HAILO_SUCCESS, std::move(message.buffer));
}
return HAILO_SUCCESS;
}
Expected<Buffer> Client::execute_request(HailoRpcActionID action_id, const MemoryView &request,
std::function<hailo_status(RpcConnection)> write_buffers_callback)
std::function<hailo_status(RpcConnection)> additional_writes_lambda)
{
auto status = wait_for_execute_request_ready(request, get_request_timeout());
CHECK_SUCCESS(status);
hailo_status transfer_status = HAILO_UNINITIALIZED;
Buffer out_reply;
auto request_sent_callback = [] (hailo_status status) {
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to send request, status = {}", status);
}
};
auto reply_received_callback = [&] (hailo_status status, Buffer &&reply) {
{
std::unique_lock<std::mutex> lock(m_sync_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
out_reply = std::move(reply);
}
m_sync_cv.notify_one();
};
status = execute_request_async(action_id, request, request_sent_callback,
reply_received_callback, additional_writes_lambda);
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
}
CHECK_SUCCESS_AS_EXPECTED(status);
std::unique_lock<std::mutex> lock(m_sync_mutex);
CHECK_AS_EXPECTED(m_sync_cv.wait_for(lock, get_request_timeout(), [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
CHECK_SUCCESS(transfer_status);
return out_reply;
}
hailo_status Client::wait_for_execute_request_ready(const MemoryView &request, std::chrono::milliseconds timeout)
{
return m_connection.wait_for_write_message_async_ready(request.size(), timeout);
}
hailo_status Client::execute_request_async(HailoRpcActionID action_id, const MemoryView &request,
std::function<void(hailo_status)> request_sent_callback,
std::function<void(hailo_status, Buffer&&)> reply_received_callback,
std::function<hailo_status(RpcConnection)> additional_writes_lambda)
{
rpc_message_header_t header;
{
@@ -107,31 +164,28 @@ Expected<Buffer> Client::execute_request(HailoRpcActionID action_id, const Memor
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);
CHECK_SUCCESS_AS_EXPECTED(status);
auto status = m_connection.write_message_async(header, request, std::move(request_sent_callback));
CHECK_SUCCESS(status);
if (additional_writes_lambda) {
status = additional_writes_lambda(m_connection);
CHECK_SUCCESS(status);
}
}
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;
std::unique_lock<std::mutex> lock(m_replies_mutex);
m_replies_callbacks[header.message_id] = reply_received_callback;
}
m_events_cv.notify_all();
m_replies_cv.notify_all();
auto status = event->wait(REQUEST_TIMEOUT);
CHECK_SUCCESS_AS_EXPECTED(status);
return event->release();
return HAILO_SUCCESS;
}
void Client::register_custom_reply(HailoRpcActionID action_id,
std::function<hailo_status(const MemoryView&, RpcConnection connection)> callback)
{
m_custom_callbacks[action_id] = callback;
}
} // namespace hailort

View File

@@ -17,12 +17,16 @@
#include "rpc_connection.hpp"
#include "hrpc_protocol/serializer.hpp"
#include "hrpc/connection_context.hpp"
namespace hrpc
namespace hailort
{
#define REQUEST_TIMEOUT std::chrono::milliseconds(10000)
#ifndef HAILO_EMULATOR
constexpr std::chrono::milliseconds REQUEST_TIMEOUT(std::chrono::seconds(10));
#else /* ifndef HAILO_EMULATOR */
constexpr std::chrono::milliseconds REQUEST_TIMEOUT(std::chrono::seconds(5000));
#endif /* ifndef HAILO_EMULATOR */
class ResultEvent
{
@@ -42,13 +46,19 @@ private:
class Client
{
public:
Client(const std::string &device_id) : m_device_id(device_id), m_is_running(true) {}
Client(const std::string &device_id) : m_device_id(device_id), m_is_running(true), m_messages_sent(0) {}
~Client();
hailo_status connect();
Expected<Buffer> execute_request(HailoRpcActionID action_id, const MemoryView &request,
std::function<hailo_status(RpcConnection)> write_buffers_callback = nullptr);
std::function<hailo_status(RpcConnection)> additional_writes_lambda = nullptr);
hailo_status wait_for_execute_request_ready(const MemoryView &request, std::chrono::milliseconds timeout);
hailo_status execute_request_async(HailoRpcActionID action_id, const MemoryView &request,
std::function<void(hailo_status)> request_sent_callback,
std::function<void(hailo_status, Buffer&&)> reply_received_callback,
std::function<hailo_status(RpcConnection)> additional_writes_lambda = nullptr);
void register_custom_reply(HailoRpcActionID action_id, std::function<hailo_status(const MemoryView&, RpcConnection connection)> callback);
std::shared_ptr<HailoRTDriver> get_driver() { return m_conn_context->get_driver(); };
protected:
hailo_status message_loop();
@@ -58,14 +68,16 @@ protected:
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<uint32_t, std::function<void(hailo_status, Buffer&&)>> m_replies_callbacks;
std::unordered_map<HailoRpcActionID, std::function<hailo_status(const MemoryView&, RpcConnection)>> m_custom_callbacks;
uint32_t m_messages_sent = 0;
uint32_t m_messages_sent;
std::mutex m_write_mutex;
std::condition_variable m_events_cv;
std::mutex m_events_mutex;
std::condition_variable m_replies_cv;
std::mutex m_replies_mutex;
std::mutex m_sync_mutex;
std::condition_variable m_sync_cv;
};
} // namespace hrpc
} // namespace hailort
#endif // _CLIENT_HPP_

View File

@@ -3,31 +3,42 @@
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection.cpp
* @brief Raw Connection
* @file connection_context.cpp
* @brief Connection Context
**/
#include "hailo/vdevice.hpp"
#include "hrpc/raw_connection.hpp"
#include "hrpc/os/pcie/raw_connection_internal.hpp"
#include "connection_context.hpp"
#include "hailo/hailo_session.hpp"
#include "common/internal_env_vars.hpp"
#include "hailo/vdevice.hpp"
#include "hrpc/raw_connection_internal/pcie/hailo_session_internal.hpp"
#include "hrpc/raw_connection_internal/socket/hailo_session_internal.hpp"
#ifdef _WIN32
#include "hrpc/os/windows/raw_connection_internal.hpp"
#else
#include "hrpc/os/posix/raw_connection_internal.hpp"
#endif
namespace hailort
{
Expected<std::shared_ptr<ConnectionContext>> ConnectionContext::create_shared(const std::string &device_id)
{
auto should_force_socket_com = get_env_variable(HAILO_SOCKET_COM_ADDR_CLIENT_ENV_VAR);
using namespace hrpc;
// If forcing hrpc service, its because we work without EP driver -> use sockets
if (should_force_socket_com.has_value()) {
return OsConnectionContext::create_shared(false);
} else {
if (HailoRTDriver::is_pcie_ep_loaded()) {
return PcieConnectionContext::create_server_shared();
} else {
return PcieConnectionContext::create_client_shared(device_id);
}
}
}
Expected<std::shared_ptr<ConnectionContext>> ConnectionContext::create_client_shared(const std::string &device_id)
{
auto should_force_socket_com = get_env_variable(HAILO_SOCKET_COM_ADDR_CLIENT_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()) {
if (should_force_socket_com.has_value()) {
return OsConnectionContext::create_shared(false);
} else {
return PcieConnectionContext::create_client_shared(device_id);
@@ -39,20 +50,11 @@ Expected<std::shared_ptr<ConnectionContext>> ConnectionContext::create_server_sh
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()) {
if (should_force_socket_com.has_value()) {
return OsConnectionContext::create_shared(true);
} else {
return PcieConnectionContext::create_server_shared();
}
}
Expected<std::shared_ptr<RawConnection>> RawConnection::create_shared(std::shared_ptr<ConnectionContext> context)
{
// Create according to ConnectionContext type
auto os_connection_context = std::dynamic_pointer_cast<OsConnectionContext>(context);
if (os_connection_context != nullptr) {
return OsRawConnection::create_shared(os_connection_context);
} else {
return PcieRawConnection::create_shared(std::dynamic_pointer_cast<PcieConnectionContext>(context));
}
}
} // namespace hailort

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file connection_context.hpp
* @brief Connection Context - holds the driver instance
**/
#ifndef _HAILO_CONNECTION_CONTEXT_HPP_
#define _HAILO_CONNECTION_CONTEXT_HPP_
#include "hailo/expected.hpp"
#include "vdma/driver/hailort_driver.hpp"
#include <memory>
namespace hailort
{
class ConnectionContext
{
public:
static Expected<std::shared_ptr<ConnectionContext>> create_client_shared(const std::string &device_id = "");
static Expected<std::shared_ptr<ConnectionContext>> create_server_shared();
static Expected<std::shared_ptr<ConnectionContext>> create_shared(const std::string &device_id = "");
bool is_accepting() const { return m_is_accepting; }
virtual std::shared_ptr<HailoRTDriver> get_driver() { return nullptr; };
ConnectionContext(bool is_accepting) : m_is_accepting(is_accepting) {}
virtual ~ConnectionContext() = default;
protected:
bool m_is_accepting;
};
} // namespace hailort
#endif // _HAILO_CONNECTION_CONTEXT_HPP_

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailo_session.cpp
* @brief Hailo Session
**/
#include "hailo/vdevice.hpp"
#include "hailo/hailo_session.hpp"
#include "hrpc/raw_connection_internal/pcie/hailo_session_internal.hpp"
#include "hrpc/raw_connection_internal/socket/hailo_session_internal.hpp"
#include "common/internal_env_vars.hpp"
#include "connection_context.hpp"
namespace hailort
{
Expected<std::shared_ptr<SessionListener>> SessionListener::create_shared(uint16_t port, const std::string &device_id)
{
TRY(auto context, ConnectionContext::create_shared(device_id));
return SessionListener::create_shared(context, port);
}
Expected<std::shared_ptr<SessionListener>> SessionListener::create_shared(std::shared_ptr<ConnectionContext> context, uint16_t port)
{
// Create according to ConnectionContext type
auto os_connection_context = std::dynamic_pointer_cast<OsConnectionContext>(context);
if (os_connection_context != nullptr) {
return OsListener::create_shared(os_connection_context, port);
} else {
return RawPcieListener::create_shared(std::dynamic_pointer_cast<PcieConnectionContext>(context), port);
}
}
Expected<std::shared_ptr<Session>> Session::connect(uint16_t port, const std::string &device_id)
{
// Create according to ConnectionContext type
TRY(auto context, ConnectionContext::create_shared(device_id));
auto os_connection_context = std::dynamic_pointer_cast<OsConnectionContext>(context);
if (os_connection_context != nullptr) {
return OsSession::connect(os_connection_context, port);
} else {
return RawPcieSession::connect(std::dynamic_pointer_cast<PcieConnectionContext>(context), port);
}
}
Expected<std::shared_ptr<Session>> Session::connect(std::shared_ptr<ConnectionContext> context, uint16_t port)
{
// Create according to ConnectionContext type
auto os_connection_context = std::dynamic_pointer_cast<OsConnectionContext>(context);
if (os_connection_context != nullptr) {
return OsSession::connect(os_connection_context, port);
} else {
return RawPcieSession::connect(std::dynamic_pointer_cast<PcieConnectionContext>(context), port);
}
}
constexpr std::chrono::milliseconds Session::DEFAULT_WRITE_TIMEOUT;
constexpr std::chrono::milliseconds Session::DEFAULT_READ_TIMEOUT;
} // namespace hailort

View File

@@ -1,211 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection_internal.cpp
* @brief PCIE Raw Connection
**/
#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 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_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()));
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);
}
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()
{
std::unique_lock<std::mutex> lock(m_mutex);
bool was_successful = m_cv.wait_for(lock, std::chrono::milliseconds(HAILO_INFINITE), [this] () -> bool {
return (m_conn_count == 0);
});
CHECK(was_successful, HAILO_TIMEOUT, "Got timeout in accept");
m_conn_count++;
return HAILO_SUCCESS;
}
void PcieConnectionContext::mark_connection_closed()
{
{
std::unique_lock<std::mutex> lock(m_mutex);
m_conn_count--;
}
m_cv.notify_one();
}
Expected<std::shared_ptr<RawConnection>> PcieRawConnection::create_shared(std::shared_ptr<PcieConnectionContext> context)
{
auto ptr = make_shared_nothrow<PcieRawConnection>(context);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<RawConnection>(ptr);
}
Expected<std::shared_ptr<RawConnection>> PcieRawConnection::accept()
{
auto status = m_context->wait_for_available_connection();
CHECK_SUCCESS(status);
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(), get_pcie_port()));
status = new_conn->set_session(std::move(session));
CHECK_SUCCESS(status);
return std::dynamic_pointer_cast<RawConnection>(new_conn);
}
hailo_status PcieRawConnection::set_session(PcieSession &&session)
{
m_session = make_shared_nothrow<PcieSession>(std::move(session));
CHECK_NOT_NULL(m_session, HAILO_OUT_OF_HOST_MEMORY);
return HAILO_SUCCESS;
}
hailo_status PcieRawConnection::connect()
{
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, std::chrono::milliseconds timeout)
{
if (0 == size) {
return HAILO_SUCCESS;
}
const auto alignment = OsUtils::get_dma_able_alignment();
const auto max_size = PcieSession::max_transfer_size();
bool is_aligned = ((reinterpret_cast<uintptr_t>(buffer) % alignment )== 0);
size_t bytes_written = 0;
while (bytes_written < size) {
size_t amount_to_write = 0;
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, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
} 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, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
}
bytes_written += amount_to_write;
}
return HAILO_SUCCESS;
}
hailo_status PcieRawConnection::read(uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
if (0 == size) {
return HAILO_SUCCESS;
}
const auto alignment = OsUtils::get_dma_able_alignment();
const auto max_size = PcieSession::max_transfer_size();
bool is_aligned = ((reinterpret_cast<uintptr_t>(buffer) % alignment) == 0);
size_t bytes_read = 0;
while (bytes_read < size) {
size_t amount_to_read = 0;
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, 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, timeout);
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
memcpy(buffer + bytes_read, m_context->read_buffer().data(), amount_to_read);
}
bytes_read += amount_to_read;
}
return HAILO_SUCCESS;
}
hailo_status PcieRawConnection::close()
{
auto status = m_session->close();
CHECK_SUCCESS(status);
m_context->mark_connection_closed();
return HAILO_SUCCESS;
}

View File

@@ -1,81 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection_internal.hpp
* @brief Raw Connection Header for pcie based comunication
**/
#ifndef _PCIE_RAW_CONNECTION_INTERNAL_HPP_
#define _PCIE_RAW_CONNECTION_INTERNAL_HPP_
#include "hailo/expected.hpp"
#include "vdma/pcie_session.hpp"
#include "hrpc/raw_connection.hpp"
#include <memory>
#include <condition_variable>
using namespace hailort;
namespace hrpc
{
class PcieConnectionContext : public ConnectionContext
{
public:
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)
: ConnectionContext(is_accepting), m_driver(std::move(driver)),
m_write_buffer(std::move(write_buffer)), m_read_buffer(std::move(read_buffer)),
m_conn_count(0) {}
virtual ~PcieConnectionContext() = default;
std::shared_ptr<HailoRTDriver> driver() { return m_driver; }
Buffer &write_buffer() { return m_write_buffer; }
Buffer &read_buffer() { return m_read_buffer; }
hailo_status wait_for_available_connection();
void mark_connection_closed();
private:
std::shared_ptr<HailoRTDriver> m_driver;
Buffer m_write_buffer;
Buffer m_read_buffer;
uint32_t m_conn_count;
std::mutex m_mutex;
std::condition_variable m_cv;
};
class PcieRawConnection : public RawConnection
{
public:
static Expected<std::shared_ptr<RawConnection>> create_shared(std::shared_ptr<PcieConnectionContext> context);
PcieRawConnection() = default;
virtual ~PcieRawConnection() = default;
virtual Expected<std::shared_ptr<RawConnection>> accept() override;
virtual hailo_status connect() 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) {}
private:
hailo_status set_session(PcieSession &&session);
std::shared_ptr<PcieConnectionContext> m_context;
std::shared_ptr<PcieSession> m_session;
};
} // namespace hrpc
#endif // _PCIE_RAW_CONNECTION_INTERNAL_HPP_

View File

@@ -1,250 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection_internal.cpp
* @brief Linux Sockets Raw Connection
**/
#include "hrpc/os/posix/raw_connection_internal.hpp"
#include <sys/socket.h>
#include <sys/un.h>
#include <string>
#include <unistd.h>
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include "common/internal_env_vars.hpp"
#include "hailo/hailort.h"
using namespace hrpc;
Expected<std::shared_ptr<ConnectionContext>> OsConnectionContext::create_shared(bool is_accepting)
{
auto ptr = make_shared_nothrow<OsConnectionContext>(is_accepting);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
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()) {
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 {
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)));
}
}
return ptr;
}
Expected<std::shared_ptr<RawConnection>> OsRawConnection::accept()
{
int fd = ::accept(m_fd, nullptr, nullptr);
CHECK_AS_EXPECTED(fd >= 0, HAILO_FILE_OPERATION_FAILURE, "Accept error, errno = {}", errno);
std::shared_ptr<RawConnection> ptr = make_shared_nothrow<OsRawConnection>(fd, m_context);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
hailo_status OsRawConnection::connect_localhost()
{
struct sockaddr_un server_addr;
std::string addr = "/tmp/unix_socket";
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strncpy(server_addr.sun_path, addr.c_str(), addr.size());
int result = ::connect(m_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
CHECK(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Connect error, errno = {}", errno);
return HAILO_SUCCESS;
}
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) {
ssize_t result = ::send(m_fd, buffer + bytes_written, size - bytes_written, MSG_NOSIGNAL);
CHECK(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Write error, errno = {}", errno);
bytes_written += result;
}
return HAILO_SUCCESS;
}
hailo_status OsRawConnection::read(uint8_t *buffer, size_t size, std::chrono::milliseconds /*timeout*/)
{
size_t bytes_read = 0;
while (bytes_read < size) {
ssize_t result = ::read(m_fd, buffer + bytes_read, size - bytes_read);
if (0 == result) {
return HAILO_COMMUNICATION_CLOSED; // 0 means the communication is closed
}
CHECK(result >= 0, HAILO_FILE_OPERATION_FAILURE, "Read error, errno = {}", errno);
bytes_read += result;
}
return HAILO_SUCCESS;
}
hailo_status OsRawConnection::close()
{
int result = ::shutdown(m_fd, SHUT_RDWR);
CHECK(0 == result, HAILO_CLOSE_FAILURE, "Socket shutdown failed, errno = {}", errno);
result = ::close(m_fd);
CHECK(0 == result, HAILO_CLOSE_FAILURE, "Socket close failed, errno = {}", errno);
return HAILO_SUCCESS;
}

View File

@@ -1,68 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection_internal.hpp
* @brief Raw Connection Header for sockets based comunication
**/
#ifndef _POSIX_RAW_CONNECTION_INTERNAL_HPP_
#define _POSIX_RAW_CONNECTION_INTERNAL_HPP_
#include "hailo/expected.hpp"
#include "hrpc/raw_connection.hpp"
#include <memory>
using namespace hailort;
namespace hrpc
{
class OsConnectionContext : public ConnectionContext
{
public:
static Expected<std::shared_ptr<ConnectionContext>> create_shared(bool is_accepting);
OsConnectionContext(bool is_accepting) : ConnectionContext(is_accepting) {}
virtual ~OsConnectionContext() = default;
};
class OsRawConnection : public RawConnection
{
public:
static Expected<std::shared_ptr<RawConnection>> create_shared(std::shared_ptr<OsConnectionContext> context);
virtual ~OsRawConnection() = default;
virtual Expected<std::shared_ptr<RawConnection>> accept() override;
virtual hailo_status connect() 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;
};
} // namespace hrpc
#endif // _POSIX_RAW_CONNECTION_INTERNAL_HPP_

View File

@@ -1,59 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection_internal.cpp
* @brief Windows Sockets Raw Connection
**/
#include "hrpc/os/windows/raw_connection_internal.hpp"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include "hailo/hailort.h"
using namespace hrpc;
Expected<std::shared_ptr<ConnectionContext>> OsConnectionContext::create_shared(bool is_accepting)
{
(void)is_accepting;
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
Expected<std::shared_ptr<RawConnection>> OsRawConnection::create_shared(std::shared_ptr<OsConnectionContext> context)
{
(void)context;
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
Expected<std::shared_ptr<RawConnection>> OsRawConnection::accept()
{
return make_unexpected(HAILO_NOT_IMPLEMENTED);
}
hailo_status OsRawConnection::connect()
{
return HAILO_NOT_IMPLEMENTED;
}
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, std::chrono::milliseconds timeout)
{
(void)buffer;
(void)size;
(void)timeout;
return HAILO_NOT_IMPLEMENTED;
}
hailo_status OsRawConnection::close()
{
return HAILO_NOT_IMPLEMENTED;
}

View File

@@ -1,50 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection_internal.hpp
* @brief Raw Connection Header for sockets based comunication
**/
#ifndef _WINDOWS_RAW_CONNECTION_INTERNAL_HPP_
#define _WINDOWS_RAW_CONNECTION_INTERNAL_HPP_
#include "hailo/expected.hpp"
#include "hrpc/raw_connection.hpp"
#include <memory>
using namespace hailort;
namespace hrpc
{
class OsConnectionContext : public ConnectionContext
{
public:
static Expected<std::shared_ptr<ConnectionContext>> create_shared(bool is_accepting);
};
class OsRawConnection : public RawConnection
{
public:
static Expected<std::shared_ptr<RawConnection>> create_shared(std::shared_ptr<OsConnectionContext> context);
OsRawConnection() = default;
virtual ~OsRawConnection() = default;
virtual Expected<std::shared_ptr<RawConnection>> accept() override;
virtual hailo_status connect() 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*/) {}
};
} // namespace hrpc
#endif // _WINDOWS_RAW_CONNECTION_INTERNAL_HPP_

View File

@@ -1,61 +0,0 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file raw_connection.hpp
* @brief Raw Connection Header
**/
#ifndef _RAW_CONNECTION_HPP_
#define _RAW_CONNECTION_HPP_
#include "hailo/expected.hpp"
#include "vdma/pcie_session.hpp"
#include <memory>
#define DEFAULT_WRITE_TIMEOUT (std::chrono::milliseconds(10000))
#define DEFAULT_READ_TIMEOUT (std::chrono::milliseconds(HAILO_INFINITE))
using namespace hailort;
namespace hrpc
{
class ConnectionContext
{
public:
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; }
ConnectionContext(bool is_accepting) : m_is_accepting(is_accepting) {}
virtual ~ConnectionContext() = default;
protected:
bool m_is_accepting;
};
class RawConnection
{
public:
static Expected<std::shared_ptr<RawConnection>> create_shared(std::shared_ptr<ConnectionContext> context);
RawConnection() = default;
virtual ~RawConnection() = default;
virtual Expected<std::shared_ptr<RawConnection>> accept() = 0;
virtual hailo_status connect() = 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;
};
} // namespace hrpc
#endif // _RAW_CONNECTION_HPP_

View File

@@ -0,0 +1,336 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailo_session_internal.cpp
* @brief PCIE Hailo Session
**/
#include "hrpc/raw_connection_internal/pcie/hailo_session_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"
#define TRANSFER_TIMEOUT (std::chrono::seconds(10))
namespace hailort
{
Expected<std::shared_ptr<ConnectionContext>> PcieConnectionContext::create_client_shared(const std::string &device_id)
{
if (device_id.size() > 0) {
TRY(auto driver, HailoRTDriver::create_pcie(device_id));
auto ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), false);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
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);
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()
{
TRY(auto driver, HailoRTDriver::create_pcie_ep());
auto ptr = make_shared_nothrow<PcieConnectionContext>(std::move(driver), true);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
hailo_status PcieConnectionContext::wait_for_available_connection()
{
std::unique_lock<std::mutex> lock(m_mutex);
bool was_successful = m_cv.wait_for(lock, std::chrono::milliseconds(HAILO_INFINITE), [this] () -> bool {
return (m_conn_count == 0);
});
CHECK(was_successful, HAILO_TIMEOUT, "Got timeout in accept");
m_conn_count++;
return HAILO_SUCCESS;
}
void PcieConnectionContext::mark_connection_closed()
{
if (0 == m_conn_count) return; // In case number of connections is 0 - no need to mark as closed
{
std::unique_lock<std::mutex> lock(m_mutex);
m_conn_count--;
}
m_cv.notify_one();
}
Expected<std::shared_ptr<RawPcieListener>> RawPcieListener::create_shared(std::shared_ptr<PcieConnectionContext> context, uint16_t port)
{
auto ptr = make_shared_nothrow<RawPcieListener>(context, port);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
Expected<std::shared_ptr<Session>> RawPcieListener::accept()
{
auto status = m_context->wait_for_available_connection();
CHECK_SUCCESS(status);
auto new_conn = make_shared_nothrow<RawPcieSession>(m_context);
CHECK_NOT_NULL_AS_EXPECTED(new_conn, HAILO_OUT_OF_HOST_MEMORY);
TRY(auto session, PcieSession::accept(m_context->get_driver(), m_port));
status = new_conn->set_session(std::move(session));
CHECK_SUCCESS(status);
return std::dynamic_pointer_cast<Session>(new_conn);
}
RawPcieSession::~RawPcieSession()
{
close();
}
Expected<std::shared_ptr<RawPcieSession>> RawPcieSession::connect(std::shared_ptr<PcieConnectionContext> context, uint16_t port)
{
auto ptr = std::make_shared<RawPcieSession>(context);
auto status = ptr->connect(port);
CHECK_SUCCESS(status);
return ptr;
}
hailo_status RawPcieSession::connect(uint16_t port)
{
TRY(auto session, PcieSession::connect(m_context->get_driver(), port));
return set_session(std::move(session));
}
hailo_status RawPcieSession::write(const uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = write_async(buffer, size, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(m_write_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_write_cv.notify_one();
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(m_write_mutex);
CHECK(m_write_cv.wait_for(lock, timeout, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
hailo_status RawPcieSession::read(uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = read_async(buffer, size, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(m_read_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_read_cv.notify_one();
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(m_read_mutex);
CHECK(m_read_cv.wait_for(lock, timeout, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
hailo_status RawPcieSession::close()
{
if (m_session != nullptr) {
auto status = m_session->close();
CHECK_SUCCESS(status);
}
m_context->mark_connection_closed();
{
std::unique_lock<std::mutex> lock(m_ongoing_writes_mutex);
m_ongoing_writes = 0;
m_ongoing_writes_cv.notify_all();
}
{
std::unique_lock<std::mutex> lock(m_ongoing_reads_mutex);
m_ongoing_reads = 0;
m_ongoing_reads_cv.notify_all();
}
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::wait_for_write_async_ready(size_t transfer_size, std::chrono::milliseconds timeout)
{
std::unique_lock<std::mutex> lock(m_ongoing_writes_mutex);
CHECK(m_ongoing_writes_cv.wait_for(lock, timeout, [this, transfer_size] () {
return m_session->is_write_ready(transfer_size);
}), HAILO_TIMEOUT, "Timeout waiting for transfer ready");
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::write_async(const uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
if (0 == size) {
callback(HAILO_SUCCESS);
return HAILO_SUCCESS;
}
bool is_aligned = ((reinterpret_cast<uintptr_t>(buffer) % OsUtils::get_dma_able_alignment()) == 0);
if (is_aligned) {
auto status = write_async_aligned(buffer, size, std::move(callback));
CHECK_SUCCESS(status);
} else {
auto status = write_async_unaligned(buffer, size, std::move(callback));
CHECK_SUCCESS(status);
}
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::write_async_aligned(const uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
std::unique_lock<std::mutex> lock(m_ongoing_writes_mutex);
auto status = m_session->write_async(buffer, size, [this, callback] (hailo_status status) {
if (HAILO_STREAM_ABORT == status) {
callback(HAILO_COMMUNICATION_CLOSED);
return;
}
callback(status);
std::unique_lock<std::mutex> lock(m_ongoing_writes_mutex);
m_ongoing_writes--;
m_ongoing_writes_cv.notify_all();
});
if (HAILO_STREAM_ABORT == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
m_ongoing_writes++;
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::write_async_unaligned(const uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
TRY(auto aligned_buffer, Buffer::create_shared(buffer, size, BufferStorageParams::create_dma()));
auto status = write_async_aligned(aligned_buffer->data(), aligned_buffer->size(),
[callback, aligned_buffer] (hailo_status status) {
(void)aligned_buffer; // Avoid compiler optimization
callback(status);
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::wait_for_read_async_ready(size_t transfer_size, std::chrono::milliseconds timeout)
{
std::unique_lock<std::mutex> lock(m_ongoing_reads_mutex);
CHECK(m_ongoing_reads_cv.wait_for(lock, timeout, [this, transfer_size] () {
return m_session->is_read_ready(transfer_size);
}), HAILO_TIMEOUT, "Timeout waiting for transfer ready");
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::read_async(uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
if (0 == size) {
callback(HAILO_SUCCESS);
return HAILO_SUCCESS;
}
bool is_aligned = ((reinterpret_cast<uintptr_t>(buffer) % OsUtils::get_dma_able_alignment()) == 0);
if (is_aligned) {
auto status = read_async_aligned(buffer, size, std::move(callback));
if (HAILO_COMMUNICATION_CLOSED == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
} else {
auto status = read_async_unaligned(buffer, size, std::move(callback));
if (HAILO_COMMUNICATION_CLOSED == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
}
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::read_async_aligned(uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
std::unique_lock<std::mutex> lock(m_ongoing_reads_mutex);
auto status = m_session->read_async(buffer, size, [this, callback] (hailo_status status) {
if (HAILO_STREAM_ABORT == status) {
callback(HAILO_COMMUNICATION_CLOSED);
return;
}
callback(status);
std::unique_lock<std::mutex> lock(m_ongoing_reads_mutex);
m_ongoing_reads--;
m_ongoing_reads_cv.notify_all();
});
if ((HAILO_STREAM_ABORT == status) || (HAILO_STREAM_NOT_ACTIVATED == status)) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
m_ongoing_reads++;
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::read_async_unaligned(uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
TRY(auto aligned_buffer, Buffer::create_shared(size, BufferStorageParams::create_dma()));
auto status = read_async_aligned(aligned_buffer->data(), aligned_buffer->size(),
[buffer, aligned_buffer, callback] (hailo_status status) {
if (HAILO_SUCCESS == status) {
memcpy(buffer, aligned_buffer->data(), aligned_buffer->size());
}
callback(status);
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status RawPcieSession::set_session(PcieSession &&session)
{
m_session = make_shared_nothrow<PcieSession>(std::move(session));
CHECK_NOT_NULL(m_session, HAILO_OUT_OF_HOST_MEMORY);
return HAILO_SUCCESS;
}
} // namespace hailort

View File

@@ -0,0 +1,117 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailo_session_internal.hpp
* @brief Hailo Session Header for pcie based comunication
**/
#ifndef _PCIE_RAW_CONNECTION_INTERNAL_HPP_
#define _PCIE_RAW_CONNECTION_INTERNAL_HPP_
#include "hailo/expected.hpp"
#include "vdma/pcie_session.hpp"
#include "hailo/hailo_session.hpp"
#include "hrpc/connection_context.hpp"
#include <memory>
#include <condition_variable>
namespace hailort
{
class PcieConnectionContext : public ConnectionContext
{
public:
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)
: ConnectionContext(is_accepting), m_driver(std::move(driver)), m_conn_count(0) {}
virtual ~PcieConnectionContext() = default;
virtual std::shared_ptr<HailoRTDriver> get_driver() override { return m_driver; }
hailo_status wait_for_available_connection();
void mark_connection_closed();
private:
std::shared_ptr<HailoRTDriver> m_driver;
uint32_t m_conn_count;
std::mutex m_mutex;
std::condition_variable m_cv;
};
class RawPcieSession : public Session
{
public:
static Expected<std::shared_ptr<RawPcieSession>> connect(std::shared_ptr<PcieConnectionContext> context, uint16_t port);
RawPcieSession() = default;
virtual ~RawPcieSession();
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;
virtual hailo_status wait_for_write_async_ready(size_t transfer_size, std::chrono::milliseconds timeout) override;
virtual hailo_status write_async(const uint8_t *buffer, size_t size,
std::function<void(hailo_status)> &&callback) override;
virtual hailo_status wait_for_read_async_ready(size_t transfer_size, std::chrono::milliseconds timeout) override;
virtual hailo_status read_async(uint8_t *buffer, size_t size,
std::function<void(hailo_status)> &&callback) override;
explicit RawPcieSession(std::shared_ptr<PcieConnectionContext> context) : m_context(context), m_ongoing_writes(0),
m_ongoing_reads(0) {}
hailo_status set_session(PcieSession &&session);
hailo_status connect(uint16_t port);
private:
hailo_status write_async_aligned(const uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback);
hailo_status write_async_unaligned(const uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback);
hailo_status read_async_aligned(uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback);
hailo_status read_async_unaligned(uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback);
std::mutex m_read_mutex;
std::condition_variable m_read_cv;
std::mutex m_write_mutex;
std::condition_variable m_write_cv;
std::shared_ptr<PcieConnectionContext> m_context;
std::shared_ptr<PcieSession> m_session;
std::atomic_uint32_t m_ongoing_writes;
std::mutex m_ongoing_writes_mutex;
std::condition_variable m_ongoing_writes_cv;
std::atomic_uint32_t m_ongoing_reads;
std::mutex m_ongoing_reads_mutex;
std::condition_variable m_ongoing_reads_cv;
};
class RawPcieListener : public SessionListener
{
public:
static Expected<std::shared_ptr<RawPcieListener>> create_shared(std::shared_ptr<PcieConnectionContext> context, uint16_t port);
RawPcieListener() = default;
virtual ~RawPcieListener() = default;
virtual Expected<std::shared_ptr<Session>> accept() override;
explicit RawPcieListener(std::shared_ptr<PcieConnectionContext> context, uint16_t port) : SessionListener(port), m_context(context) {}
hailo_status set_session(PcieSession &&session);
private:
std::shared_ptr<PcieConnectionContext> m_context;
std::shared_ptr<PcieSession> m_session;
};
} // namespace hailort
#endif // _PCIE_RAW_CONNECTION_INTERNAL_HPP_

View File

@@ -0,0 +1,454 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailo_session_internal.cpp
* @brief Linux Sockets Hailo Session
**/
#include "hrpc/raw_connection_internal/socket/hailo_session_internal.hpp"
#include "common/logger_macros.hpp"
#include "common/utils.hpp"
#include "common/internal_env_vars.hpp"
#include "common/filesystem.hpp"
#include "hailo/hailort.h"
#include <string>
#define BACKLOG_SIZE (5)
#define USE_DEFAULT_PROTOCOL (0)
#define HRT_UNIX_SOCKET_FILE_NAME ("hailort_unix_socket")
namespace hailort
{
// Same as in pcie_session.cpp
static constexpr uint64_t MAX_ONGOING_TRANSFERS = 128;
Expected<std::shared_ptr<AsyncActionsThread>> AsyncActionsThread::create(size_t queue_size)
{
TRY(auto shutdown_event, Event::create_shared(Event::State::not_signalled));
TRY(auto write_queue, SpscQueue<AsyncAction>::create(queue_size, shutdown_event));
auto ptr = make_shared_nothrow<AsyncActionsThread>(std::move(write_queue), shutdown_event);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
AsyncActionsThread::AsyncActionsThread(SpscQueue<AsyncAction> &&queue,
EventPtr shutdown_event) : m_queue(std::move(queue)), m_shutdown_event(shutdown_event)
{
m_thread = std::thread([this] () { thread_loop(); });
}
hailo_status AsyncActionsThread::abort()
{
auto status = m_shutdown_event->signal();
if (HAILO_SUCCESS != status) {
LOGGER__CRITICAL("Failed to signal shutdown event, status = {}", status);
}
if (m_thread.joinable()) {
m_thread.join();
}
const bool IGNORE_SHUTDOWN_EVENT = true;
while (true) {
auto action = m_queue.dequeue(std::chrono::milliseconds(0), IGNORE_SHUTDOWN_EVENT);
if (HAILO_TIMEOUT == action.status()) {
break;
}
if (!action) {
status = action.status();
LOGGER__ERROR("Failed to dequeue action, status = {}", status);
continue;
}
action->on_finish_callback(action->action(true));
}
m_cv.notify_all();
return status;
}
AsyncActionsThread::~AsyncActionsThread()
{
abort();
}
hailo_status AsyncActionsThread::thread_loop()
{
while (true) {
TRY_WITH_ACCEPTABLE_STATUS(HAILO_SHUTDOWN_EVENT_SIGNALED, auto action,
m_queue.dequeue(std::chrono::milliseconds(HAILO_INFINITE)));
m_cv.notify_one();
action.on_finish_callback(action.action(false));
}
return HAILO_SUCCESS;
}
hailo_status AsyncActionsThread::wait_for_enqueue_ready(std::chrono::milliseconds timeout)
{
std::unique_lock<std::mutex> lock(m_mutex);
CHECK(m_cv.wait_for(lock, timeout, [this] () {
return !m_queue.is_queue_full();
}), HAILO_TIMEOUT, "Timeout waiting for enqueue ready");
return HAILO_SUCCESS;
}
hailo_status AsyncActionsThread::enqueue_nonblocking(AsyncAction action)
{
auto status = m_queue.enqueue(action, std::chrono::milliseconds(0));
CHECK(status != HAILO_TIMEOUT, HAILO_QUEUE_IS_FULL); // Should call wait_for_enqueue_ready() before enqueue_nonblocking()
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
Expected<std::shared_ptr<ConnectionContext>> OsConnectionContext::create_shared(bool is_accepting)
{
auto ptr = make_shared_nothrow<OsConnectionContext>(is_accepting);
CHECK_NOT_NULL(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<ConnectionContext>(ptr);
}
static Expected<Socket> create_inet_socket()
{
TRY(auto socket, Socket::create(AF_INET, SOCK_STREAM, USE_DEFAULT_PROTOCOL));
CHECK_SUCCESS(socket.allow_reuse_address());
auto interface_name = get_env_variable(HAILO_SOCKET_BIND_TO_INTERFACE_ENV_VAR);
if (interface_name) {
CHECK_SUCCESS(socket.bind_to_device(interface_name.value()));
}
return socket;
}
Expected<std::shared_ptr<Session>> OsListener::accept()
{
TRY(auto client_socket, m_socket.accept());
TRY(auto write_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
TRY(auto read_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
std::shared_ptr<OsSession> ptr = make_shared_nothrow<OsSession>(std::move(client_socket), m_context,
write_actions_thread, read_actions_thread, m_port);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return std::dynamic_pointer_cast<Session>(ptr);
}
Expected<std::shared_ptr<SessionListener>> OsListener::create_shared(std::shared_ptr<OsConnectionContext> context, uint16_t port)
{
std::shared_ptr<SessionListener> ptr;
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, port));
} else {
TRY(auto ip_port_pair, OsSession::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)));
}
return ptr;
}
Expected<std::shared_ptr<OsListener>> OsListener::create_by_addr_server(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port)
{
TRY(auto socket, create_inet_socket());
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 status = socket.pton(AF_INET, ip.c_str(), &server_addr.sin_addr);
CHECK_SUCCESS_AS_EXPECTED(status,
"Failed to run 'inet_pton'. make sure 'HAILO_SOCKET_COM_ADDR_SERVER' is set correctly (ip:port)");
status = socket.socket_bind((struct sockaddr*)&server_addr, addr_len);
CHECK_SUCCESS_AS_EXPECTED(status);
status = socket.listen(BACKLOG_SIZE);
CHECK_SUCCESS_AS_EXPECTED(status);
TRY(auto write_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
TRY(auto read_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
auto res = make_shared_nothrow<OsListener>(std::move(socket), context, write_actions_thread, read_actions_thread, port);
CHECK_NOT_NULL_AS_EXPECTED(res, HAILO_OUT_OF_HOST_MEMORY);
return res;
}
Expected<std::shared_ptr<OsListener>> OsListener::create_localhost_server(std::shared_ptr<OsConnectionContext> context, uint16_t port)
{
TRY(auto socket, Socket::create(AF_UNIX, SOCK_STREAM, USE_DEFAULT_PROTOCOL));
TRY(sockaddr_un server_addr, OsSession::get_localhost_server_addr());
std::remove(server_addr.sun_path);
auto status = socket.socket_bind((struct sockaddr*)&server_addr, sizeof(server_addr));
CHECK_SUCCESS_AS_EXPECTED(status);
status = socket.listen(BACKLOG_SIZE);
CHECK_SUCCESS_AS_EXPECTED(status);
TRY(auto write_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
TRY(auto read_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
auto ptr = make_shared_nothrow<OsListener>(std::move(socket), context, write_actions_thread, read_actions_thread, port);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
OsSession::~OsSession()
{
close();
}
Expected<std::pair<std::string, uint16_t>> OsSession::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<OsSession>> OsSession::connect(std::shared_ptr<OsConnectionContext> context, uint16_t port)
{
(void)port;
// Creates one of the following 2 types of sessions:
// Unix Socket client - for local communication
// TCP client - for remote communication - using ip and port
std::shared_ptr<OsSession> ptr;
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, port));
} 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)));
}
auto status = ptr->connect();
CHECK_SUCCESS(status);
return ptr;
}
Expected<std::shared_ptr<OsSession>> OsSession::create_localhost_client(std::shared_ptr<OsConnectionContext> context, uint16_t port)
{
TRY(auto socket, Socket::create(AF_UNIX, SOCK_STREAM, USE_DEFAULT_PROTOCOL));
TRY(auto write_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
TRY(auto read_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
auto ptr = make_shared_nothrow<OsSession>(std::move(socket), context, write_actions_thread, read_actions_thread, port);
CHECK_NOT_NULL_AS_EXPECTED(ptr, HAILO_OUT_OF_HOST_MEMORY);
return ptr;
}
Expected<std::shared_ptr<OsSession>> OsSession::create_by_addr_client(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port)
{
TRY(auto socket, create_inet_socket());
sockaddr_in server_addr = {};
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
auto status = socket.pton(AF_INET, ip.c_str(), &server_addr.sin_addr);
CHECK_SUCCESS_AS_EXPECTED(status,
"Failed to run 'inet_pton'. make sure 'HAILO_SOCKET_COM_ADDR_CLIENT' is set correctly (ip:port)");
TRY(auto write_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
TRY(auto read_actions_thread, AsyncActionsThread::create(MAX_ONGOING_TRANSFERS));
auto res = make_shared_nothrow<OsSession>(std::move(socket), context, write_actions_thread, read_actions_thread, port);
CHECK_NOT_NULL_AS_EXPECTED(res, HAILO_OUT_OF_HOST_MEMORY);
return res;
}
hailo_status OsSession::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 OsSession::connect_localhost()
{
TRY(sockaddr_un server_addr, get_localhost_server_addr());
auto status = m_socket.connect((struct sockaddr*)&server_addr, sizeof(server_addr));
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
Expected<sockaddr_un> OsSession::get_localhost_server_addr()
{
TRY(auto tmp_path, Filesystem::get_temp_path());
std::string addr = tmp_path + HRT_UNIX_SOCKET_FILE_NAME;
struct sockaddr_un server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strncpy(server_addr.sun_path, addr.c_str(), addr.size());
return server_addr;
}
hailo_status OsSession::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 status = m_socket.pton(AF_INET, ip.c_str(), &server_addr.sin_addr);
CHECK_SUCCESS_AS_EXPECTED(status,
"Failed to run 'inet_pton'. make sure 'HAILO_SOCKET_COM_ADDR_XX' is set correctly (ip:port)");
status = m_socket.connect((struct sockaddr*)&server_addr, addr_len);
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status OsSession::write(const uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = wait_for_write_async_ready(size, timeout);
CHECK_SUCCESS(status);
status = write_async(buffer, size, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(m_write_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_write_cv.notify_one();
});
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(m_write_mutex);
CHECK(m_write_cv.wait_for(lock, timeout, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
hailo_status OsSession::read(uint8_t *buffer, size_t size, std::chrono::milliseconds timeout)
{
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = wait_for_read_async_ready(size, timeout);
CHECK_SUCCESS(status);
status = read_async(buffer, size, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(m_read_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_read_cv.notify_one();
});
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(m_read_mutex);
CHECK(m_read_cv.wait_for(lock, timeout, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
hailo_status OsSession::close()
{
if (INVALID_SOCKET == m_socket.get_fd()) { // In case of double close
return HAILO_SUCCESS;
}
auto status = m_socket.abort();
CHECK_SUCCESS(status);
status = m_write_actions_thread->abort();
CHECK_SUCCESS(status);
status = m_read_actions_thread->abort();
CHECK_SUCCESS(status);
status = m_socket.close_socket_fd();
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status OsSession::wait_for_write_async_ready(size_t /*transfer_size*/, std::chrono::milliseconds timeout)
{
return m_write_actions_thread->wait_for_enqueue_ready(timeout);
}
hailo_status OsSession::write_async(const uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
auto status = m_write_actions_thread->enqueue_nonblocking({[this, buffer, size] (bool is_aborted) -> hailo_status {
if (is_aborted) {
return HAILO_STREAM_ABORTED_BY_USER;
}
auto status = m_socket.sendall(buffer, size, MSG_NOSIGNAL);
CHECK(status == HAILO_SUCCESS || status == HAILO_COMMUNICATION_CLOSED, status);
return status;
}, callback});
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status OsSession::wait_for_read_async_ready(size_t /*transfer_size*/, std::chrono::milliseconds timeout)
{
return m_read_actions_thread->wait_for_enqueue_ready(timeout);
}
hailo_status OsSession::read_async(uint8_t *buffer, size_t size, std::function<void(hailo_status)> &&callback)
{
auto status = m_read_actions_thread->enqueue_nonblocking({[this, buffer, size] (bool is_aborted) -> hailo_status {
if (is_aborted) {
return HAILO_STREAM_ABORTED_BY_USER;
}
auto status = m_socket.recvall(buffer, size);
CHECK(status == HAILO_SUCCESS || status == HAILO_COMMUNICATION_CLOSED, status);
return status;
}, callback});
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
} // namespace hailort

View File

@@ -0,0 +1,141 @@
/**
* Copyright (c) 2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the MIT license (https://opensource.org/licenses/MIT)
**/
/**
* @file hailo_session_internal.hpp
* @brief Hailo Session Header for sockets based comunication
**/
#ifndef _POSIX_RAW_CONNECTION_INTERNAL_HPP_
#define _POSIX_RAW_CONNECTION_INTERNAL_HPP_
#include "hailo/expected.hpp"
#include "hailo/hailo_session.hpp"
#include "common/thread_safe_queue.hpp"
#include "common/socket.hpp"
#include "hrpc/connection_context.hpp"
#include <memory>
namespace hailort
{
struct AsyncAction
{
std::function<hailo_status(bool)> action;
std::function<void(hailo_status)> on_finish_callback;
};
class AsyncActionsThread
{
public:
static Expected<std::shared_ptr<AsyncActionsThread>> create(size_t queue_size);
AsyncActionsThread(SpscQueue<AsyncAction> &&queue, EventPtr shutdown_event);
virtual ~AsyncActionsThread();
hailo_status wait_for_enqueue_ready(std::chrono::milliseconds timeout);
hailo_status enqueue_nonblocking(AsyncAction action);
hailo_status abort();
private:
hailo_status thread_loop();
std::mutex m_mutex;
std::condition_variable m_cv;
SpscQueue<AsyncAction> m_queue;
EventPtr m_shutdown_event;
std::thread m_thread;
};
class OsConnectionContext : public ConnectionContext
{
public:
static Expected<std::shared_ptr<ConnectionContext>> create_shared(bool is_accepting);
OsConnectionContext(bool is_accepting) : ConnectionContext(is_accepting) {}
virtual ~OsConnectionContext() = default;
};
class OsListener : public SessionListener
{
public:
static Expected<std::shared_ptr<SessionListener>> create_shared(std::shared_ptr<OsConnectionContext> context, uint16_t port);
virtual ~OsListener() = default;
virtual Expected<std::shared_ptr<Session>> accept() override;
OsListener(Socket &&socket, std::shared_ptr<OsConnectionContext> context,
std::shared_ptr<AsyncActionsThread> write_actions_thread,
std::shared_ptr<AsyncActionsThread> read_actions_thread, uint16_t port) :
SessionListener(port), m_socket(std::move(socket)),
m_context(context), m_write_actions_thread(write_actions_thread),
m_read_actions_thread(read_actions_thread) {}
private:
static Expected<std::shared_ptr<OsListener>> create_by_addr_server(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port);
static Expected<std::shared_ptr<OsListener>> create_localhost_server(std::shared_ptr<OsConnectionContext> context, uint16_t port);
Socket m_socket;
std::shared_ptr<OsConnectionContext> m_context;
std::shared_ptr<AsyncActionsThread> m_write_actions_thread;
std::shared_ptr<AsyncActionsThread> m_read_actions_thread;
};
class OsSession : public Session
{
public:
static Expected<std::shared_ptr<OsSession>> connect(std::shared_ptr<OsConnectionContext> context, uint16_t port);
virtual ~OsSession();
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;
virtual hailo_status wait_for_write_async_ready(size_t transfer_size, std::chrono::milliseconds timeout) override;
virtual hailo_status write_async(const uint8_t *buffer, size_t size,
std::function<void(hailo_status)> &&callback) override;
virtual hailo_status wait_for_read_async_ready(size_t transfer_size, std::chrono::milliseconds timeout) override;
virtual hailo_status read_async(uint8_t *buffer, size_t size,
std::function<void(hailo_status)> &&callback) override;
OsSession(Socket &&socket, std::shared_ptr<OsConnectionContext> context,
std::shared_ptr<AsyncActionsThread> write_actions_thread,
std::shared_ptr<AsyncActionsThread> read_actions_thread, uint16_t port) :
Session(port), m_socket(std::move(socket)), m_context(context),
m_write_actions_thread(write_actions_thread),
m_read_actions_thread(read_actions_thread) {}
static Expected<sockaddr_un> get_localhost_server_addr();
static Expected<std::pair<std::string, uint16_t>> parse_ip_port(const std::string &ip_port);
hailo_status connect();
private:
static Expected<std::shared_ptr<OsSession>> create_by_addr_client(std::shared_ptr<OsConnectionContext> context,
const std::string &ip, uint16_t port);
static Expected<std::shared_ptr<OsSession>> create_localhost_client(std::shared_ptr<OsConnectionContext> context, uint16_t port);
hailo_status connect_by_addr(const std::string &ip, uint16_t port);
hailo_status connect_localhost();
std::mutex m_read_mutex;
std::condition_variable m_read_cv;
std::mutex m_write_mutex;
std::condition_variable m_write_cv;
Socket m_socket;
std::shared_ptr<OsConnectionContext> m_context;
std::shared_ptr<AsyncActionsThread> m_write_actions_thread;
std::shared_ptr<AsyncActionsThread> m_read_actions_thread;
};
} // namespace hailort
#endif // _POSIX_RAW_CONNECTION_INTERNAL_HPP_

View File

@@ -8,61 +8,221 @@
**/
#include "rpc_connection.hpp"
#include "vdma/pcie_session.hpp"
namespace hrpc
namespace hailort
{
hailo_status RpcConnection::write_message(const rpc_message_header_t &header, const MemoryView &buffer) {
auto header_with_magic = header;
header_with_magic.magic = RPC_MESSAGE_MAGIC;
auto status = m_raw->write(reinterpret_cast<const uint8_t*>(&header_with_magic), sizeof(header_with_magic));
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
}
CHECK_SUCCESS(status);
#define TRANSFER_TIMEOUT std::chrono::seconds(10)
status = m_raw->write(buffer.data(), header.size);
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
}
CHECK_SUCCESS(status);
Expected<RpcConnection> RpcConnection::create(std::shared_ptr<Session> raw)
{
TRY(auto shutdown_event, Event::create_shared(Event::State::not_signalled));
TRY(auto write_rpc_headers, DmaAbleBufferPool::create_shared(sizeof(rpc_message_header_t),
PcieSession::MAX_ONGOING_TRANSFERS, shutdown_event));
TRY(auto read_rpc_headers, DmaAbleBufferPool::create_shared(sizeof(rpc_message_header_t),
PcieSession::MAX_ONGOING_TRANSFERS, shutdown_event));
return HAILO_SUCCESS;
auto read_mutex = make_shared_nothrow<std::mutex>();
CHECK_NOT_NULL(read_mutex, HAILO_OUT_OF_HOST_MEMORY);
auto write_mutex = make_shared_nothrow<std::mutex>();
CHECK_NOT_NULL(write_mutex, HAILO_OUT_OF_HOST_MEMORY);
auto read_cv = make_shared_nothrow<std::condition_variable>();
CHECK_NOT_NULL(read_cv, HAILO_OUT_OF_HOST_MEMORY);
auto write_cv = make_shared_nothrow<std::condition_variable>();
CHECK_NOT_NULL(write_cv, HAILO_OUT_OF_HOST_MEMORY);
return RpcConnection(raw, write_rpc_headers, read_rpc_headers, shutdown_event, read_mutex, write_mutex, read_cv, write_cv);
}
Expected<Buffer> RpcConnection::read_message(rpc_message_header_t &header) {
auto status = m_raw->read(reinterpret_cast<uint8_t*>(&header), sizeof(header));
hailo_status RpcConnection::write_message(const rpc_message_header_t &header, const MemoryView &buffer)
{
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = wait_for_write_message_async_ready(buffer.size(), TRANSFER_TIMEOUT);
CHECK_SUCCESS(status);
status = write_message_async(header, buffer, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(*m_write_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_write_cv->notify_one();
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(*m_write_mutex);
CHECK(m_write_cv->wait_for(lock, TRANSFER_TIMEOUT, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
Expected<rpc_message_t> RpcConnection::read_message()
{
auto expected_dma_header_ptr = m_read_rpc_headers->acquire_buffer();
if (HAILO_SHUTDOWN_EVENT_SIGNALED == expected_dma_header_ptr.status()) {
return make_unexpected(HAILO_COMMUNICATION_CLOSED);
}
CHECK_EXPECTED(expected_dma_header_ptr);
auto dma_header_ptr = expected_dma_header_ptr.release();
rpc_message_header_t &dma_header = *reinterpret_cast<rpc_message_header_t*>(dma_header_ptr->data());
auto status = m_session->read(reinterpret_cast<uint8_t*>(&dma_header), sizeof(dma_header));
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
}
CHECK_SUCCESS_AS_EXPECTED(status);
CHECK_AS_EXPECTED(RPC_MESSAGE_MAGIC == header.magic, HAILO_INTERNAL_FAILURE, "Invalid magic! {} != {}",
header.magic, RPC_MESSAGE_MAGIC);
CHECK_SUCCESS(status);
CHECK(RPC_MESSAGE_MAGIC == dma_header.magic, HAILO_INTERNAL_FAILURE, "Invalid magic! {} != {}",
dma_header.magic, RPC_MESSAGE_MAGIC);
TRY(auto buffer, Buffer::create(header.size, BufferStorageParams::create_dma()));
status = m_raw->read(buffer.data(), header.size);
TRY(auto buffer, Buffer::create(dma_header.size, BufferStorageParams::create_dma()));
status = m_session->read(buffer.data(), buffer.size());
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
}
CHECK_SUCCESS_AS_EXPECTED(status);
CHECK_SUCCESS(status);
return buffer;
rpc_message_t rpc_message = {};
rpc_message.header = dma_header;
rpc_message.buffer = std::move(buffer);
status = m_read_rpc_headers->return_to_pool(dma_header_ptr);
CHECK_SUCCESS(status);
return rpc_message;
}
hailo_status RpcConnection::write_buffer(const MemoryView &buffer)
{
auto status = m_raw->write(buffer.data(), buffer.size());
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = wait_for_write_buffer_async_ready(buffer.size(), TRANSFER_TIMEOUT);
CHECK_SUCCESS(status);
status = write_buffer_async(buffer, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(*m_write_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_write_cv->notify_one();
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
return status;
}
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(*m_write_mutex);
CHECK(m_write_cv->wait_for(lock, TRANSFER_TIMEOUT, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
hailo_status RpcConnection::read_buffer(MemoryView buffer)
{
hailo_status transfer_status = HAILO_UNINITIALIZED;
auto status = wait_for_read_buffer_async_ready(buffer.size(), TRANSFER_TIMEOUT);
CHECK_SUCCESS(status);
status = read_buffer_async(buffer, [&] (hailo_status status) {
{
std::unique_lock<std::mutex> lock(*m_read_mutex);
assert(status != HAILO_UNINITIALIZED);
transfer_status = status;
}
m_read_cv->notify_one();
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(*m_read_mutex);
CHECK(m_read_cv->wait_for(lock, TRANSFER_TIMEOUT, [&] { return transfer_status != HAILO_UNINITIALIZED; }),
HAILO_TIMEOUT, "Timeout waiting for transfer completion");
return transfer_status;
}
hailo_status RpcConnection::wait_for_write_message_async_ready(size_t buffer_size, std::chrono::milliseconds timeout)
{
return m_session->wait_for_write_async_ready(sizeof(rpc_message_header_t) + buffer_size, timeout);
}
hailo_status RpcConnection::write_message_async(const rpc_message_header_t &header, const MemoryView &buffer,
std::function<void(hailo_status)> &&callback)
{
auto expected_dma_header_ptr = m_write_rpc_headers->acquire_buffer();
if (HAILO_SHUTDOWN_EVENT_SIGNALED == expected_dma_header_ptr.status()) {
return HAILO_COMMUNICATION_CLOSED;
}
CHECK_EXPECTED(expected_dma_header_ptr);
auto dma_header_ptr = expected_dma_header_ptr.release();
rpc_message_header_t &dma_header = *reinterpret_cast<rpc_message_header_t*>(dma_header_ptr->data());
memcpy(&dma_header, &header, sizeof(header));
dma_header.magic = RPC_MESSAGE_MAGIC;
auto status = m_session->write_async(reinterpret_cast<const uint8_t*>(&dma_header), sizeof(dma_header),
[write_rpc_headers = m_write_rpc_headers, dma_header_ptr] (hailo_status status) {
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to write header, status = {}", status);
}
status = write_rpc_headers->return_to_pool(dma_header_ptr);
if (HAILO_SUCCESS != status) {
LOGGER__CRITICAL("Could not return buffer to pool! status = {}", status);
}
});
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
status = m_session->write_async(buffer.data(), dma_header.size, std::move(callback));
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status RpcConnection::read_buffer(MemoryView buffer)
hailo_status RpcConnection::wait_for_write_buffer_async_ready(size_t buffer_size, std::chrono::milliseconds timeout)
{
auto status = m_raw->read(buffer.data(), buffer.size());
return m_session->wait_for_write_async_ready(buffer_size, timeout);
}
hailo_status RpcConnection::write_buffer_async(const MemoryView &buffer, std::function<void(hailo_status)> &&callback)
{
auto status = m_session->write_async(buffer.data(), buffer.size(), std::move(callback));
if (HAILO_COMMUNICATION_CLOSED == status) {
return status;
}
CHECK_SUCCESS(status);
return HAILO_SUCCESS;
}
hailo_status RpcConnection::wait_for_read_buffer_async_ready(size_t buffer_size, std::chrono::milliseconds timeout)
{
return m_session->wait_for_read_async_ready(buffer_size, timeout);
}
hailo_status RpcConnection::read_buffer_async(MemoryView buffer, std::function<void(hailo_status)> &&callback)
{
auto status = m_session->read_async(buffer.data(), buffer.size(), std::move(callback));
if (HAILO_COMMUNICATION_CLOSED == status) {
return make_unexpected(status);
}
@@ -73,10 +233,22 @@ hailo_status RpcConnection::read_buffer(MemoryView buffer)
hailo_status RpcConnection::close()
{
if (m_raw) {
return m_raw->close();
hailo_status status = HAILO_UNINITIALIZED;
if (m_session != nullptr) {
status = m_session->close();
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to close session, status = {}", status);
}
return HAILO_SUCCESS;
}
if (m_shutdown_event != nullptr) {
status = m_shutdown_event->signal();
if (HAILO_SUCCESS != status) {
LOGGER__CRITICAL("Failed to signal shutdown event, status = {}", status);
}
}
return status;
}
} // namespace hrpc
} // namespace hailort

View File

@@ -10,17 +10,29 @@
#ifndef _RPC_CONNECTION_HPP_
#define _RPC_CONNECTION_HPP_
#include "raw_connection.hpp"
#include "hailo/hailo_session.hpp"
#include "hailo/buffer.hpp"
#include "common/utils.hpp"
#include "common/internal_env_vars.hpp"
#include "common/buffer_pool.hpp"
#define RPC_MESSAGE_MAGIC (0x8A554432)
#define DEFAULT_PCIE_PORT (12133)
namespace hrpc
namespace hailort
{
// TODO: HRT-15413 - Remove Env var usage. Use the API to choose port, use defaults ports for each server.
inline 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;
}
#pragma pack(push, 1)
struct rpc_message_header_t
{
@@ -31,24 +43,52 @@ struct rpc_message_header_t
};
#pragma pack(pop)
struct rpc_message_t
{
rpc_message_header_t header;
Buffer buffer;
};
class RpcConnection
{
public:
static Expected<RpcConnection> create(std::shared_ptr<Session> raw);
RpcConnection() = default;
explicit RpcConnection(std::shared_ptr<RawConnection> raw) : m_raw(raw) {}
explicit RpcConnection(std::shared_ptr<Session> raw, std::shared_ptr<DmaAbleBufferPool> write_rpc_headers,
std::shared_ptr<DmaAbleBufferPool> read_rpc_headers, EventPtr shutdown_event, std::shared_ptr<std::mutex> read_mutex,
std::shared_ptr<std::mutex> write_mutex, std::shared_ptr<std::condition_variable> read_cv, std::shared_ptr<std::condition_variable> write_cv) :
m_session(raw), m_write_rpc_headers(write_rpc_headers), m_read_rpc_headers(read_rpc_headers), m_shutdown_event(shutdown_event),
m_read_mutex(read_mutex), m_write_mutex(write_mutex), m_read_cv(read_cv), m_write_cv(write_cv) {}
hailo_status write_message(const rpc_message_header_t &header, const MemoryView &buffer);
Expected<Buffer> read_message(rpc_message_header_t &header);
Expected<rpc_message_t> read_message();
hailo_status write_buffer(const MemoryView &buffer);
hailo_status read_buffer(MemoryView buffer);
hailo_status wait_for_write_message_async_ready(size_t buffer_size, std::chrono::milliseconds timeout);
hailo_status write_message_async(const rpc_message_header_t &header, const MemoryView &buffer,
std::function<void(hailo_status)> &&callback);
hailo_status wait_for_write_buffer_async_ready(size_t buffer_size, std::chrono::milliseconds timeout);
hailo_status write_buffer_async(const MemoryView &buffer, std::function<void(hailo_status)> &&callback);
hailo_status wait_for_read_buffer_async_ready(size_t buffer_size, std::chrono::milliseconds timeout);
hailo_status read_buffer_async(MemoryView buffer, std::function<void(hailo_status)> &&callback);
hailo_status close();
private:
std::shared_ptr<RawConnection> m_raw;
std::shared_ptr<Session> m_session;
DmaAbleBufferPoolPtr m_write_rpc_headers;
DmaAbleBufferPoolPtr m_read_rpc_headers;
EventPtr m_shutdown_event;
std::shared_ptr<std::mutex> m_read_mutex;
std::shared_ptr<std::mutex> m_write_mutex;
std::shared_ptr<std::condition_variable> m_read_cv;
std::shared_ptr<std::condition_variable> m_write_cv;
};
} // namespace hrpc
} // namespace hailort
#endif // _RPC_CONNECTION_HPP_

View File

@@ -9,16 +9,16 @@
#include "server.hpp"
namespace hrpc
namespace hailort
{
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,
rpc_object_handle_t callback_owner_handle, std::function<hailo_status(RpcConnection)> write_buffers_callback)
rpc_object_handle_t callback_owner_handle, std::function<hailo_status(RpcConnection)> additional_writes_lambda)
{
return m_server.trigger_callback(callback_id, callback_status, callback_owner_handle, m_connection, write_buffers_callback);
return m_server.trigger_callback(callback_id, callback_status, callback_owner_handle, m_connection, additional_writes_lambda);
}
RpcConnection &ServerContext::connection()
@@ -43,7 +43,7 @@ Expected<Buffer> Dispatcher::call_action(HailoRpcActionID action_id, const Memor
hailo_status Server::serve()
{
TRY(auto server_connection, RawConnection::create_shared(m_connection_context));
TRY(auto server_connection, SessionListener::create_shared(m_connection_context, get_pcie_port()));
while (true) {
TRY(auto client_connection, create_client_connection(server_connection));
auto th = std::thread([this, client_connection]() { serve_client(client_connection); });
@@ -57,10 +57,11 @@ void Server::set_dispatcher(Dispatcher dispatcher)
m_dispatcher = dispatcher;
}
Expected<RpcConnection> Server::create_client_connection(std::shared_ptr<hrpc::RawConnection> server_connection)
Expected<RpcConnection> Server::create_client_connection(std::shared_ptr<SessionListener> server_connection)
{
TRY(auto conn, server_connection->accept());
return RpcConnection(conn);
TRY(auto rpc_conn, RpcConnection::create(conn));
return rpc_conn;
}
hailo_status Server::serve_client(RpcConnection client_connection)
@@ -68,21 +69,33 @@ hailo_status Server::serve_client(RpcConnection client_connection)
auto server_context = make_shared_nothrow<ServerContext>(*this, client_connection);
CHECK_NOT_NULL(server_context, HAILO_OUT_OF_HOST_MEMORY);
while (true) {
rpc_message_header_t header;
auto request = client_connection.read_message(header);
auto request = client_connection.read_message();
if (HAILO_COMMUNICATION_CLOSED == request.status()) {
cleanup_client_resources(client_connection);
break; // Client EP is disconnected, exit this loop
}
CHECK_EXPECTED_AS_STATUS(request);
assert(header.action_id < static_cast<uint32_t>(HailoRpcActionID::MAX_VALUE));
TRY(auto reply, m_dispatcher.call_action(static_cast<HailoRpcActionID>(header.action_id), MemoryView(*request), server_context));
assert(request->header.action_id < static_cast<uint32_t>(HailoRpcActionID::MAX_VALUE));
TRY(auto reply, m_dispatcher.call_action(static_cast<HailoRpcActionID>(request->header.action_id),
MemoryView(request->buffer), server_context));
request->header.size = static_cast<uint32_t>(reply.size());
auto status = client_connection.wait_for_write_message_async_ready(reply.size(), SERVER_TIMEOUT);
CHECK_SUCCESS(status);
{
std::unique_lock<std::mutex> lock(m_write_mutex);
header.size = static_cast<uint32_t>(reply.size());
auto reply_memview = MemoryView(reply);
auto reply_ptr = make_shared_nothrow<Buffer>(std::move(reply));
CHECK_NOT_NULL(reply_ptr, HAILO_OUT_OF_HOST_MEMORY);
auto status = client_connection.write_message(header, MemoryView(reply));
status = client_connection.write_message_async(request->header, reply_memview,
[reply_ptr] (hailo_status status) {
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to send reply, status = {}", status);
}
});
if ((HAILO_COMMUNICATION_CLOSED == status) || (HAILO_FILE_OPERATION_FAILURE == status)) {
lock.unlock(); // We need to acquire this lock when releasing the client resources (trigger cb)
cleanup_client_resources(client_connection);
@@ -96,29 +109,39 @@ hailo_status Server::serve_client(RpcConnection client_connection)
}
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)
RpcConnection connection, std::function<hailo_status(RpcConnection)> additional_writes_lambda)
{
// 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;
header.action_id = static_cast<uint32_t>(HailoRpcActionID::CALLBACK_CALLED);
header.message_id = callback_id;
header.size = static_cast<uint32_t>(reply.size());
auto status = connection.write_message(header, MemoryView(reply));
auto reply_ptr = make_shared_nothrow<Buffer>(std::move(reply));
CHECK_NOT_NULL(reply_ptr, HAILO_OUT_OF_HOST_MEMORY);
auto status = connection.wait_for_write_message_async_ready(reply_ptr->size(), SERVER_TIMEOUT);
CHECK_SUCCESS(status);
std::unique_lock<std::mutex> lock(m_write_mutex);
status = connection.write_message_async(header, MemoryView(*reply_ptr),
[reply_ptr] (hailo_status status) {
if (HAILO_SUCCESS != status) {
LOGGER__ERROR("Failed to send callback called reply, status = {}", status);
}
});
if ((HAILO_COMMUNICATION_CLOSED == status) || (HAILO_FILE_OPERATION_FAILURE == status)) {
return status;
}
CHECK_SUCCESS(status);
if (write_buffers_callback) {
status = write_buffers_callback(connection);
if (additional_writes_lambda) {
status = additional_writes_lambda(connection);
CHECK_SUCCESS(status);
}
return HAILO_SUCCESS;
}
} // namespace hrpc
} // namespace hailort

View File

@@ -17,8 +17,9 @@
#include "hailort_service/service_resource_manager.hpp"
#include "hrpc_protocol/serializer.hpp"
constexpr auto SERVER_TIMEOUT = std::chrono::seconds(10);
namespace hrpc
namespace hailort
{
class Server;
@@ -27,7 +28,7 @@ class ServerContext
public:
ServerContext(Server &server, RpcConnection connection);
hailo_status 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 = nullptr);
rpc_object_handle_t callback_owner_handle, std::function<hailo_status(RpcConnection)> additional_writes_lambda = nullptr);
RpcConnection &connection();
private:
@@ -56,23 +57,25 @@ public:
virtual ~Server() = default;
hailo_status serve();
void set_dispatcher(Dispatcher dispatcher);
friend class ServerContext;
protected:
std::shared_ptr<ConnectionContext> m_connection_context;
private:
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, hailo_status callback_status, rpc_object_handle_t callback_owner_handle,
RpcConnection connection, std::function<hailo_status(RpcConnection)> write_buffers_callback = nullptr);
RpcConnection connection, std::function<hailo_status(RpcConnection)> additional_writes_lambda = nullptr);
std::shared_ptr<ConnectionContext> m_connection_context;
private:
Expected<RpcConnection> create_client_connection(std::shared_ptr<SessionListener> server_connection);
hailo_status serve_client(RpcConnection client_connection);
virtual hailo_status cleanup_client_resources(RpcConnection client_connection) = 0;
Dispatcher m_dispatcher;
std::mutex m_write_mutex;
};
} // namespace hrpc
} // namespace hailort
#endif // _SERVER_HPP_

View File

@@ -25,6 +25,12 @@ message RpcRequest {
Device_Destroy_Request destroy_device_request = 16;
Device_Identify_Request identify_device_request = 17;
Device_ExtendedInfo_Request extended_device_info_request = 18;
Device_GetChipTemperature_Request get_chip_temperature_request = 19;
Device_PowerMeasurement_Request power_measurement_request = 20;
Device_SetPowerMeasurement_Request set_power_measurement_request = 21;
Device_StartPowerMeasurement_Request start_power_measurement_request = 22;
Device_GetPowerMeasurement_Request get_power_measurement_request = 23;
Device_StopPowerMeasurement_Request stop_power_measurement_request = 24;
}
}
@@ -51,9 +57,15 @@ message RpcReply {
Device_Destroy_Reply destroy_device_reply = 16;
Device_Identify_Reply identify_device_reply = 17;
Device_ExtendedInfo_Reply extended_device_info_reply = 18;
Device_GetChipTemperature_Reply get_chip_temperature_reply = 19;
Device_PowerMeasurement_Reply power_measurement_reply = 20;
Device_SetPowerMeasurement_Reply set_power_measurement_reply = 21;
Device_StartPowerMeasurement_Reply start_power_measurement_reply = 22;
Device_GetPowerMeasurement_Reply get_power_measurement_reply = 23;
Device_StopPowerMeasurement_Reply stop_power_measurement_reply = 24;
// Here comes replies that have no matching requests
CallbackCalled_Reply callback_called_reply = 19;
CallbackCalled_Reply callback_called_reply = 100;
}
}
@@ -115,6 +127,7 @@ message InferStreamParamsProto {
float nms_iou_threshold = 5;
uint32 nms_max_proposals_per_class = 6;
uint32 nms_max_accumulated_mask_size = 7;
uint32 nms_max_proposals_total = 8;
};
message InferModel_CreateConfiguredInferModel_Request {
@@ -252,7 +265,7 @@ enum DeviceArchitectureProto {
HAILO8 = 1;
HAILO8L = 2;
HAILO15H = 3;
PLUTO = 4;
HAILO15L = 4;
HAILO15M = 5;
HAILO10H = 6;
}
@@ -305,3 +318,71 @@ message Device_ExtendedInfo_Reply {
repeated uint32 unit_level_tracking_id = 8;
repeated uint32 soc_pm_values = 9;
}
message Device_GetChipTemperature_Request {
HailoObjectHandle device_handle = 1;
}
message Device_GetChipTemperature_Reply {
uint32 status = 1;
float ts0_temperature = 2;
float ts1_temperature = 3;
uint32 sample_count = 4;
}
message Device_PowerMeasurement_Request {
HailoObjectHandle device_handle = 1;
uint32 hailo_dvm_options = 2; /* corresponds to hailo_dvm_options_t */
uint32 hailo_power_measurement_type = 3; /* corresponds to hailo_power_measurement_type_t */
}
message Device_PowerMeasurement_Reply {
uint32 status = 1;
float power = 2;
}
message Device_SetPowerMeasurement_Request {
HailoObjectHandle device_handle = 1;
uint32 hailo_dvm_options = 2; /* corresponds to hailo_dvm_options_t */
uint32 hailo_power_measurement_type = 3; /* corresponds to hailo_power_measurement_type_t */
}
message Device_SetPowerMeasurement_Reply {
uint32 status = 1;
}
message Device_StartPowerMeasurement_Request {
HailoObjectHandle device_handle = 1;
uint32 averaging_factor = 2; /* corresponds to hailo_averaging_factor_t */
uint32 sampling_period = 3; /* corresponds to hailo_sampling_period_t */
}
message Device_StartPowerMeasurement_Reply {
uint32 status = 1;
}
message Device_GetPowerMeasurement_Request {
HailoObjectHandle device_handle = 1;
bool should_clear = 2;
}
message HailoPowerMeasurementData {
float average_value = 1;
float average_time_value_milliseconds = 2;
float min_value = 3;
float max_value = 4;
uint32 total_number_of_samples = 5;
}
message Device_GetPowerMeasurement_Reply {
uint32 status = 1;
HailoPowerMeasurementData data = 2;
}
message Device_StopPowerMeasurement_Request {
HailoObjectHandle device_handle = 1;
}
message Device_StopPowerMeasurement_Reply {
uint32 status = 1;
}

View File

@@ -8,10 +8,12 @@
**/
#include "serializer.hpp"
#include "hailo/buffer.hpp"
#include "hailo/hailort.h"
#include "hailo/hailort_common.hpp"
#include "hailo/hailort_defaults.hpp"
#include "common/utils.hpp"
#include <cstdint>
#include <tuple>
// https://github.com/protocolbuffers/protobuf/tree/master/cmake#notes-on-compiler-warnings
#if defined(_MSC_VER)
@@ -40,16 +42,10 @@ 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-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 'CreateVDevice'");
return serialized_request;
return get_serialized_request<VDevice_Create_Request>(request, "CreateVDevice");
}
Expected<hailo_vdevice_params_t> CreateVDeviceSerializer::deserialize_request(const MemoryView &serialized_request)
Expected<SerializerVDeviceParamsWrapper> CreateVDeviceSerializer::deserialize_request(const MemoryView &serialized_request)
{
VDevice_Create_Request request;
@@ -57,15 +53,14 @@ Expected<hailo_vdevice_params_t> CreateVDeviceSerializer::deserialize_request(co
HAILO_RPC_FAILED, "Failed to de-serialize 'CreateVDevice'");
bool multi_process_service_flag = false;
hailo_vdevice_params_t res = {
SerializerVDeviceParamsWrapper params(
1,
nullptr,
static_cast<hailo_scheduling_algorithm_e>(request.params().scheduling_algorithm()),
request.params().group_id().c_str(),
multi_process_service_flag
};
request.params().group_id(),
multi_process_service_flag);
return res;
return params;
}
Expected<Buffer> CreateVDeviceSerializer::serialize_reply(hailo_status status, rpc_object_handle_t vdevice_handle)
@@ -76,12 +71,8 @@ Expected<Buffer> CreateVDeviceSerializer::serialize_reply(hailo_status status, r
auto proto_vdevice_handle = reply.mutable_vdevice_handle();
proto_vdevice_handle->set_id(vdevice_handle);
TRY(auto serialized_reply, Buffer::create(reply.ByteSizeLong(), BufferStorageParams::create_dma()));
return get_serialized_reply<VDevice_Create_Reply>(reply, "CreateVDevice");
CHECK_AS_EXPECTED(reply.SerializeToArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to serialize 'CreateVDevice'");
return serialized_reply;
}
Expected<std::tuple<hailo_status, rpc_object_handle_t>> CreateVDeviceSerializer::deserialize_reply(const MemoryView &serialized_reply)
@@ -134,16 +125,11 @@ Expected<Buffer> DestroyVDeviceSerializer::serialize_reply(hailo_status status)
hailo_status DestroyVDeviceSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
VDevice_Destroy_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'DestroyVDevice'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<VDevice_Destroy_Reply>(
serialized_reply, "DestroyVDevice");
}
Expected<Buffer> CreateInferModelSerializer::serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size,
const std::string &name)
Expected<Buffer> CreateInferModelSerializer::serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size, const std::string &name)
{
VDevice_CreateInferModel_Request request;
@@ -236,12 +222,8 @@ Expected<Buffer> DestroyInferModelSerializer::serialize_reply(hailo_status statu
hailo_status DestroyInferModelSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
InferModel_Destroy_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'DestroyInferModel'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<InferModel_Destroy_Reply>(
serialized_reply, "DestroyInferModel");
}
Expected<Buffer> CreateConfiguredInferModelSerializer::serialize_request(rpc_create_configured_infer_model_request_params_t params)
@@ -263,6 +245,7 @@ Expected<Buffer> CreateConfiguredInferModelSerializer::serialize_request(rpc_cre
proto_input_stream->set_nms_iou_threshold(input_stream_params.second.nms_iou_threshold);
proto_input_stream->set_nms_max_proposals_per_class(input_stream_params.second.nms_max_proposals_per_class);
proto_input_stream->set_nms_max_accumulated_mask_size(input_stream_params.second.nms_max_accumulated_mask_size);
proto_input_stream->set_nms_max_proposals_total(input_stream_params.second.nms_max_proposals_total);
}
for (auto &output_stream_params : params.output_streams_params) {
@@ -274,6 +257,7 @@ Expected<Buffer> CreateConfiguredInferModelSerializer::serialize_request(rpc_cre
proto_output_stream->set_nms_iou_threshold(output_stream_params.second.nms_iou_threshold);
proto_output_stream->set_nms_max_proposals_per_class(output_stream_params.second.nms_max_proposals_per_class);
proto_output_stream->set_nms_max_accumulated_mask_size(output_stream_params.second.nms_max_accumulated_mask_size);
proto_output_stream->set_nms_max_proposals_total(output_stream_params.second.nms_max_proposals_total);
}
request.set_batch_size(static_cast<uint32_t>(params.batch_size));
@@ -306,6 +290,7 @@ Expected<rpc_create_configured_infer_model_request_params_t> CreateConfiguredInf
current_stream_params.nms_score_threshold = input_stream.nms_score_threshold();
current_stream_params.nms_iou_threshold = input_stream.nms_iou_threshold();
current_stream_params.nms_max_proposals_per_class = input_stream.nms_max_proposals_per_class();
current_stream_params.nms_max_proposals_total = input_stream.nms_max_proposals_total();
current_stream_params.nms_max_accumulated_mask_size = input_stream.nms_max_accumulated_mask_size();
request_params.input_streams_params.emplace(input_stream.name(), current_stream_params);
}
@@ -317,6 +302,7 @@ Expected<rpc_create_configured_infer_model_request_params_t> CreateConfiguredInf
current_stream_params.nms_score_threshold = output_stream.nms_score_threshold();
current_stream_params.nms_iou_threshold = output_stream.nms_iou_threshold();
current_stream_params.nms_max_proposals_per_class = output_stream.nms_max_proposals_per_class();
current_stream_params.nms_max_proposals_total = output_stream.nms_max_proposals_total();
current_stream_params.nms_max_accumulated_mask_size = output_stream.nms_max_accumulated_mask_size();
request_params.output_streams_params.emplace(output_stream.name(), current_stream_params);
}
@@ -397,13 +383,8 @@ Expected<Buffer> DestroyConfiguredInferModelSerializer::serialize_reply(hailo_st
hailo_status DestroyConfiguredInferModelSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_Destroy_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'CreateConfiguredInferModel'");
CHECK_SUCCESS(static_cast<hailo_status>(reply.status()));
return HAILO_SUCCESS;
return get_deserialized_status_only_reply<ConfiguredInferModel_Destroy_Reply>(
serialized_reply, "DestroyConfiguredInferModel");
}
Expected<Buffer> SetSchedulerTimeoutSerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle, const std::chrono::milliseconds &timeout)
@@ -448,12 +429,8 @@ Expected<Buffer> SetSchedulerTimeoutSerializer::serialize_reply(hailo_status sta
hailo_status SetSchedulerTimeoutSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_SetSchedulerTimeout_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'SetSchedulerTimeout'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_SetSchedulerTimeout_Reply>(
serialized_reply, "SetSchedulerTimeout");
}
Expected<Buffer> SetSchedulerThresholdSerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle, uint32_t threshold)
@@ -498,12 +475,8 @@ Expected<Buffer> SetSchedulerThresholdSerializer::serialize_reply(hailo_status s
hailo_status SetSchedulerThresholdSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_SetSchedulerThreshold_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'SetSchedulerThreshold'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_SetSchedulerThreshold_Reply>(
serialized_reply, "SetSchedulerThreshold");
}
Expected<Buffer> SetSchedulerPrioritySerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle, uint32_t priority)
@@ -548,12 +521,8 @@ Expected<Buffer> SetSchedulerPrioritySerializer::serialize_reply(hailo_status st
hailo_status SetSchedulerPrioritySerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_SetSchedulerPriority_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'SetSchedulerPriority'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_SetSchedulerPriority_Reply>(
serialized_reply, "SetSchedulerPriority");
}
Expected<Buffer> GetHwLatencyMeasurementSerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle)
@@ -645,12 +614,8 @@ Expected<Buffer> ActivateSerializer::serialize_reply(hailo_status status)
hailo_status ActivateSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_Activate_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'Activate'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_Activate_Reply>(
serialized_reply, "Activate");
}
Expected<Buffer> DeactivateSerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle)
@@ -693,12 +658,8 @@ Expected<Buffer> DeactivateSerializer::serialize_reply(hailo_status status)
hailo_status DeactivateSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_Deactivate_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'Deactivate'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_Deactivate_Reply>(
serialized_reply, "Deactivate");
}
Expected<Buffer> ShutdownSerializer::serialize_request(rpc_object_handle_t configured_infer_model_handle)
@@ -741,12 +702,8 @@ Expected<Buffer> ShutdownSerializer::serialize_reply(hailo_status status)
hailo_status ShutdownSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_Shutdown_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'Shutdown'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_Shutdown_Reply>(
serialized_reply, "Shutdown");
}
Expected<Buffer> RunAsyncSerializer::serialize_request(const RunAsyncSerializer::Request &request_struct)
@@ -805,12 +762,8 @@ Expected<Buffer> RunAsyncSerializer::serialize_reply(hailo_status status)
hailo_status RunAsyncSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
ConfiguredInferModel_AsyncInfer_Reply reply;
CHECK(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'RunAsync'");
return static_cast<hailo_status>(reply.status());
return get_deserialized_status_only_reply<ConfiguredInferModel_AsyncInfer_Reply>(
serialized_reply, "RunAsync");
}
Expected<Buffer> CallbackCalledSerializer::serialize_reply(hailo_status status, rpc_object_handle_t callback_handle,
@@ -934,12 +887,8 @@ Expected<Buffer> DestroyDeviceSerializer::serialize_reply(hailo_status status)
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());
return get_deserialized_status_only_reply<Device_Destroy_Reply>(
serialized_reply, "DestroyDevice");
}
Expected<Buffer> IdentifyDeviceSerializer::serialize_request(rpc_object_handle_t device_handle)
@@ -1047,22 +996,12 @@ Expected<Buffer> ExtendedDeviceInfoSerializer::serialize_request(rpc_object_hand
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;
return get_serialized_request<Device_ExtendedInfo_Request>(request, "ExtendedDeviceInfo");
}
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();
return get_deserialized_request<Device_ExtendedInfo_Request>(serialized_request, "ExtendedDeviceInfo");
}
Expected<Buffer> ExtendedDeviceInfoSerializer::serialize_reply(hailo_status status, const hailo_extended_device_information_t &extended_info)
@@ -1103,12 +1042,7 @@ Expected<Buffer> ExtendedDeviceInfoSerializer::serialize_reply(hailo_status stat
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;
return get_serialized_reply<Device_ExtendedInfo_Reply>(reply, "ExtendedDeviceInfo");
}
Expected<std::tuple<hailo_status, hailo_extended_device_information_t>> ExtendedDeviceInfoSerializer::deserialize_reply(const MemoryView &serialized_reply)
@@ -1148,4 +1082,267 @@ Expected<std::tuple<hailo_status, hailo_extended_device_information_t>> Extended
return std::make_tuple(static_cast<hailo_status>(reply.status()), extended_info);
}
Expected<Buffer> GetChipTemperatureSerializer::serialize_request(rpc_object_handle_t device_handle)
{
Device_GetChipTemperature_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
return get_serialized_request<Device_GetChipTemperature_Request>(request, "GetChipTemperature");
}
Expected<rpc_object_handle_t> GetChipTemperatureSerializer::deserialize_request(const MemoryView &serialized_request)
{
return get_deserialized_request<Device_GetChipTemperature_Request>(serialized_request, "GetChipTemperature");
}
Expected<Buffer> GetChipTemperatureSerializer::serialize_reply(hailo_status status, const hailo_chip_temperature_info_t &info)
{
Device_GetChipTemperature_Reply reply;
reply.set_status(status);
reply.set_ts0_temperature(info.ts0_temperature);
reply.set_ts1_temperature(info.ts1_temperature);
reply.set_sample_count(info.sample_count);
return get_serialized_reply<Device_GetChipTemperature_Reply>(reply, "GetChipTemperature");
}
Expected<std::tuple<hailo_status, hailo_chip_temperature_info_t>> GetChipTemperatureSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
Device_GetChipTemperature_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'GetChipTemperature'");
hailo_chip_temperature_info_t info = {};
info.ts0_temperature = reply.ts0_temperature();
info.ts1_temperature = reply.ts1_temperature();
info.sample_count = static_cast<uint16_t>(reply.sample_count());
return std::make_tuple(static_cast<hailo_status>(reply.status()), info);
}
Expected<Buffer> PowerMeasurementSerializer::serialize_request(rpc_object_handle_t device_handle, uint32_t hailo_dvm_options, uint32_t hailo_power_measurement_type)
{
Device_PowerMeasurement_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
request.set_hailo_dvm_options(hailo_dvm_options);
request.set_hailo_power_measurement_type(hailo_power_measurement_type);
return get_serialized_request<Device_PowerMeasurement_Request>(request, "PowerMeasurement");
}
Expected<std::tuple<rpc_object_handle_t, uint32_t, uint32_t>> PowerMeasurementSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_PowerMeasurement_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize '{}'", "PowerMeasurement");
auto device_handle_id = request.device_handle().id();
auto hailo_dvm_options = request.hailo_dvm_options();
auto hailo_power_measurement_type = request.hailo_power_measurement_type();
return std::make_tuple(device_handle_id, hailo_dvm_options, hailo_power_measurement_type);
}
Expected<Buffer> PowerMeasurementSerializer::serialize_reply(hailo_status status, const float32_t &power)
{
Device_PowerMeasurement_Reply reply;
reply.set_status(status);
reply.set_power(power);
return get_serialized_reply<Device_PowerMeasurement_Reply>(reply, "PowerMeasurement");
}
Expected<std::tuple<hailo_status, float32_t>> PowerMeasurementSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
Device_PowerMeasurement_Reply reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'PowerMeasurement'");
auto power = reply.power();
return std::make_tuple(static_cast<hailo_status>(reply.status()), power);
}
Expected<Buffer> SetPowerMeasurementSerializer::serialize_request(rpc_object_handle_t device_handle, uint32_t hailo_dvm_options, uint32_t hailo_power_measurement_type)
{
Device_SetPowerMeasurement_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
request.set_hailo_dvm_options(hailo_dvm_options);
request.set_hailo_power_measurement_type(hailo_power_measurement_type);
return get_serialized_request<Device_SetPowerMeasurement_Request>(request, "SetPowerMeasurement");
}
Expected<std::tuple<rpc_object_handle_t, uint32_t, uint32_t>> SetPowerMeasurementSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_SetPowerMeasurement_Request request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize '{}'", "SetPowerMeasurement");
auto device_handle_id = request.device_handle().id();
auto hailo_dvm_options = request.hailo_dvm_options();
auto hailo_power_measurement_type = request.hailo_power_measurement_type();
return std::make_tuple(device_handle_id, hailo_dvm_options, hailo_power_measurement_type);
}
Expected<Buffer> SetPowerMeasurementSerializer::serialize_reply(hailo_status status)
{
Device_SetPowerMeasurement_Reply reply;
reply.set_status(status);
return get_serialized_reply<Device_SetPowerMeasurement_Reply>(reply, "SetPowerMeasurement");
}
hailo_status SetPowerMeasurementSerializer::deserialize_reply(const MemoryView &serialized_reply)
{
return get_deserialized_status_only_reply<Device_SetPowerMeasurement_Reply>(serialized_reply, "SetPowerMeasurement");
}
Expected<Buffer> StartPowerMeasurementSerializer::serialize_request(
rpc_object_handle_t device_handle, uint32_t averaging_factor,
uint32_t sampling_period)
{
Device_StartPowerMeasurement_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
request.set_averaging_factor(averaging_factor);
request.set_sampling_period(sampling_period);
return get_serialized_request<Device_StartPowerMeasurement_Request>(
request, "StartPowerMeasurement");
}
Expected<std::tuple<rpc_object_handle_t, uint32_t, uint32_t>>
StartPowerMeasurementSerializer::deserialize_request(
const MemoryView &serialized_request)
{
Device_StartPowerMeasurement_Request request;
auto parsed_request = request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size()));
CHECK_AS_EXPECTED(parsed_request, HAILO_RPC_FAILED, "Failed to de-serialize '{}'", "StartPowerMeasurement");
auto device_handle_id = request.device_handle().id();
auto averaging_factor = request.averaging_factor();
auto sampling_period = request.sampling_period();
return std::make_tuple(device_handle_id, averaging_factor, sampling_period);
}
Expected<Buffer> StartPowerMeasurementSerializer::serialize_reply(
hailo_status status)
{
Device_StartPowerMeasurement_Reply reply;
reply.set_status(status);
auto serialized_reply = get_serialized_reply<Device_StartPowerMeasurement_Reply>(reply, "StartPowerMeasurement");
return serialized_reply;
}
hailo_status StartPowerMeasurementSerializer::deserialize_reply(
const MemoryView &serialized_reply)
{
return get_deserialized_status_only_reply<Device_StartPowerMeasurement_Reply>(
serialized_reply, "StartPowerMeasurement");
}
Expected<Buffer> GetPowerMeasurementSerializer::serialize_request(
rpc_object_handle_t device_handle, bool should_clear)
{
Device_GetPowerMeasurement_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
request.set_should_clear(should_clear);
return get_serialized_request<Device_GetPowerMeasurement_Request>(request, "GetPowerMeasurement");
}
Expected<std::tuple<rpc_object_handle_t, bool>> GetPowerMeasurementSerializer::deserialize_request(const MemoryView &serialized_request)
{
Device_GetPowerMeasurement_Request request;
CHECK_AS_EXPECTED(
request.ParseFromArray(serialized_request.data(),
static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize '{}'", "GetPowerMeasurement");
auto device_handle_id = request.device_handle().id();
auto should_clear = request.should_clear();
return std::make_tuple(device_handle_id, should_clear);
}
Expected<Buffer> GetPowerMeasurementSerializer::serialize_reply(
hailo_status status, const hailo_power_measurement_data_t &data)
{
Device_GetPowerMeasurement_Reply reply;
reply.set_status(status);
auto proto_data = reply.mutable_data();
proto_data->set_average_value(data.average_value);
proto_data->set_average_time_value_milliseconds(data.average_time_value_milliseconds);
proto_data->set_min_value(data.min_value);
proto_data->set_max_value(data.max_value);
proto_data->set_total_number_of_samples(data.total_number_of_samples);
return get_serialized_reply<Device_GetPowerMeasurement_Reply>(reply, "GetPowerMeasurement");
}
Expected<std::tuple<hailo_status, hailo_power_measurement_data_t>>
GetPowerMeasurementSerializer::deserialize_reply(
const MemoryView &serialized_reply)
{
Device_GetPowerMeasurement_Reply reply;
CHECK_AS_EXPECTED(
reply.ParseFromArray(serialized_reply.data(),
static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize 'GetPowerMeasurement'");
auto data_serialized = reply.data();
hailo_power_measurement_data_t data = {};
data.average_value = data_serialized.average_value();
data.average_time_value_milliseconds = data_serialized.average_time_value_milliseconds();
data.min_value = data_serialized.min_value();
data.max_value = data_serialized.max_value();
data.total_number_of_samples = data_serialized.total_number_of_samples();
return std::make_tuple(
static_cast<hailo_status>(reply.status()), (data));
}
Expected<Buffer> StopPowerMeasurementSerializer::serialize_request(
rpc_object_handle_t device_handle)
{
Device_StopPowerMeasurement_Request request;
auto proto_device_handle = request.mutable_device_handle();
proto_device_handle->set_id(device_handle);
return get_serialized_request<Device_StopPowerMeasurement_Request>(
request, "StopPowerMeasurement");
}
Expected<rpc_object_handle_t> StopPowerMeasurementSerializer::deserialize_request(
const MemoryView &serialized_request)
{
return get_deserialized_request<Device_StopPowerMeasurement_Request>(
serialized_request, "StopPowerMeasurement");
}
Expected<Buffer> StopPowerMeasurementSerializer::serialize_reply(
hailo_status status)
{
Device_StopPowerMeasurement_Reply reply;
reply.set_status(status);
return get_serialized_reply<Device_StopPowerMeasurement_Reply>(
reply, "StopPowerMeasurement");
}
hailo_status StopPowerMeasurementSerializer::deserialize_reply(
const MemoryView &serialized_reply)
{
return get_deserialized_status_only_reply<Device_StopPowerMeasurement_Reply>(
serialized_reply, "StopPowerMeasurement");
}
} /* namespace hailort */

View File

@@ -13,6 +13,7 @@
#include "hailo/hailort.h"
#include "hailo/buffer.hpp"
#include "hailo/expected.hpp"
#include "common/utils.hpp"
#include <chrono>
#include <unordered_map>
@@ -46,6 +47,12 @@ enum class HailoRpcActionID {
DEVICE__DESTROY,
DEVICE__IDENTIFY,
DEVICE__EXTENDED_INFO,
DEVICE__GET_CHIP_TEMPERATURE,
DEVICE__POWER_MEASUREMENT,
DEVICE__SET_POWER_MEASUREMENT,
DEVICE__GET_POWER_MEASUREMENT,
DEVICE__START_POWER_MEASUREMENT,
DEVICE__STOP_POWER_MEASUREMENT,
CALLBACK_CALLED,
@@ -61,6 +68,7 @@ struct rpc_stream_params_t
float32_t nms_iou_threshold;
uint32_t nms_max_proposals_per_class;
uint32_t nms_max_accumulated_mask_size;
uint32_t nms_max_proposals_total;
};
using rpc_stream_params_map_t = std::unordered_map<std::string, rpc_stream_params_t>;
struct rpc_create_configured_infer_model_request_params_t
@@ -74,21 +82,81 @@ struct rpc_create_configured_infer_model_request_params_t
hailo_latency_measurement_flags_t latency_flag;
};
class CreateVDeviceSerializer
class SerializerVDeviceParamsWrapper
{
public:
SerializerVDeviceParamsWrapper(uint32_t device_count,
hailo_device_id_t *device_ids,
hailo_scheduling_algorithm_t scheduling_algorithm,
const std::string &group_id,
bool multi_process_service) : m_group_id(group_id)
{
m_vdevice_params = {
device_count,
device_ids,
scheduling_algorithm,
m_group_id.c_str(),
multi_process_service
};
}
const hailo_vdevice_params_t &get() const { return m_vdevice_params; }
private:
std::string m_group_id;
hailo_vdevice_params_t m_vdevice_params;
};
template <typename T>
Expected<Buffer> get_serialized_request(T request, const std::string &name)
{
// 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 '{}'", name);
return serialized_request;
}
template <typename T>
Expected<rpc_object_handle_t> get_deserialized_request(const MemoryView &serialized_request, const std::string &name)
{
T request;
CHECK_AS_EXPECTED(request.ParseFromArray(serialized_request.data(), static_cast<int>(serialized_request.size())),
HAILO_RPC_FAILED, "Failed to de-serialize '{}'", name);
return request.device_handle().id();
}
template <typename T>
Expected<Buffer> get_serialized_reply(T reply, const std::string &name)
{
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 '{}'", name);
return serialized_reply;
}
template <typename T>
hailo_status get_deserialized_status_only_reply(const MemoryView &serialized_reply, const std::string &name)
{
T reply;
CHECK_AS_EXPECTED(reply.ParseFromArray(serialized_reply.data(), static_cast<int>(serialized_reply.size())),
HAILO_RPC_FAILED, "Failed to de-serialize '{}'", name);
return static_cast<hailo_status>(reply.status());
}
struct CreateVDeviceSerializer
{
CreateVDeviceSerializer() = delete;
static Expected<Buffer> serialize_request(const hailo_vdevice_params_t &params);
static Expected<hailo_vdevice_params_t> deserialize_request(const MemoryView &serialized_request);
static Expected<SerializerVDeviceParamsWrapper> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, rpc_object_handle_t vdevice_handle = INVALID_HANDLE_ID);
static Expected<std::tuple<hailo_status, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class DestroyVDeviceSerializer
struct DestroyVDeviceSerializer
{
public:
DestroyVDeviceSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t vdevice_handle);
@@ -98,9 +166,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class CreateInferModelSerializer
struct CreateInferModelSerializer
{
public:
CreateInferModelSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t vdevice_handle, uint64_t hef_size, const std::string &name);
@@ -110,9 +177,8 @@ public:
static Expected<std::tuple<hailo_status, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class DestroyInferModelSerializer
struct DestroyInferModelSerializer
{
public:
DestroyInferModelSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t infer_model_handle);
@@ -122,9 +188,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class CreateConfiguredInferModelSerializer
struct CreateConfiguredInferModelSerializer
{
public:
CreateConfiguredInferModelSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_create_configured_infer_model_request_params_t params);
@@ -135,9 +200,8 @@ public:
static Expected<std::tuple<hailo_status, rpc_object_handle_t, uint32_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class DestroyConfiguredInferModelSerializer
struct DestroyConfiguredInferModelSerializer
{
public:
DestroyConfiguredInferModelSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle);
@@ -147,9 +211,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class SetSchedulerTimeoutSerializer
struct SetSchedulerTimeoutSerializer
{
public:
SetSchedulerTimeoutSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle, const std::chrono::milliseconds &timeout);
@@ -159,9 +222,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class SetSchedulerThresholdSerializer
struct SetSchedulerThresholdSerializer
{
public:
SetSchedulerThresholdSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle, uint32_t threshold);
@@ -171,9 +233,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class SetSchedulerPrioritySerializer
struct SetSchedulerPrioritySerializer
{
public:
SetSchedulerPrioritySerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle, uint32_t priority);
@@ -183,9 +244,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class GetHwLatencyMeasurementSerializer
struct GetHwLatencyMeasurementSerializer
{
public:
GetHwLatencyMeasurementSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle);
@@ -195,9 +255,8 @@ public:
static Expected<std::tuple<hailo_status, std::chrono::nanoseconds>> deserialize_reply(const MemoryView &serialized_reply);
};
class ActivateSerializer
struct ActivateSerializer
{
public:
ActivateSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle);
@@ -207,9 +266,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class DeactivateSerializer
struct DeactivateSerializer
{
public:
DeactivateSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle);
@@ -219,9 +277,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class ShutdownSerializer
struct ShutdownSerializer
{
public:
ShutdownSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t configured_infer_model_handle);
@@ -231,9 +288,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class RunAsyncSerializer
struct RunAsyncSerializer
{
public:
RunAsyncSerializer() = delete;
struct Request
@@ -251,9 +307,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class CallbackCalledSerializer
struct CallbackCalledSerializer
{
public:
CallbackCalledSerializer() = delete;
static Expected<Buffer> serialize_reply(hailo_status status, rpc_object_handle_t callback_handle = INVALID_HANDLE_ID,
@@ -261,9 +316,8 @@ public:
static Expected<std::tuple<hailo_status, rpc_object_handle_t, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class CreateDeviceSerializer
struct CreateDeviceSerializer
{
public:
CreateDeviceSerializer() = delete;
static Expected<Buffer> serialize_request();
@@ -273,9 +327,8 @@ public:
static Expected<std::tuple<hailo_status, rpc_object_handle_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class DestroyDeviceSerializer
struct DestroyDeviceSerializer
{
public:
DestroyDeviceSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle);
@@ -285,9 +338,8 @@ public:
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
class IdentifyDeviceSerializer
struct IdentifyDeviceSerializer
{
public:
IdentifyDeviceSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle);
@@ -297,9 +349,8 @@ public:
static Expected<std::tuple<hailo_status, hailo_device_identity_t>> deserialize_reply(const MemoryView &serialized_reply);
};
class ExtendedDeviceInfoSerializer
struct ExtendedDeviceInfoSerializer
{
public:
ExtendedDeviceInfoSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle);
@@ -309,6 +360,59 @@ public:
static Expected<std::tuple<hailo_status, hailo_extended_device_information_t>> deserialize_reply(const MemoryView &serialized_reply);
};
struct GetChipTemperatureSerializer
{
GetChipTemperatureSerializer() = 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_chip_temperature_info_t &info = {});
static Expected<std::tuple<hailo_status, hailo_chip_temperature_info_t>> deserialize_reply(const MemoryView &serialized_reply);
};
struct PowerMeasurementSerializer
{
PowerMeasurementSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle, uint32_t hailo_dvm_options, uint32_t hailo_power_measurement_type);
static Expected<std::tuple<rpc_object_handle_t, uint32_t, uint32_t>> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, const float32_t &power = 0.0f);
static Expected<std::tuple<hailo_status, float32_t>> deserialize_reply(const MemoryView &serialized_reply);
};
struct SetPowerMeasurementSerializer
{
SetPowerMeasurementSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle, uint32_t hailo_dvm_options, uint32_t hailo_power_measurement_type);
static Expected<std::tuple<rpc_object_handle_t, uint32_t, uint32_t>> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status);
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
struct StartPowerMeasurementSerializer
{
StartPowerMeasurementSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle, uint32_t averaging_factor, uint32_t sampling_period);
static Expected<std::tuple<rpc_object_handle_t, uint32_t, uint32_t>> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status);
static hailo_status deserialize_reply(const MemoryView &serialized_reply);
};
struct GetPowerMeasurementSerializer
{
GetPowerMeasurementSerializer() = delete;
static Expected<Buffer> serialize_request(rpc_object_handle_t device_handle, bool should_clear);
static Expected<std::tuple<rpc_object_handle_t, bool>> deserialize_request(const MemoryView &serialized_request);
static Expected<Buffer> serialize_reply(hailo_status status, const hailo_power_measurement_data_t &data = {});
static Expected<std::tuple<hailo_status, hailo_power_measurement_data_t>> deserialize_reply(const MemoryView &serialized_reply);
};
struct StopPowerMeasurementSerializer
{
StopPowerMeasurementSerializer() = 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);
};
} /* namespace hailort */

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.5.0)
# set(CMAKE_C_CLANG_TIDY "clang-tidy;-checks=*")
set(HAILORT_MAJOR_VERSION 4)
set(HAILORT_MINOR_VERSION 19)
set(HAILORT_MINOR_VERSION 20)
set(HAILORT_REVISION_VERSION 0)
# Add the cmake folder so the modules there are found
@@ -68,3 +68,6 @@ add_subdirectory(bindings)
if(HAILO_BUILD_DOC)
add_subdirectory(doc)
endif()
# Support builds without installation
set(HailoRT_DIR "${HailoRT_DIR}" PARENT_SCOPE)

View File

@@ -4,7 +4,7 @@ project(gsthailo)
include(GNUInstallDirs)
find_package(HailoRT 4.19.0 EXACT REQUIRED)
find_package(HailoRT 4.20.0 EXACT REQUIRED)
# GST_PLUGIN_DEFINE needs PACKAGE to be defined
set(GST_HAILO_PACKAGE_NAME "hailo")
@@ -37,9 +37,7 @@ 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
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
@@ -71,17 +69,19 @@ endif()
target_compile_options(gsthailo PRIVATE ${HAILORT_COMPILE_OPTIONS})
set(GST_METADATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo/metadata/")
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_include_directories(gsthailo PRIVATE ${GSTREAMER_VIDEO_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo ${CMAKE_CURRENT_SOURCE_DIR}/gst-hailo/os/linux ${GST_METADATA_DIR})
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_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 ${GST_METADATA_DIR})
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/")
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")
@@ -97,5 +97,14 @@ install(TARGETS gsthailo
RUNTIME DESTINATION "${GSTREAMER_LIB_DEST}"
LIBRARY DESTINATION "${GSTREAMER_LIB_DEST}"
ARCHIVE DESTINATION "${GSTREAMER_LIB_DEST}"
PUBLIC_HEADER DESTINATION "${PUBLIC_HEADER_DEST}"
CONFIGURATIONS Release)
# Install the entire gst-hailo/include directory and its contents
install(DIRECTORY gst-hailo/include
DESTINATION ${PUBLIC_HEADER_DEST}
)
install(FILES
gst-hailo/metadata/tensor_meta.hpp
DESTINATION ${PUBLIC_HEADER_DEST}
)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
if (UNIX)
include(find_libs_for_gstreamer_linux.cmake)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.0)
find_package(PkgConfig REQUIRED)
pkg_search_module(GLIB REQUIRED glib-2.0)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.0)
cmake_minimum_required(VERSION 3.5.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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 Hailo Technologies Ltd. All rights reserved.
/**
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the LGPL 2.1 license (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt)
*
* This library is free software; you can redistribute it and/or

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022 Hailo Technologies Ltd. All rights reserved.
/**
* Copyright (c) 2019-2024 Hailo Technologies Ltd. All rights reserved.
* Distributed under the LGPL 2.1 license (https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt)
*
* This library is free software; you can redistribute it and/or
@@ -23,7 +23,7 @@
#include "hailo/device.hpp"
#include "hailo/network_group.hpp"
#include "hailo/vstream.hpp"
#include "hailo_gst.h"
#include "include/hailo_gst.h"
#include <vector>

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