blob: 4731489e7070c3e5ecef164f4365acb0e5e060fa [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
telsoa015307bc12018-03-09 13:51:08 +000011#include <boost/assert.hpp>
12
arovir01b0717b52018-09-05 17:03:25 +010013#include <log/log.h>
14
telsoa015307bc12018-03-09 13:51:08 +000015using namespace android;
16
17namespace armnn_driver
18{
19
Matteo Martincighe48bdff2018-09-03 13:50:50 +010020template<typename HalVersion>
21RequestThread<HalVersion>::RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000022{
23 ALOGV("RequestThread::RequestThread()");
24 m_Thread = std::make_unique<std::thread>(&RequestThread::Process, this);
25}
26
Matteo Martincighe48bdff2018-09-03 13:50:50 +010027template<typename HalVersion>
28RequestThread<HalVersion>::~RequestThread()
telsoa015307bc12018-03-09 13:51:08 +000029{
30 ALOGV("RequestThread::~RequestThread()");
surmeh0149b9e102018-05-17 14:11:25 +010031
32 try
33 {
34 // Coverity fix: The following code may throw an exception of type std::length_error.
35
36 // This code is meant to to terminate the inner thread gracefully by posting an EXIT message
37 // to the thread's message queue. However, according to Coverity, this code could throw an exception and fail.
38 // Since only one static instance of RequestThread is used in the driver (in ArmnnPreparedModel),
39 // this destructor is called only when the application has been closed, which means that
40 // the inner thread will be terminated anyway, although abruptly, in the event that the destructor code throws.
41 // Wrapping the destructor's code with a try-catch block simply fixes the Coverity bug.
42
43 // Post an EXIT message to the thread
44 std::shared_ptr<AsyncExecuteData> nulldata(nullptr);
45 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::EXIT, nulldata);
46 PostMsg(pMsg);
47 // Wait for the thread to terminate, it is deleted automatically
48 m_Thread->join();
49 }
50 catch (const std::exception&) { } // Swallow any exception.
telsoa015307bc12018-03-09 13:51:08 +000051}
52
Matteo Martincighe48bdff2018-09-03 13:50:50 +010053template<typename HalVersion>
54void RequestThread<HalVersion>::PostMsg(ArmnnPreparedModel<HalVersion>* model,
55 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& memPools,
56 std::shared_ptr<armnn::InputTensors>& inputTensors,
57 std::shared_ptr<armnn::OutputTensors>& outputTensors,
58 const ::android::sp<IExecutionCallback>& callback)
telsoa015307bc12018-03-09 13:51:08 +000059{
60 ALOGV("RequestThread::PostMsg(...)");
61 auto data = std::make_shared<AsyncExecuteData>(model,
62 memPools,
63 inputTensors,
64 outputTensors,
65 callback);
66 auto pMsg = std::make_shared<ThreadMsg>(ThreadMsgType::REQUEST, data);
67 PostMsg(pMsg);
68}
69
Matteo Martincighe48bdff2018-09-03 13:50:50 +010070template<typename HalVersion>
71void RequestThread<HalVersion>::PostMsg(std::shared_ptr<ThreadMsg>& pMsg)
telsoa015307bc12018-03-09 13:51:08 +000072{
73 ALOGV("RequestThread::PostMsg(pMsg)");
74 // Add a message to the queue and notify the request thread
75 std::unique_lock<std::mutex> lock(m_Mutex);
76 m_Queue.push(pMsg);
77 m_Cv.notify_one();
78}
79
Matteo Martincighe48bdff2018-09-03 13:50:50 +010080template<typename HalVersion>
81void RequestThread<HalVersion>::Process()
telsoa015307bc12018-03-09 13:51:08 +000082{
83 ALOGV("RequestThread::Process()");
84 while (true)
85 {
86 std::shared_ptr<ThreadMsg> pMsg(nullptr);
87 {
88 // Wait for a message to be added to the queue
89 // This is in a separate scope to minimise the lifetime of the lock
90 std::unique_lock<std::mutex> lock(m_Mutex);
91 while (m_Queue.empty())
92 {
93 m_Cv.wait(lock);
94 }
95 // get the message to process from the front of the queue
96 pMsg = m_Queue.front();
97 m_Queue.pop();
98 }
99
100 switch (pMsg->type)
101 {
102 case ThreadMsgType::REQUEST:
103 {
104 ALOGV("RequestThread::Process() - request");
105 // invoke the asynchronous execution method
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100106 ArmnnPreparedModel<HalVersion>* model = pMsg->data->m_Model;
telsoa015307bc12018-03-09 13:51:08 +0000107 model->ExecuteGraph(pMsg->data->m_MemPools,
108 pMsg->data->m_InputTensors,
109 pMsg->data->m_OutputTensors,
110 pMsg->data->m_callback);
111 break;
112 }
113
114 case ThreadMsgType::EXIT:
115 {
116 ALOGV("RequestThread::Process() - exit");
117 // delete all remaining messages (there should not be any)
118 std::unique_lock<std::mutex> lock(m_Mutex);
119 while (!m_Queue.empty())
120 {
121 m_Queue.pop();
122 }
123 return;
124 }
125
126 default:
127 // this should be unreachable
128 ALOGE("RequestThread::Process() - invalid message type");
129 BOOST_ASSERT_MSG(false, "ArmNN: RequestThread: invalid message type");
130 }
131 }
132}
133
arovir01b0717b52018-09-05 17:03:25 +0100134///
135/// Class template specializations
136///
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100137
arovir01b0717b52018-09-05 17:03:25 +0100138template class RequestThread<hal_1_0::HalPolicy>;
139
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100140#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100141template class RequestThread<hal_1_1::HalPolicy>;
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100142#endif
143
arovir01b0717b52018-09-05 17:03:25 +0100144} // namespace armnn_driver