blob: 06d819b9a729f5366a070edb7709abb0dc52a59d [file] [log] [blame]
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "DynamicBackend.hpp"
7#include "DynamicBackendUtils.hpp"
8
9namespace armnn
10{
11
12DynamicBackend::DynamicBackend(const void* sharedObjectHandle)
13 : m_BackendIdFunction(nullptr)
14 , m_BackendVersionFunction(nullptr)
15 , m_BackendFactoryFunction(nullptr)
16 , m_Handle(const_cast<void*>(sharedObjectHandle), &DynamicBackendUtils::CloseHandle)
17{
18 if (m_Handle == nullptr)
19 {
20 throw InvalidArgumentException("Cannot create a DynamicBackend object from an invalid shared object handle");
21 }
22
23 // These calls will throw in case of error
24 m_BackendIdFunction = SetFunctionPointer<IdFunctionType>("GetBackendId");
25 m_BackendVersionFunction = SetFunctionPointer<VersionFunctionType>("GetVersion");
26 m_BackendFactoryFunction = SetFunctionPointer<FactoryFunctionType>("BackendFactory");
27
28 // Check that the backend is compatible with the current Backend API
29 BackendId backendId = GetBackendId();
30 BackendVersion backendVersion = GetBackendVersion();
31 if (!DynamicBackendUtils::IsBackendCompatible(backendVersion))
32 {
33 throw RuntimeException(boost::str(boost::format("The dynamic backend %1% (version %2%) is not compatible"
34 "with the current Backend API (vesion %3%)")
35 % backendId
36 % backendVersion
37 % IBackendInternal::GetApiVersion()));
38 }
39}
40
41BackendId DynamicBackend::GetBackendId()
42{
43 if (m_BackendIdFunction == nullptr)
44 {
45 throw RuntimeException("GetBackendId error: invalid function pointer");
46 }
47
Matteo Martincighbc2e2102019-07-24 14:56:13 +010048 const char* backendId = m_BackendIdFunction();
49 if (backendId == nullptr)
50 {
51 throw RuntimeException("GetBackendId error: invalid backend id");
52 }
53
54 return BackendId(backendId);
Matteo Martincigh2e7f6ad2019-07-24 09:54:26 +010055}
56
57BackendVersion DynamicBackend::GetBackendVersion()
58{
59 if (m_BackendVersionFunction == nullptr)
60 {
61 throw RuntimeException("GetBackendVersion error: invalid function pointer");
62 }
63
64 uint32_t major = 0;
65 uint32_t minor = 0;
66 m_BackendVersionFunction(&major, &minor);
67
68 return BackendVersion{ major, minor };
69}
70
71IBackendInternalUniquePtr DynamicBackend::GetBackend()
72{
73 if (m_BackendFactoryFunction == nullptr)
74 {
75 throw RuntimeException("GetBackend error: invalid function pointer");
76 }
77
78 auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
79 if (backendPointer == nullptr)
80 {
81 throw RuntimeException("GetBackend error: backend instance must not be null");
82 }
83
84 return std::unique_ptr<IBackendInternal>(backendPointer);
85}
86
87template<typename BackendFunctionType>
88BackendFunctionType DynamicBackend::SetFunctionPointer(const std::string& backendFunctionName)
89{
90 if (m_Handle == nullptr)
91 {
92 throw RuntimeException("SetFunctionPointer error: invalid shared object handle");
93 }
94
95 if (backendFunctionName.empty())
96 {
97 throw RuntimeException("SetFunctionPointer error: backend function name must not be empty");
98 }
99
100 // This call will throw in case of error
101 auto functionPointer = DynamicBackendUtils::GetEntryPoint<BackendFunctionType>(m_Handle.get(),
102 backendFunctionName.c_str());
103 if (!functionPointer)
104 {
105 throw RuntimeException("SetFunctionPointer error: invalid backend function pointer returned");
106 }
107
108 return functionPointer;
109}
110
111} // namespace armnn