blob: 927af922014866c5bd0b2859c4d46a5910080ccb [file] [log] [blame]
telsoa015307bc12018-03-09 13:51:08 +00001//
2// Copyright © 2017 Arm Ltd. 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
Narumol Prangnawarat4d07e5e2020-04-06 16:46:21 +010020#include <armnn/utility/Assert.hpp>
telsoa015307bc12018-03-09 13:51:08 +000021
arovir01b0717b52018-09-05 17:03:25 +010022#include <log/log.h>
23
telsoa015307bc12018-03-09 13:51:08 +000024using namespace android;
25
26namespace armnn_driver
27{
28
Derek Lamberti4de83c52020-03-17 13:40:18 +000029template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
30RequestThread<PreparedModel, HalVersion, CallbackContext>::RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000031{
32 ALOGV("RequestThread::RequestThread()");
33 m_Thread = std::make_unique<std::thread>(&RequestThread::Process, this);
34}
35
Derek Lamberti4de83c52020-03-17 13:40:18 +000036template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
37RequestThread<PreparedModel, HalVersion, CallbackContext>::~RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000038{
39 ALOGV("RequestThread::~RequestThread()");
surmeh0149b9e102018-05-17 14:11:25 +010040
41 try
42 {
43 // Coverity fix: The following code may throw an exception of type std::length_error.
44
45 // This code is meant to to terminate the inner thread gracefully by posting an EXIT message
46 // to the thread's message queue. However, according to Coverity, this code could throw an exception and fail.
47 // Since only one static instance of RequestThread is used in the driver (in ArmnnPreparedModel),
48 // this destructor is called only when the application has been closed, which means that
49 // the inner thread will be terminated anyway, although abruptly, in the event that the destructor code throws.
50 // Wrapping the destructor's code with a try-catch block simply fixes the Coverity bug.
51
52 // Post an EXIT message to the thread
53 std::shared_ptr<AsyncExecuteData> nulldata(nullptr);
54 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::EXIT, nulldata);
55 PostMsg(pMsg);
56 // Wait for the thread to terminate, it is deleted automatically
57 m_Thread->join();
58 }
59 catch (const std::exception&) { } // Swallow any exception.
telsoa015307bc12018-03-09 13:51:08 +000060}
61
Derek Lamberti4de83c52020-03-17 13:40:18 +000062template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
63void RequestThread<PreparedModel, HalVersion, CallbackContext>::PostMsg(PreparedModel<HalVersion>* model,
Mike Kellyb5fdf382019-06-11 16:35:25 +010064 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& memPools,
65 std::shared_ptr<armnn::InputTensors>& inputTensors,
66 std::shared_ptr<armnn::OutputTensors>& outputTensors,
Derek Lamberti4de83c52020-03-17 13:40:18 +000067 CallbackContext callbackContext)
telsoa015307bc12018-03-09 13:51:08 +000068{
69 ALOGV("RequestThread::PostMsg(...)");
70 auto data = std::make_shared<AsyncExecuteData>(model,
71 memPools,
72 inputTensors,
73 outputTensors,
Derek Lamberti4de83c52020-03-17 13:40:18 +000074 callbackContext);
telsoa015307bc12018-03-09 13:51:08 +000075 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::REQUEST, data);
76 PostMsg(pMsg);
77}
78
Derek Lamberti4de83c52020-03-17 13:40:18 +000079template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
80void RequestThread<PreparedModel, HalVersion, CallbackContext>::PostMsg(std::shared_ptr<ThreadMsg>& pMsg)
telsoa015307bc12018-03-09 13:51:08 +000081{
82 ALOGV("RequestThread::PostMsg(pMsg)");
83 // Add a message to the queue and notify the request thread
84 std::unique_lock<std::mutex> lock(m_Mutex);
85 m_Queue.push(pMsg);
86 m_Cv.notify_one();
87}
88
Derek Lamberti4de83c52020-03-17 13:40:18 +000089template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename CallbackContext>
90void RequestThread<PreparedModel, HalVersion, CallbackContext>::Process()
telsoa015307bc12018-03-09 13:51:08 +000091{
92 ALOGV("RequestThread::Process()");
93 while (true)
94 {
95 std::shared_ptr<ThreadMsg> pMsg(nullptr);
96 {
97 // Wait for a message to be added to the queue
98 // This is in a separate scope to minimise the lifetime of the lock
99 std::unique_lock<std::mutex> lock(m_Mutex);
100 while (m_Queue.empty())
101 {
102 m_Cv.wait(lock);
103 }
104 // get the message to process from the front of the queue
105 pMsg = m_Queue.front();
106 m_Queue.pop();
107 }
108
109 switch (pMsg->type)
110 {
111 case ThreadMsgType::REQUEST:
112 {
113 ALOGV("RequestThread::Process() - request");
114 // invoke the asynchronous execution method
Mike Kellyb5fdf382019-06-11 16:35:25 +0100115 PreparedModel<HalVersion>* model = pMsg->data->m_Model;
telsoa015307bc12018-03-09 13:51:08 +0000116 model->ExecuteGraph(pMsg->data->m_MemPools,
Derek Lamberti4de83c52020-03-17 13:40:18 +0000117 *(pMsg->data->m_InputTensors),
118 *(pMsg->data->m_OutputTensors),
119 pMsg->data->m_CallbackContext);
telsoa015307bc12018-03-09 13:51:08 +0000120 break;
121 }
122
123 case ThreadMsgType::EXIT:
124 {
125 ALOGV("RequestThread::Process() - exit");
126 // delete all remaining messages (there should not be any)
127 std::unique_lock<std::mutex> lock(m_Mutex);
128 while (!m_Queue.empty())
129 {
130 m_Queue.pop();
131 }
132 return;
133 }
134
135 default:
136 // this should be unreachable
137 ALOGE("RequestThread::Process() - invalid message type");
Narumol Prangnawarat4d07e5e2020-04-06 16:46:21 +0100138 ARMNN_ASSERT_MSG(false, "ArmNN: RequestThread: invalid message type");
telsoa015307bc12018-03-09 13:51:08 +0000139 }
140 }
141}
142
arovir01b0717b52018-09-05 17:03:25 +0100143///
144/// Class template specializations
145///
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100146
Derek Lamberti4de83c52020-03-17 13:40:18 +0000147template class RequestThread<ArmnnPreparedModel, hal_1_0::HalPolicy, CallbackContext_1_0>;
arovir01b0717b52018-09-05 17:03:25 +0100148
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100149#ifdef ARMNN_ANDROID_NN_V1_1
Derek Lamberti4de83c52020-03-17 13:40:18 +0000150template class RequestThread<armnn_driver::ArmnnPreparedModel, hal_1_1::HalPolicy, CallbackContext_1_0>;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100151#endif
152
153#ifdef ARMNN_ANDROID_NN_V1_2
Derek Lamberti4de83c52020-03-17 13:40:18 +0000154template class RequestThread<ArmnnPreparedModel, hal_1_1::HalPolicy, CallbackContext_1_0>;
155template class RequestThread<ArmnnPreparedModel, hal_1_2::HalPolicy, CallbackContext_1_0>;
156template class RequestThread<ArmnnPreparedModel_1_2, hal_1_2::HalPolicy, CallbackContext_1_2>;
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100157#endif
158
Kevin May42477c12020-03-26 13:34:14 +0000159#ifdef ARMNN_ANDROID_NN_V1_3
160template class RequestThread<ArmnnPreparedModel, hal_1_1::HalPolicy, CallbackContext_1_0>;
161template class RequestThread<ArmnnPreparedModel, hal_1_2::HalPolicy, CallbackContext_1_0>;
162template class RequestThread<ArmnnPreparedModel, hal_1_3::HalPolicy, CallbackContext_1_0>;
163template class RequestThread<ArmnnPreparedModel_1_2, hal_1_2::HalPolicy, CallbackContext_1_2>;
Kevin May42477c12020-03-26 13:34:14 +0000164#endif
165
Matthew Bentham9e80cd22019-05-03 22:54:36 +0100166} // namespace armnn_driver