1 // 2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #pragma once 7 8 #include <armnn/backends/DynamicBackend.hpp> 9 #include <armnn/backends/IBackendInternal.hpp> 10 11 #include <armnn/Exceptions.hpp> 12 13 #include <fmt/format.h> 14 15 #include <string> 16 #include <vector> 17 #if defined(__unix__) || defined(__APPLE__) 18 #include <dlfcn.h> 19 #endif 20 21 #if !defined(DYNAMIC_BACKEND_PATHS) 22 #define DYNAMIC_BACKEND_PATHS "" 23 #endif 24 25 namespace armnn 26 { 27 28 class DynamicBackendUtils 29 { 30 public: 31 static void* OpenHandle(const std::string& sharedObjectPath); 32 static void CloseHandle(const void* sharedObjectHandle); 33 34 template<typename EntryPointType> 35 static EntryPointType GetEntryPoint(const void* sharedObjectHandle, const char* symbolName); 36 37 static bool IsBackendCompatible(const BackendVersion& backendVersion); 38 39 static std::vector<std::string> GetBackendPaths(const std::string& overrideBackendPath = ""); 40 static bool IsPathValid(const std::string& path); 41 static std::vector<std::string> GetSharedObjects(const std::vector<std::string>& backendPaths); 42 43 static std::vector<DynamicBackendPtr> CreateDynamicBackends(const std::vector<std::string>& sharedObjects); 44 static BackendIdSet RegisterDynamicBackends(const std::vector<DynamicBackendPtr>& dynamicBackends); 45 static void DeregisterDynamicBackends(const BackendIdSet& dynamicBackends); 46 47 protected: 48 /// Protected methods for testing purposes 49 static bool IsBackendCompatibleImpl(const BackendVersion& backendApiVersion, const BackendVersion& backendVersion); 50 static std::vector<std::string> GetBackendPathsImpl(const std::string& backendPaths); 51 static BackendIdSet RegisterDynamicBackendsImpl(BackendRegistry& backendRegistry, 52 const std::vector<DynamicBackendPtr>& dynamicBackends); 53 54 private: 55 static std::string GetDlError(); 56 57 /// This class is to hold utility functions only 58 DynamicBackendUtils() = delete; 59 }; 60 61 template<typename EntryPointType> GetEntryPoint(const void * sharedObjectHandle,const char * symbolName)62EntryPointType DynamicBackendUtils::GetEntryPoint(const void* sharedObjectHandle, const char* symbolName) 63 { 64 #if defined(__unix__) || defined(__APPLE__) 65 if (sharedObjectHandle == nullptr) 66 { 67 throw RuntimeException("GetEntryPoint error: invalid handle"); 68 } 69 70 if (symbolName == nullptr) 71 { 72 throw RuntimeException("GetEntryPoint error: invalid symbol"); 73 } 74 75 auto entryPoint = reinterpret_cast<EntryPointType>(dlsym(const_cast<void*>(sharedObjectHandle), symbolName)); 76 if (!entryPoint) 77 { 78 throw RuntimeException(fmt::format("GetEntryPoint error: {}", GetDlError())); 79 } 80 81 return entryPoint; 82 #else 83 armnn::IgnoreUnused(sharedObjectHandle); 84 armnn::IgnoreUnused(symbolName); 85 throw RuntimeException("Dynamic backends not supported on this platform"); 86 #endif 87 } 88 89 } // namespace armnn 90