• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include <armnn/backends/DynamicBackend.hpp>
7 #include <backendsCommon/DynamicBackendUtils.hpp>
8 
9 namespace armnn
10 {
11 
DynamicBackend(const void * sharedObjectHandle)12 DynamicBackend::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         // This exception message could not be formatted simply using fmt::format
34         std::stringstream message;
35         message << "The dynamic backend " << backendId << " (version " << backendVersion <<
36         ") is not compatible with the current Backend API (version " << IBackendInternal::GetApiVersion() << ")";
37 
38         throw RuntimeException(message.str());
39     }
40 }
41 
GetBackendId()42 BackendId DynamicBackend::GetBackendId()
43 {
44     if (m_BackendIdFunction == nullptr)
45     {
46         throw RuntimeException("GetBackendId error: invalid function pointer");
47     }
48 
49     const char* backendId = m_BackendIdFunction();
50     if (backendId == nullptr)
51     {
52         throw RuntimeException("GetBackendId error: invalid backend id");
53     }
54 
55     return BackendId(backendId);
56 }
57 
GetBackendVersion()58 BackendVersion DynamicBackend::GetBackendVersion()
59 {
60     if (m_BackendVersionFunction == nullptr)
61     {
62         throw RuntimeException("GetBackendVersion error: invalid function pointer");
63     }
64 
65     uint32_t major = 0;
66     uint32_t minor = 0;
67     m_BackendVersionFunction(&major, &minor);
68 
69     return BackendVersion{ major, minor };
70 }
71 
GetBackend()72 IBackendInternalUniquePtr DynamicBackend::GetBackend()
73 {
74     // This call throws in case of error
75     return CreateBackend();
76 }
77 
GetFactoryFunction()78 BackendRegistry::FactoryFunction DynamicBackend::GetFactoryFunction()
79 {
80     if (m_BackendFactoryFunction == nullptr)
81     {
82         throw RuntimeException("GetFactoryFunction error: invalid function pointer");
83     }
84 
85     return [this]() -> IBackendInternalUniquePtr
86     {
87         // This call throws in case of error
88         return CreateBackend();
89     };
90 }
91 
92 template<typename BackendFunctionType>
SetFunctionPointer(const std::string & backendFunctionName)93 BackendFunctionType DynamicBackend::SetFunctionPointer(const std::string& backendFunctionName)
94 {
95     if (m_Handle == nullptr)
96     {
97         throw RuntimeException("SetFunctionPointer error: invalid shared object handle");
98     }
99 
100     if (backendFunctionName.empty())
101     {
102         throw RuntimeException("SetFunctionPointer error: backend function name must not be empty");
103     }
104 
105     // This call will throw in case of error
106     auto functionPointer = DynamicBackendUtils::GetEntryPoint<BackendFunctionType>(m_Handle.get(),
107                                                                                    backendFunctionName.c_str());
108     if (!functionPointer)
109     {
110         throw RuntimeException("SetFunctionPointer error: invalid backend function pointer returned");
111     }
112 
113     return functionPointer;
114 }
115 
CreateBackend()116 IBackendInternalUniquePtr DynamicBackend::CreateBackend()
117 {
118     if (m_BackendFactoryFunction == nullptr)
119     {
120         throw RuntimeException("CreateBackend error: invalid function pointer");
121     }
122 
123     auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
124     if (backendPointer == nullptr)
125     {
126         throw RuntimeException("CreateBackend error: backend instance must not be null");
127     }
128 
129     return std::unique_ptr<IBackendInternal>(backendPointer);
130 }
131 
132 } // namespace armnn
133