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