blob: 052c5c110b6781daa8db3079d7e8451329530cf0 [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
telsoa015307bc12018-03-09 13:51:08 +000015#include <boost/assert.hpp>
16
arovir01b0717b52018-09-05 17:03:25 +010017#include <log/log.h>
18
telsoa015307bc12018-03-09 13:51:08 +000019using namespace android;
20
21namespace armnn_driver
22{
23
Mike Kelly65c42dc2019-07-22 14:06:00 +010024template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename Callback>
25RequestThread<PreparedModel, HalVersion, Callback>::RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000026{
27 ALOGV("RequestThread::RequestThread()");
28 m_Thread = std::make_unique<std::thread>(&RequestThread::Process, this);
29}
30
Mike Kelly65c42dc2019-07-22 14:06:00 +010031template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename Callback>
32RequestThread<PreparedModel, HalVersion, Callback>::~RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000033{
34 ALOGV("RequestThread::~RequestThread()");
surmeh0149b9e102018-05-17 14:11:25 +010035
36 try
37 {
38 // Coverity fix: The following code may throw an exception of type std::length_error.
39
40 // This code is meant to to terminate the inner thread gracefully by posting an EXIT message
41 // to the thread's message queue. However, according to Coverity, this code could throw an exception and fail.
42 // Since only one static instance of RequestThread is used in the driver (in ArmnnPreparedModel),
43 // this destructor is called only when the application has been closed, which means that
44 // the inner thread will be terminated anyway, although abruptly, in the event that the destructor code throws.
45 // Wrapping the destructor's code with a try-catch block simply fixes the Coverity bug.
46
47 // Post an EXIT message to the thread
48 std::shared_ptr<AsyncExecuteData> nulldata(nullptr);
49 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::EXIT, nulldata);
50 PostMsg(pMsg);
51 // Wait for the thread to terminate, it is deleted automatically
52 m_Thread->join();
53 }
54 catch (const std::exception&) { } // Swallow any exception.
telsoa015307bc12018-03-09 13:51:08 +000055}
56
Mike Kelly65c42dc2019-07-22 14:06:00 +010057template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename Callback>
58void RequestThread<PreparedModel, HalVersion, Callback>::PostMsg(PreparedModel<HalVersion>* model,
Mike Kellyb5fdf382019-06-11 16:35:25 +010059 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& memPools,
60 std::shared_ptr<armnn::InputTensors>& inputTensors,
61 std::shared_ptr<armnn::OutputTensors>& outputTensors,
Mike Kelly65c42dc2019-07-22 14:06:00 +010062 Callback callback)
telsoa015307bc12018-03-09 13:51:08 +000063{
64 ALOGV("RequestThread::PostMsg(...)");
65 auto data = std::make_shared<AsyncExecuteData>(model,
66 memPools,
67 inputTensors,
68 outputTensors,
69 callback);
70 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::REQUEST, data);
71 PostMsg(pMsg);
72}
73
Mike Kelly65c42dc2019-07-22 14:06:00 +010074template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename Callback>
75void RequestThread<PreparedModel, HalVersion, Callback>::PostMsg(std::shared_ptr<ThreadMsg>& pMsg)
telsoa015307bc12018-03-09 13:51:08 +000076{
77 ALOGV("RequestThread::PostMsg(pMsg)");
78 // Add a message to the queue and notify the request thread
79 std::unique_lock<std::mutex> lock(m_Mutex);
80 m_Queue.push(pMsg);
81 m_Cv.notify_one();
82}
83
Mike Kelly65c42dc2019-07-22 14:06:00 +010084template <template <typename HalVersion> class PreparedModel, typename HalVersion, typename Callback>
85void RequestThread<PreparedModel, HalVersion, Callback>::Process()
telsoa015307bc12018-03-09 13:51:08 +000086{
87 ALOGV("RequestThread::Process()");
88 while (true)
89 {
90 std::shared_ptr<ThreadMsg> pMsg(nullptr);
91 {
92 // Wait for a message to be added to the queue
93 // This is in a separate scope to minimise the lifetime of the lock
94 std::unique_lock<std::mutex> lock(m_Mutex);
95 while (m_Queue.empty())
96 {
97 m_Cv.wait(lock);
98 }
99 // get the message to process from the front of the queue
100 pMsg = m_Queue.front();
101 m_Queue.pop();
102 }
103
104 switch (pMsg->type)
105 {
106 case ThreadMsgType::REQUEST:
107 {
108 ALOGV("RequestThread::Process() - request");
109 // invoke the asynchronous execution method
Mike Kellyb5fdf382019-06-11 16:35:25 +0100110 PreparedModel<HalVersion>* model = pMsg->data->m_Model;
telsoa015307bc12018-03-09 13:51:08 +0000111 model->ExecuteGraph(pMsg->data->m_MemPools,
112 pMsg->data->m_InputTensors,
113 pMsg->data->m_OutputTensors,
Mike Kelly65c42dc2019-07-22 14:06:00 +0100114 pMsg->data->m_Callback);
telsoa015307bc12018-03-09 13:51:08 +0000115 break;
116 }
117
118 case ThreadMsgType::EXIT:
119 {
120 ALOGV("RequestThread::Process() - exit");
121 // delete all remaining messages (there should not be any)
122 std::unique_lock<std::mutex> lock(m_Mutex);
123 while (!m_Queue.empty())
124 {
125 m_Queue.pop();
126 }
127 return;
128 }
129
130 default:
131 // this should be unreachable
132 ALOGE("RequestThread::Process() - invalid message type");
133 BOOST_ASSERT_MSG(false, "ArmNN: RequestThread: invalid message type");
134 }
135 }
136}
137
arovir01b0717b52018-09-05 17:03:25 +0100138///
139/// Class template specializations
140///
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100141
Mike Kelly65c42dc2019-07-22 14:06:00 +0100142template class RequestThread<ArmnnPreparedModel, hal_1_0::HalPolicy, ArmnnCallback_1_0>;
arovir01b0717b52018-09-05 17:03:25 +0100143
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100144#ifdef ARMNN_ANDROID_NN_V1_1
Mike Kelly65c42dc2019-07-22 14:06:00 +0100145template class RequestThread<armnn_driver::ArmnnPreparedModel, hal_1_1::HalPolicy, ArmnnCallback_1_0>;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100146#endif
147
148#ifdef ARMNN_ANDROID_NN_V1_2
Mike Kelly65c42dc2019-07-22 14:06:00 +0100149template class RequestThread<ArmnnPreparedModel, hal_1_1::HalPolicy, ArmnnCallback_1_0>;
150template class RequestThread<ArmnnPreparedModel, hal_1_2::HalPolicy, ArmnnCallback_1_0>;
151template class RequestThread<ArmnnPreparedModel_1_2, hal_1_2::HalPolicy, ArmnnCallback_1_2>;
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100152#endif
153
Matthew Bentham9e80cd22019-05-03 22:54:36 +0100154} // namespace armnn_driver