1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "mmessage_pool.h"
17 
18 #include <cstdio>
19 #include <cstring>
20 #include <cstdlib>
21 #include <climits>
22 
23 #include "securec.h"
24 #include "fsm_common.h"
25 #include "media_log.h"
26 
27 using namespace OHOS;
28 
29 const char DEFAULT_MSG_ID = -1;
30 
MMessagePool(std::string name)31 MMessagePool::MMessagePool(std::string name) : m_name(name)
32 {
33     m_msgFreeList.clear();
34     m_msgBusyList.clear();
35 }
36 
~MMessagePool()37 MMessagePool::~MMessagePool()
38 {
39     Deinit();
40 }
41 
Init(uint32_t msgNum,uint32_t msgPayloadLen)42 int32_t MMessagePool::Init(uint32_t msgNum, uint32_t msgPayloadLen)
43 {
44     if (m_isInit == true) {
45         MEDIA_ERR_LOG("MMessagePool has inited");
46         return HI_SUCCESS;
47     }
48     if (msgNum == 0 || msgPayloadLen == 0) {
49         MEDIA_ERR_LOG("msgpool init msgNum or msgPayloadLen 0 err");
50         return HI_FAILURE;
51     }
52     if ((msgNum >= (INT_MAX / msgPayloadLen)) || (msgNum >= (INT_MAX / sizeof(MsgInfo))) ||
53         (msgNum >= (INT_MAX / sizeof(MsgPrivateInfo)))) {
54         MEDIA_ERR_LOG("interger malloc overflow");
55         return HI_FAILURE;
56     }
57     if (pthread_mutex_init(&m_listLock, nullptr) != HI_SUCCESS) {
58         MEDIA_ERR_LOG("pthread_mutex_init err");
59         return HI_FAILURE;
60     }
61 
62     if (MallocMemPool(msgNum, msgPayloadLen) != HI_SUCCESS) {
63         MEDIA_ERR_LOG("MallocMemPool err");
64         (void)pthread_mutex_destroy(&m_listLock);
65         return HI_FAILURE;
66     }
67 
68     for (uint32_t i = 0; i < msgNum; i++) {
69         m_msgMemList[i].msgData = (msgPayloadLen > 0) ?
70             static_cast<void *>(&m_msgPayloadList[i * msgPayloadLen]) : nullptr;
71         m_msgMemList[i].privDate = static_cast<void *>(&m_msgPrivList[i]);
72         m_msgMemList[i].what = DEFAULT_MSG_ID;
73         m_msgFreeList.push_back(&m_msgMemList[i]);
74     }
75 
76     m_maxMsgNum = msgNum;
77     m_maxMsgPayloadLen = msgPayloadLen;
78     m_isInit = true;
79     return HI_SUCCESS;
80 }
81 
Deinit()82 int32_t MMessagePool::Deinit()
83 {
84     if (m_isInit != true) {
85         MEDIA_INFO_LOG( "MMessagePool not inited");
86         return HI_SUCCESS;
87     }
88     if (!m_msgBusyList.empty()) {
89         MEDIA_ERR_LOG(
90                       "pool: %s: %u msgs not released", m_name.c_str(), (uint32_t)m_msgBusyList.size());
91     }
92 
93     if (m_msgFreeList.size() != m_maxMsgNum) {
94         MEDIA_ERR_LOG("free msg size not same with inited");
95     }
96 
97     std::list<MsgInfo *>::iterator msgIter = m_msgFreeList.begin();
98     while (msgIter != m_msgFreeList.end()) {
99         msgIter = m_msgFreeList.erase(msgIter);
100     }
101     m_msgFreeList.clear();
102     m_msgBusyList.clear();
103     FreeMemPool();
104     (void)pthread_mutex_destroy(&m_listLock);
105     m_isInit = false;
106     return HI_SUCCESS;
107 }
108 
GetEmptyMsg()109 MsgInfo *MMessagePool::GetEmptyMsg()
110 {
111     MsgInfo *msg = nullptr;
112 
113     FSM_LOCK(m_listLock);
114 
115     std::list<MsgInfo *>::iterator msgIter = m_msgFreeList.begin();
116     if (msgIter != m_msgFreeList.end()) {
117         msg = *msgIter;
118         m_msgFreeList.erase(msgIter);
119     }
120 
121     if (msg == nullptr || msg->privDate == nullptr) {
122         MEDIA_ERR_LOG("getMsg failed, msg pool is empty");
123         FSM_UNLOCK(m_listLock);
124         return nullptr;
125     }
126     if (msg->privDate == nullptr) {
127         MEDIA_ERR_LOG("msg->privDate is NULL");
128         FSM_UNLOCK(m_listLock);
129         return nullptr;
130     }
131     if (memset_s(msg->privDate, sizeof(MsgPrivateInfo), 0x00, sizeof(MsgPrivateInfo)) != EOK) {
132         MEDIA_ERR_LOG("memset failed");
133         FSM_UNLOCK(m_listLock);
134         return nullptr;
135     }
136     msg->what = DEFAULT_MSG_ID;
137     msg->msgDataLen = m_maxMsgPayloadLen;
138 
139     m_msgBusyList.push_back(msg);
140 
141     FSM_UNLOCK(m_listLock);
142 
143     return msg;
144 }
145 
GetMsg(const MsgInfo & msg)146 MsgInfo *MMessagePool::GetMsg(const MsgInfo &msg)
147 {
148     MsgInfo *msgInfo = nullptr;
149 
150     if (msg.msgDataLen > m_maxMsgPayloadLen) {
151         MEDIA_ERR_LOG("getMsg input msg len: %u large than maxlen: %u",
152                       msg.msgDataLen, m_maxMsgPayloadLen);
153         return nullptr;
154     }
155 
156     FSM_LOCK(m_listLock);
157 
158     std::list<MsgInfo *>::iterator msgIter = m_msgFreeList.begin();
159     if (msgIter != m_msgFreeList.end()) {
160         msgInfo = *msgIter;
161 
162         if (msgInfo->privDate == nullptr ||
163             memset_s(msgInfo->privDate, sizeof(MsgPrivateInfo), 0x00, sizeof(MsgPrivateInfo)) != EOK) {
164             MEDIA_ERR_LOG("memset_s failed");
165             FSM_UNLOCK(m_listLock);
166             return nullptr;
167         }
168 
169         msgInfo->what = msg.what;
170         msgInfo->arg1 = msg.arg1;
171         msgInfo->arg2 = msg.arg2;
172 
173         if (msg.msgDataLen > 0 && msg.msgData != nullptr && msgInfo->msgData != nullptr) {
174             if (memcpy_s(msgInfo->msgData, m_maxMsgPayloadLen, msg.msgData, msg.msgDataLen) != EOK) {
175                 MEDIA_ERR_LOG("memset_s failed");
176                 FSM_UNLOCK(m_listLock);
177                 return nullptr;
178             }
179             msgInfo->msgDataLen = msg.msgDataLen;
180         }
181 
182         m_msgFreeList.erase(msgIter);
183     }
184 
185     if (msgInfo == nullptr) {
186         MEDIA_ERR_LOG("pool: %s is empty, left size: %zd busy size: %zd",
187             m_name.c_str(), m_msgFreeList.size(), m_msgBusyList.size());
188         FSM_UNLOCK(m_listLock);
189         return nullptr;
190     }
191 
192     m_msgBusyList.push_back(msgInfo);
193 
194     FSM_UNLOCK(m_listLock);
195 
196     return msgInfo;
197 }
198 
PutMsg(MsgInfo & msg)199 int32_t MMessagePool::PutMsg(MsgInfo &msg)
200 {
201     bool isFound = false;
202 
203     FSM_LOCK(m_listLock);
204 
205     std::list<MsgInfo *>::iterator msgIter = m_msgBusyList.begin();
206     for (; msgIter != m_msgBusyList.end(); msgIter++) {
207         MsgInfo *msgInfo = *msgIter;
208         if (msgInfo == &msg) {
209             isFound = true;
210             break;
211         }
212     }
213 
214     if (!isFound) {
215         MEDIA_ERR_LOG("pool: %s putMsg invalid msg", m_name.c_str());
216         FSM_UNLOCK(m_listLock);
217         return HI_FAILURE;
218     }
219 
220     m_msgBusyList.erase(msgIter);
221 
222     msg.what = DEFAULT_MSG_ID;
223 
224     m_msgFreeList.push_back(&msg);
225 
226     FSM_UNLOCK(m_listLock);
227     return HI_SUCCESS;
228 }
229 
Dump()230 void MMessagePool::Dump()
231 {
232     FSM_LOCK(m_listLock);
233     MEDIA_INFO_LOG( "pool: %s, free msg: %zu, busy msg: %zu",
234         m_name.c_str(), m_msgFreeList.size(), m_msgBusyList.size());
235     std::list<MsgInfo *>::iterator msgIter = m_msgBusyList.begin();
236     for (; msgIter != m_msgBusyList.end(); msgIter++) {
237         MEDIA_INFO_LOG( "msg id: %d", (*msgIter)->what);
238     }
239     FSM_UNLOCK(m_listLock);
240 }
241 
MallocMemPool(uint32_t msgNum,uint32_t msgPayloadLen)242 int32_t MMessagePool::MallocMemPool(uint32_t msgNum, uint32_t msgPayloadLen)
243 {
244     m_msgPayloadList = static_cast<uint8_t *>(malloc(msgPayloadLen * msgNum));
245     if (m_msgPayloadList == nullptr) {
246         MEDIA_ERR_LOG("alloc msg payload list size failed");
247         return HI_FAILURE;
248     }
249 
250     m_msgMemList = static_cast<MsgInfo *>(malloc(sizeof(MsgInfo) * msgNum));
251     if (m_msgMemList == nullptr) {
252         MEDIA_ERR_LOG("alloc msg list num: %u failed", msgNum);
253         free(m_msgPayloadList);
254         m_msgPayloadList = nullptr;
255         return HI_FAILURE;
256     }
257 
258     m_msgPrivList = static_cast<MsgPrivateInfo *>(malloc(sizeof(MsgPrivateInfo) * msgNum));
259     if (m_msgPrivList == nullptr) {
260         MEDIA_ERR_LOG("alloc msg private list num: %u failed", msgNum);
261         free(m_msgMemList);
262         m_msgMemList = nullptr;
263         free(m_msgPayloadList);
264         m_msgPayloadList = nullptr;
265         return HI_FAILURE;
266     }
267 
268     if (memset_s(m_msgPrivList, sizeof(MsgPrivateInfo) * msgNum, 0x00, (sizeof(MsgPrivateInfo) * msgNum)) != EOK ||
269         memset_s(m_msgPayloadList, msgPayloadLen * msgNum, 0x00, (msgPayloadLen * msgNum)) != EOK ||
270             memset_s(m_msgMemList, sizeof(MsgInfo) * msgNum, 0x00, (sizeof(MsgInfo) * msgNum)) != EOK) {
271         MEDIA_ERR_LOG("memset_s failed");
272         free(m_msgPrivList);
273         m_msgPrivList = nullptr;
274         free(m_msgMemList);
275         m_msgMemList = nullptr;
276         free(m_msgPayloadList);
277         m_msgPayloadList = nullptr;
278         return HI_FAILURE;
279     }
280     return HI_SUCCESS;
281 }
282 
FreeMemPool()283 void MMessagePool::FreeMemPool()
284 {
285     if (m_msgPrivList != nullptr) {
286         free(m_msgPrivList);
287         m_msgPrivList = nullptr;
288     }
289 
290     if (m_msgPayloadList != nullptr) {
291         free(m_msgPayloadList);
292         m_msgPayloadList = nullptr;
293     }
294 
295     if (m_msgMemList != nullptr) {
296         free(m_msgMemList);
297         m_msgMemList = nullptr;
298     }
299 }
300