blob: 783e351de5da41220acadc61d31a5573b2894d9e [file] [log] [blame]
telsoa015307bc12018-03-09 13:51:08 +00001//
Mike Kellye2d611e2021-10-14 12:35:58 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
telsoa015307bc12018-03-09 13:51:08 +00004//
5
6#define LOG_TAG "ArmnnDriver"
7
8#include "RequestThread.hpp"
9#include "ArmnnPreparedModel.hpp"
10
Mike Kellyb5fdf382019-06-11 16:35:25 +010011#ifdef ARMNN_ANDROID_NN_V1_2
12#include "ArmnnPreparedModel_1_2.hpp"
13#endif
14
Kevin May42477c12020-03-26 13:34:14 +000015#ifdef ARMNN_ANDROID_NN_V1_3
16#include "ArmnnPreparedModel_1_2.hpp"
17#include "ArmnnPreparedModel_1_3.hpp"
18#endif
19
arovir01b0717b52018-09-05 17:03:25 +010020#include <log/log.h>
21
telsoa015307bc12018-03-09 13:51:08 +000022using namespace android;
23
24namespace armnn_driver
25{
26
Derek Lamberti4de83c52020-03-17 13:40:18 +000027template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
28RequestThread<PreparedModel, HalVersion, CallbackContext>::RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000029{
30 ALOGV("RequestThread::RequestThread()");
31 m_Thread = std::make_unique<std::thread>(&RequestThread::Process, this);
32}
33
Derek Lamberti4de83c52020-03-17 13:40:18 +000034template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
35RequestThread<PreparedModel, HalVersion, CallbackContext>::~RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000036{
37 ALOGV("RequestThread::~RequestThread()");
surmeh0149b9e102018-05-17 14:11:25 +010038
39 try
40 {
41 // Coverity fix: The following code may throw an exception of type std::length_error.
42
43 // This code is meant to to terminate the inner thread gracefully by posting an EXIT message
44 // to the thread's message queue. However, according to Coverity, this code could throw an exception and fail.
45 // Since only one static instance of RequestThread is used in the driver (in ArmnnPreparedModel),
46 // this destructor is called only when the application has been closed, which means that
47 // the inner thread will be terminated anyway, although abruptly, in the event that the destructor code throws.
48 // Wrapping the destructor's code with a try-catch block simply fixes the Coverity bug.
49
50 // Post an EXIT message to the thread
51 std::shared_ptr<AsyncExecuteData> nulldata(nullptr);
52 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::EXIT, nulldata);
53 PostMsg(pMsg);
54 // Wait for the thread to terminate, it is deleted automatically
55 m_Thread->join();
56 }
57 catch (const std::exception&) { } // Swallow any exception.
telsoa015307bc12018-03-09 13:51:08 +000058}
59
Derek Lamberti4de83c52020-03-17 13:40:18 +000060template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
61void RequestThread<PreparedModel, HalVersion, CallbackContext>::PostMsg(PreparedModel<HalVersion>* model,
Mike Kellyb5fdf382019-06-11 16:35:25 +010062 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& memPools,
63 std::shared_ptr<armnn::InputTensors>& inputTensors,
64 std::shared_ptr<armnn::OutputTensors>& outputTensors,
Derek Lamberti4de83c52020-03-17 13:40:18 +000065 CallbackContext callbackContext)
telsoa015307bc12018-03-09 13:51:08 +000066{
67 ALOGV("RequestThread::PostMsg(...)");
68 auto data = std::make_shared<AsyncExecuteData>(model,
69 memPools,
70 inputTensors,
71 outputTensors,
Derek Lamberti4de83c52020-03-17 13:40:18 +000072 callbackContext);
telsoa015307bc12018-03-09 13:51:08 +000073 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::REQUEST, data);
74 PostMsg(pMsg);
75}
76
Derek Lamberti4de83c52020-03-17 13:40:18 +000077template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
78void RequestThread<PreparedModel, HalVersion, CallbackContext>::PostMsg(std::shared_ptr<ThreadMsg>& pMsg)
telsoa015307bc12018-03-09 13:51:08 +000079{
80 ALOGV("RequestThread::PostMsg(pMsg)");
81 // Add a message to the queue and notify the request thread
82 std::unique_lock<std::mutex> lock(m_Mutex);
83 m_Queue.push(pMsg);
84 m_Cv.notify_one();
85}
86
Derek Lamberti4de83c52020-03-17 13:40:18 +000087template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
88void RequestThread<PreparedModel, HalVersion, CallbackContext>::Process()
telsoa015307bc12018-03-09 13:51:08 +000089{
90 ALOGV("RequestThread::Process()");
91 while (true)
92 {
93 std::shared_ptr<ThreadMsg> pMsg(nullptr);
94 {
95 // Wait for a message to be added to the queue
96 // This is in a separate scope to minimise the lifetime of the lock
97 std::unique_lock<std::mutex> lock(m_Mutex);
98 while (m_Queue.empty())
99 {
100 m_Cv.wait(lock);
101 }
102 // get the message to process from the front of the queue
103 pMsg = m_Queue.front();
104 m_Queue.pop();
105 }
106
107 switch (pMsg->type)
108 {
109 case ThreadMsgType::REQUEST:
110 {
111 ALOGV("RequestThread::Process() - request");
112 // invoke the asynchronous execution method
Mike Kellyb5fdf382019-06-11 16:35:25 +0100113 PreparedModel<HalVersion>* model = pMsg->data->m_Model;
telsoa015307bc12018-03-09 13:51:08 +0000114 model->ExecuteGraph(pMsg->data->m_MemPools,
Derek Lamberti4de83c52020-03-17 13:40:18 +0000115 *(pMsg->data->m_InputTensors),
116 *(pMsg->data->m_OutputTensors),
117 pMsg->data->m_CallbackContext);
telsoa015307bc12018-03-09 13:51:08 +0000118 break;
119 }
120
121 case ThreadMsgType::EXIT:
122 {
123 ALOGV("RequestThread::Process() - exit");
124 // delete all remaining messages (there should not be any)
125 std::unique_lock<std::mutex> lock(m_Mutex);
126 while (!m_Queue.empty())
127 {
128 m_Queue.pop();
129 }
130 return;
131 }
132
133 default:
134 // this should be unreachable
Mike Kellye2d611e2021-10-14 12:35:58 +0100135 throw armnn::RuntimeException("ArmNN: RequestThread: invalid message type");
telsoa015307bc12018-03-09 13:51:08 +0000136 }
137 }
138}
139
arovir01b0717b52018-09-05 17:03:25 +0100140///
141/// Class template specializations
142///
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100143
Derek Lamberti4de83c52020-03-17 13:40:18 +0000144template class RequestThread<ArmnnPreparedModel, hal_1_0::HalPolicy, CallbackContext_1_0>;
arovir01b0717b52018-09-05 17:03:25 +0100145
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100146#ifdef ARMNN_ANDROID_NN_V1_1
Derek Lamberti4de83c52020-03-17 13:40:18 +0000147template class RequestThread<armnn_driver::ArmnnPreparedModel, hal_1_1::HalPolicy, CallbackContext_1_0>;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100148#endif
149
150#ifdef ARMNN_ANDROID_NN_V1_2
Derek Lamberti4de83c52020-03-17 13:40:18 +0000151template class RequestThread<ArmnnPreparedModel, hal_1_1::HalPolicy, CallbackContext_1_0>;
152template class RequestThread<ArmnnPreparedModel, hal_1_2::HalPolicy, CallbackContext_1_0>;
153template class RequestThread<ArmnnPreparedModel_1_2, hal_1_2::HalPolicy, CallbackContext_1_2>;
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100154#endif
155
Kevin May42477c12020-03-26 13:34:14 +0000156#ifdef ARMNN_ANDROID_NN_V1_3
157template class RequestThread<ArmnnPreparedModel, hal_1_1::HalPolicy, CallbackContext_1_0>;
158template class RequestThread<ArmnnPreparedModel, hal_1_2::HalPolicy, CallbackContext_1_0>;
159template class RequestThread<ArmnnPreparedModel, hal_1_3::HalPolicy, CallbackContext_1_0>;
160template class RequestThread<ArmnnPreparedModel_1_2, hal_1_2::HalPolicy, CallbackContext_1_2>;
Kevin May42477c12020-03-26 13:34:14 +0000161#endif
162
Matthew Bentham9e80cd22019-05-03 22:54:36 +0100163} // namespace armnn_driver