1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci#include "file_descriptor.h" 16cc290419Sopenharmony_ci#ifndef HDC_HOST 17cc290419Sopenharmony_ci#include <sys/epoll.h> 18cc290419Sopenharmony_ci#endif 19cc290419Sopenharmony_ci 20cc290419Sopenharmony_cinamespace Hdc { 21cc290419Sopenharmony_cistatic const int SECONDS_TIMEOUT = 5; 22cc290419Sopenharmony_ci 23cc290419Sopenharmony_ciHdcFileDescriptor::HdcFileDescriptor(uv_loop_t *loopIn, int fdToRead, void *callerContextIn, 24cc290419Sopenharmony_ci CallBackWhenRead callbackReadIn, CmdResultCallback callbackFinishIn, 25cc290419Sopenharmony_ci bool interactiveShell) 26cc290419Sopenharmony_ci{ 27cc290419Sopenharmony_ci loop = loopIn; 28cc290419Sopenharmony_ci workContinue = true; 29cc290419Sopenharmony_ci callbackFinish = callbackFinishIn; 30cc290419Sopenharmony_ci callbackRead = callbackReadIn; 31cc290419Sopenharmony_ci fdIO = fdToRead; 32cc290419Sopenharmony_ci refIO = 0; 33cc290419Sopenharmony_ci isInteractive = interactiveShell; 34cc290419Sopenharmony_ci callerContext = callerContextIn; 35cc290419Sopenharmony_ci if (isInteractive) { 36cc290419Sopenharmony_ci std::thread([this]() { 37cc290419Sopenharmony_ci HdcFileDescriptor::IOWriteThread(this); 38cc290419Sopenharmony_ci }).detach(); 39cc290419Sopenharmony_ci } 40cc290419Sopenharmony_ci} 41cc290419Sopenharmony_ci 42cc290419Sopenharmony_ciHdcFileDescriptor::~HdcFileDescriptor() 43cc290419Sopenharmony_ci{ 44cc290419Sopenharmony_ci workContinue = false; 45cc290419Sopenharmony_ci if (isInteractive) { 46cc290419Sopenharmony_ci NotifyWrite(); 47cc290419Sopenharmony_ci uv_sleep(MILL_SECONDS); 48cc290419Sopenharmony_ci } 49cc290419Sopenharmony_ci} 50cc290419Sopenharmony_ci 51cc290419Sopenharmony_cibool HdcFileDescriptor::ReadyForRelease() 52cc290419Sopenharmony_ci{ 53cc290419Sopenharmony_ci return refIO == 0; 54cc290419Sopenharmony_ci} 55cc290419Sopenharmony_ci 56cc290419Sopenharmony_ci// just tryCloseFdIo = true, callback will be effect 57cc290419Sopenharmony_civoid HdcFileDescriptor::StopWorkOnThread(bool tryCloseFdIo, std::function<void()> closeFdCallback) 58cc290419Sopenharmony_ci{ 59cc290419Sopenharmony_ci workContinue = false; 60cc290419Sopenharmony_ci if (isInteractive) { 61cc290419Sopenharmony_ci NotifyWrite(); 62cc290419Sopenharmony_ci } 63cc290419Sopenharmony_ci 64cc290419Sopenharmony_ci callbackCloseFd = closeFdCallback; 65cc290419Sopenharmony_ci if (tryCloseFdIo && refIO > 0) { 66cc290419Sopenharmony_ci if (callbackCloseFd != nullptr) { 67cc290419Sopenharmony_ci callbackCloseFd(); 68cc290419Sopenharmony_ci } 69cc290419Sopenharmony_ci } 70cc290419Sopenharmony_ci} 71cc290419Sopenharmony_ci 72cc290419Sopenharmony_civoid HdcFileDescriptor::FileIOOnThread(CtxFileIO *ctxIO, int bufSize) 73cc290419Sopenharmony_ci{ 74cc290419Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INIF 75cc290419Sopenharmony_ci mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); 76cc290419Sopenharmony_ci mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); 77cc290419Sopenharmony_ci#endif 78cc290419Sopenharmony_ci HdcFileDescriptor *thisClass = ctxIO->thisClass; 79cc290419Sopenharmony_ci uint8_t *buf = ctxIO->bufIO; 80cc290419Sopenharmony_ci bool bFinish = false; 81cc290419Sopenharmony_ci bool fetalFinish = false; 82cc290419Sopenharmony_ci ssize_t nBytes; 83cc290419Sopenharmony_ci#ifndef HDC_HOST 84cc290419Sopenharmony_ci constexpr int epollSize = 1; 85cc290419Sopenharmony_ci int epfd = epoll_create(epollSize); 86cc290419Sopenharmony_ci struct epoll_event ev; 87cc290419Sopenharmony_ci struct epoll_event events[epollSize]; 88cc290419Sopenharmony_ci ev.data.fd = thisClass->fdIO; 89cc290419Sopenharmony_ci ev.events = EPOLLIN | EPOLLET; 90cc290419Sopenharmony_ci epoll_ctl(epfd, EPOLL_CTL_ADD, thisClass->fdIO, &ev); 91cc290419Sopenharmony_ci#endif 92cc290419Sopenharmony_ci while (true) { 93cc290419Sopenharmony_ci if (thisClass->workContinue == false) { 94cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "FileIOOnThread fdIO:%d workContinue false", thisClass->fdIO); 95cc290419Sopenharmony_ci bFinish = true; 96cc290419Sopenharmony_ci break; 97cc290419Sopenharmony_ci } 98cc290419Sopenharmony_ci 99cc290419Sopenharmony_ci if (memset_s(buf, bufSize, 0, bufSize) != EOK) { 100cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "FileIOOnThread buf memset_s fail."); 101cc290419Sopenharmony_ci bFinish = true; 102cc290419Sopenharmony_ci break; 103cc290419Sopenharmony_ci } 104cc290419Sopenharmony_ci#ifndef HDC_HOST 105cc290419Sopenharmony_ci int rc = epoll_wait(epfd, events, epollSize, SECONDS_TIMEOUT * TIME_BASE); 106cc290419Sopenharmony_ci#else 107cc290419Sopenharmony_ci struct timeval timeout; 108cc290419Sopenharmony_ci timeout.tv_sec = SECONDS_TIMEOUT; 109cc290419Sopenharmony_ci timeout.tv_usec = 0; 110cc290419Sopenharmony_ci fd_set rset; 111cc290419Sopenharmony_ci FD_ZERO(&rset); 112cc290419Sopenharmony_ci FD_SET(thisClass->fdIO, &rset); 113cc290419Sopenharmony_ci int rc = select(thisClass->fdIO + 1, &rset, nullptr, nullptr, &timeout); 114cc290419Sopenharmony_ci#endif 115cc290419Sopenharmony_ci if (rc < 0) { 116cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "FileIOOnThread select or epoll_wait fdIO:%d error:%d", 117cc290419Sopenharmony_ci thisClass->fdIO, errno); 118cc290419Sopenharmony_ci if (errno == EINTR || errno == EAGAIN) { 119cc290419Sopenharmony_ci continue; 120cc290419Sopenharmony_ci } 121cc290419Sopenharmony_ci bFinish = true; 122cc290419Sopenharmony_ci break; 123cc290419Sopenharmony_ci } else if (rc == 0) { 124cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FileIOOnThread select rc = 0, timeout."); 125cc290419Sopenharmony_ci continue; 126cc290419Sopenharmony_ci } 127cc290419Sopenharmony_ci nBytes = 0; 128cc290419Sopenharmony_ci#ifndef HDC_HOST 129cc290419Sopenharmony_ci uint32_t event = events[0].events; 130cc290419Sopenharmony_ci if ((event & EPOLLIN) && (thisClass->fdIO > 0)) { 131cc290419Sopenharmony_ci nBytes = read(thisClass->fdIO, buf, bufSize); 132cc290419Sopenharmony_ci } 133cc290419Sopenharmony_ci if ((event & EPOLLERR) || (event & EPOLLHUP) || (event & EPOLLRDHUP)) { 134cc290419Sopenharmony_ci bFinish = true; 135cc290419Sopenharmony_ci fetalFinish = true; 136cc290419Sopenharmony_ci if ((nBytes > 0) && !thisClass->callbackRead(thisClass->callerContext, buf, nBytes)) { 137cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FileIOOnThread fdIO:%d callbackRead false", thisClass->fdIO); 138cc290419Sopenharmony_ci } 139cc290419Sopenharmony_ci break; 140cc290419Sopenharmony_ci } 141cc290419Sopenharmony_ci if (nBytes < 0 && (errno == EINTR || errno == EAGAIN)) { 142cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FileIOOnThread fdIO:%d read interrupt", thisClass->fdIO); 143cc290419Sopenharmony_ci continue; 144cc290419Sopenharmony_ci } 145cc290419Sopenharmony_ci if (nBytes > 0) { 146cc290419Sopenharmony_ci if (!thisClass->callbackRead(thisClass->callerContext, buf, nBytes)) { 147cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FileIOOnThread fdIO:%d callbackRead false", thisClass->fdIO); 148cc290419Sopenharmony_ci bFinish = true; 149cc290419Sopenharmony_ci break; 150cc290419Sopenharmony_ci } 151cc290419Sopenharmony_ci continue; 152cc290419Sopenharmony_ci } else { 153cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "FileIOOnThread fd:%d nBytes:%d errno:%d", 154cc290419Sopenharmony_ci thisClass->fdIO, nBytes, errno); 155cc290419Sopenharmony_ci bFinish = true; 156cc290419Sopenharmony_ci fetalFinish = true; 157cc290419Sopenharmony_ci break; 158cc290419Sopenharmony_ci } 159cc290419Sopenharmony_ci#else 160cc290419Sopenharmony_ci if (thisClass->fdIO > 0) { 161cc290419Sopenharmony_ci nBytes = read(thisClass->fdIO, buf, bufSize); 162cc290419Sopenharmony_ci } 163cc290419Sopenharmony_ci if (nBytes < 0 && (errno == EINTR || errno == EAGAIN)) { 164cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FileIOOnThread fdIO:%d read interrupt", thisClass->fdIO); 165cc290419Sopenharmony_ci continue; 166cc290419Sopenharmony_ci } 167cc290419Sopenharmony_ci if (nBytes > 0) { 168cc290419Sopenharmony_ci if (!thisClass->callbackRead(thisClass->callerContext, buf, nBytes)) { 169cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "FileIOOnThread fdIO:%d callbackRead false", thisClass->fdIO); 170cc290419Sopenharmony_ci bFinish = true; 171cc290419Sopenharmony_ci break; 172cc290419Sopenharmony_ci } 173cc290419Sopenharmony_ci continue; 174cc290419Sopenharmony_ci } else { 175cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "FileIOOnThread fd:%d nBytes:%d errno:%d", 176cc290419Sopenharmony_ci thisClass->fdIO, nBytes, errno); 177cc290419Sopenharmony_ci bFinish = true; 178cc290419Sopenharmony_ci fetalFinish = true; 179cc290419Sopenharmony_ci break; 180cc290419Sopenharmony_ci } 181cc290419Sopenharmony_ci#endif 182cc290419Sopenharmony_ci } 183cc290419Sopenharmony_ci#ifndef HDC_HOST 184cc290419Sopenharmony_ci if ((thisClass->fdIO > 0) && (epoll_ctl(epfd, EPOLL_CTL_DEL, thisClass->fdIO, nullptr) == -1)) { 185cc290419Sopenharmony_ci WRITE_LOG(LOG_INFO, "EPOLL_CTL_DEL fail fd:%d epfd:%d errno:%d", 186cc290419Sopenharmony_ci thisClass->fdIO, epfd, errno); 187cc290419Sopenharmony_ci } 188cc290419Sopenharmony_ci close(epfd); 189cc290419Sopenharmony_ci#endif 190cc290419Sopenharmony_ci if (buf != nullptr) { 191cc290419Sopenharmony_ci delete[] buf; 192cc290419Sopenharmony_ci buf = nullptr; 193cc290419Sopenharmony_ci } 194cc290419Sopenharmony_ci delete ctxIO; 195cc290419Sopenharmony_ci 196cc290419Sopenharmony_ci --thisClass->refIO; 197cc290419Sopenharmony_ci if (bFinish) { 198cc290419Sopenharmony_ci thisClass->workContinue = false; 199cc290419Sopenharmony_ci thisClass->callbackFinish(thisClass->callerContext, fetalFinish, STRING_EMPTY); 200cc290419Sopenharmony_ci } 201cc290419Sopenharmony_ci} 202cc290419Sopenharmony_ci 203cc290419Sopenharmony_ciint HdcFileDescriptor::LoopReadOnThread() 204cc290419Sopenharmony_ci{ 205cc290419Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INIF 206cc290419Sopenharmony_ci mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); 207cc290419Sopenharmony_ci mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); 208cc290419Sopenharmony_ci#endif 209cc290419Sopenharmony_ci int readMax = Base::GetMaxBufSizeStable() * 1.2; // 120% of max buf size, use stable size to avoid no buf. 210cc290419Sopenharmony_ci auto contextIO = new(std::nothrow) CtxFileIO(); 211cc290419Sopenharmony_ci auto buf = new(std::nothrow) uint8_t[readMax](); 212cc290419Sopenharmony_ci if (!contextIO || !buf) { 213cc290419Sopenharmony_ci if (contextIO) { 214cc290419Sopenharmony_ci delete contextIO; 215cc290419Sopenharmony_ci } 216cc290419Sopenharmony_ci if (buf) { 217cc290419Sopenharmony_ci delete[] buf; 218cc290419Sopenharmony_ci } 219cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Memory alloc failed"); 220cc290419Sopenharmony_ci callbackFinish(callerContext, true, "Memory alloc failed"); 221cc290419Sopenharmony_ci return -1; 222cc290419Sopenharmony_ci } 223cc290419Sopenharmony_ci contextIO->bufIO = buf; 224cc290419Sopenharmony_ci contextIO->thisClass = this; 225cc290419Sopenharmony_ci ++refIO; 226cc290419Sopenharmony_ci std::thread([contextIO, readMax]() { 227cc290419Sopenharmony_ci HdcFileDescriptor::FileIOOnThread(contextIO, readMax); 228cc290419Sopenharmony_ci }).detach(); 229cc290419Sopenharmony_ci return 0; 230cc290419Sopenharmony_ci} 231cc290419Sopenharmony_ci 232cc290419Sopenharmony_cibool HdcFileDescriptor::StartWorkOnThread() 233cc290419Sopenharmony_ci{ 234cc290419Sopenharmony_ci if (LoopReadOnThread() < 0) { 235cc290419Sopenharmony_ci return false; 236cc290419Sopenharmony_ci } 237cc290419Sopenharmony_ci return true; 238cc290419Sopenharmony_ci} 239cc290419Sopenharmony_ci 240cc290419Sopenharmony_ciint HdcFileDescriptor::Write(uint8_t *data, int size) 241cc290419Sopenharmony_ci{ 242cc290419Sopenharmony_ci if (size > static_cast<int>(HDC_BUF_MAX_BYTES - 1)) { 243cc290419Sopenharmony_ci size = static_cast<int>(HDC_BUF_MAX_BYTES - 1); 244cc290419Sopenharmony_ci } 245cc290419Sopenharmony_ci if (size <= 0) { 246cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "Write failed, size:%d", size); 247cc290419Sopenharmony_ci return -1; 248cc290419Sopenharmony_ci } 249cc290419Sopenharmony_ci auto buf = new(std::nothrow) uint8_t[size]; 250cc290419Sopenharmony_ci if (!buf) { 251cc290419Sopenharmony_ci return -1; 252cc290419Sopenharmony_ci } 253cc290419Sopenharmony_ci if (memcpy_s(buf, size, data, size) != EOK) { 254cc290419Sopenharmony_ci delete[] buf; 255cc290419Sopenharmony_ci return -1; 256cc290419Sopenharmony_ci } 257cc290419Sopenharmony_ci return WriteWithMem(buf, size); 258cc290419Sopenharmony_ci} 259cc290419Sopenharmony_ci 260cc290419Sopenharmony_ci// Data's memory must be Malloc, and the callback FREE after this function is completed 261cc290419Sopenharmony_ciint HdcFileDescriptor::WriteWithMem(uint8_t *data, int size) 262cc290419Sopenharmony_ci{ 263cc290419Sopenharmony_ci#ifdef CONFIG_USE_JEMALLOC_DFX_INIF 264cc290419Sopenharmony_ci mallopt(M_DELAYED_FREE, M_DELAYED_FREE_DISABLE); 265cc290419Sopenharmony_ci mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_DISABLE); 266cc290419Sopenharmony_ci#endif 267cc290419Sopenharmony_ci auto contextIO = new(std::nothrow) CtxFileIO(); 268cc290419Sopenharmony_ci if (!contextIO) { 269cc290419Sopenharmony_ci delete[] data; 270cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "Memory alloc failed"); 271cc290419Sopenharmony_ci callbackFinish(callerContext, true, "Memory alloc failed"); 272cc290419Sopenharmony_ci return -1; 273cc290419Sopenharmony_ci } 274cc290419Sopenharmony_ci contextIO->bufIO = data; 275cc290419Sopenharmony_ci contextIO->size = static_cast<size_t>(size); 276cc290419Sopenharmony_ci contextIO->thisClass = this; 277cc290419Sopenharmony_ci PushWrite(contextIO); 278cc290419Sopenharmony_ci NotifyWrite(); 279cc290419Sopenharmony_ci return size; 280cc290419Sopenharmony_ci} 281cc290419Sopenharmony_ci 282cc290419Sopenharmony_civoid HdcFileDescriptor::IOWriteThread(void *object) 283cc290419Sopenharmony_ci{ 284cc290419Sopenharmony_ci HdcFileDescriptor *hfd = reinterpret_cast<HdcFileDescriptor *>(object); 285cc290419Sopenharmony_ci while (hfd->workContinue) { 286cc290419Sopenharmony_ci hfd->HandleWrite(); 287cc290419Sopenharmony_ci hfd->WaitWrite(); 288cc290419Sopenharmony_ci } 289cc290419Sopenharmony_ci} 290cc290419Sopenharmony_ci 291cc290419Sopenharmony_civoid HdcFileDescriptor::PushWrite(CtxFileIO *cfio) 292cc290419Sopenharmony_ci{ 293cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(writeMutex); 294cc290419Sopenharmony_ci writeQueue.push(cfio); 295cc290419Sopenharmony_ci} 296cc290419Sopenharmony_ci 297cc290419Sopenharmony_ciCtxFileIO *HdcFileDescriptor::PopWrite() 298cc290419Sopenharmony_ci{ 299cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(writeMutex); 300cc290419Sopenharmony_ci CtxFileIO *cfio = nullptr; 301cc290419Sopenharmony_ci if (!writeQueue.empty()) { 302cc290419Sopenharmony_ci cfio = writeQueue.front(); 303cc290419Sopenharmony_ci writeQueue.pop(); 304cc290419Sopenharmony_ci } 305cc290419Sopenharmony_ci return cfio; 306cc290419Sopenharmony_ci} 307cc290419Sopenharmony_ci 308cc290419Sopenharmony_civoid HdcFileDescriptor::NotifyWrite() 309cc290419Sopenharmony_ci{ 310cc290419Sopenharmony_ci writeCond.notify_one(); 311cc290419Sopenharmony_ci} 312cc290419Sopenharmony_ci 313cc290419Sopenharmony_civoid HdcFileDescriptor::WaitWrite() 314cc290419Sopenharmony_ci{ 315cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(writeMutex); 316cc290419Sopenharmony_ci writeCond.wait_for(lock, std::chrono::seconds(WAIT_SECONDS), [&]() { 317cc290419Sopenharmony_ci return !writeQueue.empty() || !workContinue; 318cc290419Sopenharmony_ci }); 319cc290419Sopenharmony_ci} 320cc290419Sopenharmony_ci 321cc290419Sopenharmony_civoid HdcFileDescriptor::HandleWrite() 322cc290419Sopenharmony_ci{ 323cc290419Sopenharmony_ci CtxFileIO *cfio = nullptr; 324cc290419Sopenharmony_ci while ((cfio = PopWrite()) != nullptr) { 325cc290419Sopenharmony_ci CtxFileIOWrite(cfio); 326cc290419Sopenharmony_ci delete cfio; 327cc290419Sopenharmony_ci } 328cc290419Sopenharmony_ci} 329cc290419Sopenharmony_ci 330cc290419Sopenharmony_civoid HdcFileDescriptor::CtxFileIOWrite(CtxFileIO *cfio) 331cc290419Sopenharmony_ci{ 332cc290419Sopenharmony_ci std::unique_lock<std::mutex> lock(writeMutex); 333cc290419Sopenharmony_ci uint8_t *buf = cfio->bufIO; 334cc290419Sopenharmony_ci uint8_t *data = buf; 335cc290419Sopenharmony_ci size_t cnt = cfio->size; 336cc290419Sopenharmony_ci constexpr int intrmax = 1000; 337cc290419Sopenharmony_ci int intrcnt = 0; 338cc290419Sopenharmony_ci while (cnt > 0) { 339cc290419Sopenharmony_ci ssize_t rc = write(fdIO, data, cnt); 340cc290419Sopenharmony_ci if (rc < 0) { 341cc290419Sopenharmony_ci if (errno == EINTR || errno == EAGAIN) { 342cc290419Sopenharmony_ci if (++intrcnt > intrmax) { 343cc290419Sopenharmony_ci WRITE_LOG(LOG_WARN, "CtxFileIOWrite fdIO:%d interrupt errno:%d", fdIO, errno); 344cc290419Sopenharmony_ci intrcnt = 0; 345cc290419Sopenharmony_ci } 346cc290419Sopenharmony_ci continue; 347cc290419Sopenharmony_ci } else { 348cc290419Sopenharmony_ci WRITE_LOG(LOG_FATAL, "CtxFileIOWrite fdIO:%d rc:%d error:%d", fdIO, rc, errno); 349cc290419Sopenharmony_ci break; 350cc290419Sopenharmony_ci } 351cc290419Sopenharmony_ci } 352cc290419Sopenharmony_ci data += rc; 353cc290419Sopenharmony_ci cnt -= static_cast<size_t>(rc); 354cc290419Sopenharmony_ci } 355cc290419Sopenharmony_ci delete[] buf; 356cc290419Sopenharmony_ci} 357cc290419Sopenharmony_ci} // namespace Hdc 358