1 /*
2 * Copyright (c) 2023 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 "nncompiled_cache.h"
17
18 #include <unistd.h>
19 #include <functional>
20 #include <memory>
21 #include <limits>
22 #include <cstdio>
23 #include <securec.h>
24
25 #include "utils.h"
26 #include "backend_manager.h"
27 #include "nnbackend.h"
28
29 namespace OHOS {
30 namespace NeuralNetworkRuntime {
31 constexpr int32_t NULL_PTR_LENGTH = 0;
32 constexpr int32_t NUMBER_CACHE_INFO_MEMBERS = 3;
33 constexpr int32_t NUMBER_CACHE_INFO_EXTENSION_MEMBERS = 2;
34 constexpr int32_t HEX_UNIT = 16;
35 constexpr size_t MAX_CACHE_SIZE = 2 * 1024 * 1024; // 限制最大校验内存为2MB
36 constexpr char ROOT_DIR_STR = '/';
37 constexpr char DOUBLE_SLASH_STR[] = "//";
38
Save(const std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches,const std::string & cacheDir,uint32_t version)39 OH_NN_ReturnCode NNCompiledCache::Save(const std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches,
40 const std::string& cacheDir,
41 uint32_t version)
42 {
43 if (caches.empty()) {
44 LOGE("[NNCompiledCache] Save failed, caches is empty.");
45 return OH_NN_INVALID_PARAMETER;
46 }
47
48 if (m_device == nullptr) {
49 LOGE("[NNCompiledCache] Save failed, m_device is empty.");
50 return OH_NN_INVALID_PARAMETER;
51 }
52
53 OH_NN_ReturnCode ret = GenerateCacheFiles(caches, cacheDir, version);
54 if (ret != OH_NN_SUCCESS) {
55 LOGE("[NNCompiledCache] Save failed, error happened when calling GenerateCacheFiles.");
56 return ret;
57 }
58
59 return OH_NN_SUCCESS;
60 }
61
CheckCache(const std::string & cacheDir,uint32_t version,std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches)62 OH_NN_ReturnCode NNCompiledCache::CheckCache(const std::string& cacheDir,
63 uint32_t version,
64 std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches)
65 {
66 if (cacheDir.empty()) {
67 LOGE("[NNCompiledCache] Restore failed, cacheDir is empty.");
68 return OH_NN_INVALID_PARAMETER;
69 }
70
71 if (!caches.empty()) {
72 LOGE("[NNCompiledCache] Restore failed, caches is not empty.");
73 return OH_NN_INVALID_PARAMETER;
74 }
75
76 if (m_device == nullptr) {
77 LOGE("[NNCompiledCache] Restore failed, m_device is empty.");
78 return OH_NN_INVALID_PARAMETER;
79 }
80 return OH_NN_SUCCESS;
81 }
82
Restore(const std::string & cacheDir,uint32_t version,std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches)83 OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir,
84 uint32_t version,
85 std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches)
86 {
87 OH_NN_ReturnCode ret = CheckCache(cacheDir, version, caches);
88 if (ret != OH_NN_SUCCESS) {
89 return ret;
90 }
91
92 std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache";
93 char path[PATH_MAX];
94 if (realpath(cacheInfoPath.c_str(), path) == nullptr) {
95 LOGE("[NNCompiledCache] Restore failed, fail to get the real path of cacheInfoPath.");
96 return OH_NN_INVALID_PARAMETER;
97 }
98 if (access(path, F_OK) != 0) {
99 LOGE("[NNCompiledCache] Restore failed, cacheInfoPath is not exist.");
100 return OH_NN_INVALID_PARAMETER;
101 }
102
103 NNCompiledCacheInfo cacheInfo;
104 ret = CheckCacheInfo(cacheInfo, path);
105 if (ret != OH_NN_SUCCESS) {
106 LOGE("[NNCompiledCache] Restore failed, error happened when calling CheckCacheInfo.");
107 return ret;
108 }
109
110 if (static_cast<int64_t>(version) > cacheInfo.version) {
111 LOGE("[NNCompiledCache] Restore failed, version is not match.");
112 return OH_NN_INVALID_FILE;
113 }
114
115 if (static_cast<int64_t>(version) < cacheInfo.version) {
116 LOGE("[NNCompiledCache] Restore failed, the current version is lower than the cache files, "
117 "please set a higher version.");
118 return OH_NN_OPERATION_FORBIDDEN;
119 }
120
121 for (uint32_t i = 0; i < cacheInfo.fileNumber; ++i) {
122 std::string cacheModelPath = cacheDir + "/" + m_modelName + std::to_string(i) + ".nncache";
123 OHOS::NeuralNetworkRuntime::Buffer modelBuffer;
124 ret = ReadCacheModelFile(cacheModelPath, modelBuffer);
125 if (ret != OH_NN_SUCCESS) {
126 LOGE("[NNCompiledCache] Restore failed, error happened when calling ReadCacheModelFile.");
127 return OH_NN_INVALID_FILE;
128 }
129
130 if (GetCrc16(static_cast<char*>(modelBuffer.data), modelBuffer.length) !=
131 cacheInfo.modelCheckSum[i]) {
132 LOGE("[NNCompiledCache] Restore failed, the cache model file %{public}s has been changed.",
133 cacheModelPath.c_str());
134 munmap(modelBuffer.data, modelBuffer.length);
135 close(modelBuffer.fd);
136 return OH_NN_INVALID_FILE;
137 }
138
139 caches.emplace_back(std::move(modelBuffer));
140 }
141
142 return ret;
143 }
144
SetBackend(size_t backendID)145 OH_NN_ReturnCode NNCompiledCache::SetBackend(size_t backendID)
146 {
147 BackendManager& backendManager = BackendManager::GetInstance();
148 std::shared_ptr<Backend> backend = backendManager.GetBackend(backendID);
149 if (backend == nullptr) {
150 LOGE("[NNCompiledCache] SetBackend failed, backend with backendID %{public}zu is not exist.", backendID);
151 return OH_NN_INVALID_PARAMETER;
152 }
153
154 std::shared_ptr<NNBackend> nnBackend = std::reinterpret_pointer_cast<NNBackend>(backend);
155 m_device = nnBackend->GetDevice();
156 if (m_device == nullptr) {
157 LOGE("[NNCompiledCache] SetBackend failed, device with backendID %{public}zu is not exist.", backendID);
158 return OH_NN_FAILED;
159 }
160
161 m_backendID = backendID;
162 return OH_NN_SUCCESS;
163 }
164
SetModelName(const std::string & modelName)165 void NNCompiledCache::SetModelName(const std::string& modelName)
166 {
167 m_modelName = modelName;
168 }
169
SetIsExceedRamLimit(const bool isExceedRamLimit)170 void NNCompiledCache::SetIsExceedRamLimit(const bool isExceedRamLimit)
171 {
172 m_isExceedRamLimit = isExceedRamLimit;
173 }
174
GenerateCacheFiles(const std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches,const std::string & cacheDir,uint32_t version) const175 OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches,
176 const std::string& cacheDir,
177 uint32_t version) const
178 {
179 const size_t cacheNumber = caches.size();
180 uint32_t cacheSize = NUMBER_CACHE_INFO_MEMBERS + cacheNumber + NUMBER_CACHE_INFO_EXTENSION_MEMBERS;
181 nlohmann::json cacheInfo;
182
183 OH_NN_ReturnCode ret = GenerateCacheModel(caches, cacheInfo, cacheDir, version);
184 if (ret != OH_NN_SUCCESS) {
185 LOGE("[NNCompiledCache] GenerateCacheFiles failed, error happened when calling GenerateCacheModel.");
186 return ret;
187 }
188
189 uint32_t infoCharNumber = cacheSize * sizeof(uint64_t);
190 ret = WriteCacheInfo(infoCharNumber, cacheInfo, cacheDir);
191 if (ret != OH_NN_SUCCESS) {
192 LOGE("[NNCompiledCache] GenerateCacheFiles failed, error happened when calling WriteCacheInfo.");
193 return ret;
194 }
195
196 return OH_NN_SUCCESS;
197 }
198
GenerateCacheModel(const std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches,nlohmann::json & cacheInfo,const std::string & cacheDir,uint32_t version) const199 OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches,
200 nlohmann::json& cacheInfo,
201 const std::string& cacheDir,
202 uint32_t version) const
203 {
204 size_t cacheNumber = caches.size();
205 if (cacheNumber == 0 || cacheNumber > NN_CACHE_FILE_NUMBER_MAX) {
206 LOGE("[NNCompiledCache] Caches size is equal 0 or greater than 100.");
207 return OH_NN_FAILED;
208 }
209
210 cacheInfo["data"]["fileNumber"] = static_cast<int64_t>(cacheNumber);
211 cacheInfo["data"]["version"] = static_cast<int64_t>(version);
212 cacheInfo["data"]["deviceId"] = static_cast<int64_t>(m_backendID); // Should call SetBackend first.
213
214 // standardize the input dir
215 OH_NN_ReturnCode ret = OH_NN_SUCCESS;
216 char path[PATH_MAX];
217 if (realpath(cacheDir.c_str(), path) == nullptr) {
218 LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to get the real path of cacheDir.");
219 return OH_NN_INVALID_PARAMETER;
220 }
221
222 // verify the Standardized path available
223 ret = VerifyCachePath(path);
224 if (ret != OH_NN_SUCCESS) {
225 LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to verify the file path of cacheDir.");
226 return ret;
227 }
228
229 std::string cachePath = path;
230 for (size_t i = 0; i < cacheNumber; ++i) {
231 std::string cacheModelFile = cachePath + "/" + m_modelName + std::to_string(i) + ".nncache";
232 std::ofstream cacheModelStream(cacheModelFile, std::ios::binary | std::ios::out | std::ios::trunc);
233 if (cacheModelStream.fail()) {
234 LOGE("[NNCompiledCache] GenerateCacheModel failed, model cache file is invalid.");
235 return OH_NN_INVALID_PARAMETER;
236 }
237
238 uint64_t checkSum =
239 static_cast<int64_t>(GetCrc16(static_cast<char*>(caches[i].data), caches[i].length));
240 cacheInfo["data"]["modelCheckSum"][i] = checkSum;
241 if (!cacheModelStream.write(static_cast<const char*>(caches[i].data), caches[i].length)) {
242 LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to write cache model.");
243 cacheModelStream.close();
244 return OH_NN_SAVE_CACHE_EXCEPTION;
245 };
246
247 cacheModelStream.close();
248 }
249
250 int currentOpVersion = 0;
251 ret = m_device->ReadOpVersion(currentOpVersion);
252 if (ret != OH_NN_SUCCESS) {
253 LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to read op version.");
254 return ret;
255 }
256 cacheInfo["data"]["opVersion"] = currentOpVersion;
257
258 cacheInfo["data"]["isExceedRamLimit"] = m_isExceedRamLimit ? 1 : 0;
259
260 const size_t dataLength = cacheInfo["data"].dump().length();
261 char cacheInfoData[dataLength + 1];
262 if (strncpy_s(cacheInfoData, dataLength+1, cacheInfo["data"].dump().c_str(), dataLength) != 0) {
263 LOGE("ParseStr failed due to strncpy_s error");
264 return OH_NN_INVALID_PARAMETER;
265 }
266
267 cacheInfo["CheckSum"] = static_cast<int64_t>(CacheInfoGetCrc16(cacheInfoData, dataLength));
268
269 return OH_NN_SUCCESS;
270 }
271
WriteCacheInfo(uint32_t cacheSize,nlohmann::json & cacheInfo,const std::string & cacheDir) const272 OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize,
273 nlohmann::json& cacheInfo,
274 const std::string& cacheDir) const
275 {
276 // standardize the input dir
277 char path[PATH_MAX];
278 if (realpath(cacheDir.c_str(), path) == nullptr) {
279 LOGE("[NNCompiledCache] WriteCacheInfo failed, fail to get the real path of cacheDir.");
280 return OH_NN_INVALID_PARAMETER;
281 }
282
283 // verify the Standardized path available
284 OH_NN_ReturnCode ret = VerifyCachePath(path);
285 if (ret != OH_NN_SUCCESS) {
286 LOGE("[NNCompiledCache] WriteCacheInfo failed, fail to verify the file path of cacheDir.");
287 return ret;
288 }
289
290 std::string cachePath = path;
291 std::string cacheInfoPath = cachePath + "/" + m_modelName + "cache_info.nncache";
292 std::ofstream cacheInfoStream(cacheInfoPath, std::ios::binary | std::ios::out | std::ios::trunc);
293 if (cacheInfoStream.fail()) {
294 LOGE("[NNCompiledCache] WriteCacheInfo failed, model cache info file is invalid.");
295 return OH_NN_INVALID_FILE;
296 }
297
298 cacheInfoStream << cacheInfo << std::endl;
299
300 cacheInfoStream.close();
301 return OH_NN_SUCCESS;
302 }
303
CheckCacheInfo(NNCompiledCacheInfo & modelCacheInfo,const std::string & cacheInfoPath) const304 OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo,
305 const std::string& cacheInfoPath) const
306 {
307 // cacheInfoPath is validated outside.
308 std::ifstream infoCacheFile(cacheInfoPath.c_str(), std::ios::in | std::ios::binary);
309 if (!infoCacheFile) {
310 LOGE("[NNCompiledCache] CheckCacheInfo failed, error happened when opening cache info file.");
311 return OH_NN_INVALID_FILE;
312 }
313
314 std::string content((std::istreambuf_iterator<char>(infoCacheFile)), std::istreambuf_iterator<char>());
315 infoCacheFile.close();
316 if (!nlohmann::json::accept(content)) {
317 LOGE("[NNCompiledCache] CheckCacheInfo JSON parse error");
318 return OH_NN_INVALID_FILE;
319 }
320
321 // Parse the JSON string
322 nlohmann::json j = nlohmann::json::parse(content);
323 // modelCacheInfo.deviceId type is int64_t,
324 // it is transformed from size_t value, so the transform here will not truncate value.
325 if (j.find("data") == j.end()) {
326 LOGE("[NNCompiledCache] CheckCacheInfo read cache info file failed.");
327 return OH_NN_INVALID_FILE;
328 }
329
330 if (j["data"].find("deviceId") == j["data"].end()) {
331 LOGE("[NNCompiledCache] CheckCacheInfo read deviceId from cache info file failed.");
332 return OH_NN_INVALID_FILE;
333 }
334 modelCacheInfo.deviceId = j["data"]["deviceId"].get<int64_t>();
335
336 if (j["data"].find("version") == j["data"].end()) {
337 LOGE("[NNCompiledCache] CheckCacheInfo read version from cache info file failed.");
338 return OH_NN_INVALID_FILE;
339 }
340 modelCacheInfo.version = j["data"]["version"].get<int64_t>();
341
342 size_t deviceId = static_cast<size_t>(modelCacheInfo.deviceId);
343 if (deviceId != m_backendID) {
344 LOGE("[NNCompiledCache] CheckCacheInfo failed. The deviceId in the cache files "
345 "is different from current deviceId,"
346 "please change the cache directory or current deviceId.");
347 return OH_NN_INVALID_FILE;
348 }
349
350 if (j["data"].find("fileNumber") == j["data"].end()) {
351 LOGE("[NNCompiledCache] CheckCacheInfo read fileNumber from cache info file failed.");
352 return OH_NN_INVALID_FILE;
353 }
354 modelCacheInfo.fileNumber = j["data"]["fileNumber"].get<int64_t>();
355
356 return CheckCacheInfoExtension(modelCacheInfo, j);
357 }
358
CheckCacheInfoExtension(NNCompiledCacheInfo & modelCacheInfo,nlohmann::json & j) const359 OH_NN_ReturnCode NNCompiledCache::CheckCacheInfoExtension(NNCompiledCacheInfo& modelCacheInfo,
360 nlohmann::json& j) const
361 {
362 const size_t dataLength = j["data"].dump().length();
363 char jData[dataLength + 1];
364 if (strncpy_s(jData, dataLength+1, j["data"].dump().c_str(), dataLength) != 0) {
365 LOGE("[NNCompiledCache] ParseStr failed due to strncpy_s error.");
366 return OH_NN_INVALID_FILE;
367 }
368
369 if (j.find("CheckSum") == j.end()) {
370 LOGE("[NNCompiledCache] read CheckSum from cache info file failed.");
371 return OH_NN_INVALID_FILE;
372 }
373
374 if (static_cast<int64_t>(CacheInfoGetCrc16(jData, dataLength)) != j["CheckSum"].get<int64_t>()) {
375 LOGE("[NNCompiledCache] cache_info CheckSum is not correct.");
376 return OH_NN_INVALID_FILE;
377 }
378 std::vector<int64_t> modelCheckSum;
379 modelCheckSum.resize(modelCacheInfo.fileNumber);
380 modelCacheInfo.modelCheckSum.resize(modelCacheInfo.fileNumber);
381 if (j["data"].find("modelCheckSum") == j["data"].end()) {
382 LOGE("[NNCompiledCache] CheckCacheInfo read modelCheckSum from cache file failed.");
383 return OH_NN_INVALID_FILE;
384 }
385 for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) {
386 modelCheckSum[i] = static_cast<int64_t>(j["data"]["modelCheckSum"][i]);
387 }
388
389 for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) {
390 modelCacheInfo.modelCheckSum[i] = static_cast<unsigned short>(modelCheckSum[i]);
391 }
392
393 if (j["data"].find("opVersion") == j["data"].end()) {
394 LOGW("[NNCompiledCache] CheckCacheInfo read opVersion from cache info file failed.");
395 } else {
396 modelCacheInfo.opVersion = j["data"]["opVersion"].get<int64_t>();
397 }
398
399 if (j["data"].find("isExceedRamLimit") == j["data"].end()) {
400 LOGE("[NNCompiledCache] CheckCacheInfo read isExceedRamLimit from cache info file failed.");
401 return OH_NN_INVALID_FILE;
402 } else {
403 modelCacheInfo.isExceedRamLimit = j["data"]["isExceedRamLimit"].get<int64_t>();
404 }
405
406 return OH_NN_SUCCESS;
407 }
408
ReadCacheModelFile(const std::string & filePath,OHOS::NeuralNetworkRuntime::Buffer & cache)409 OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath,
410 OHOS::NeuralNetworkRuntime::Buffer& cache)
411 {
412 char path[PATH_MAX];
413 if (realpath(filePath.c_str(), path) == nullptr) {
414 LOGE("[NNCompiledCache] ReadCacheModelFile failed, fail to get the real path of filePath.");
415 return OH_NN_INVALID_PARAMETER;
416 }
417 if (access(path, 0) != 0) {
418 LOGE("[NNCompiledCache] ReadCacheModelFile failed, filePath is not exist.");
419 return OH_NN_INVALID_PARAMETER;
420 }
421
422 int fd = open(path, O_RDONLY);
423 if (fd == -1) {
424 LOGE("[NNCompiledCache] ReadCacheModelFile failed, file fopen failed.");
425 return OH_NN_INVALID_FILE;
426 }
427
428 struct stat sb;
429 if (fstat(fd, &sb) == -1) {
430 close(fd);
431 LOGE("[NNCompiledCache] ReadCacheModelFile failed, get file %{public}s state failed.", filePath.c_str());
432 return OH_NN_MEMORY_ERROR;
433 }
434
435 off_t fsize = sb.st_size;
436
437 void *ptr = mmap(nullptr, fsize, PROT_READ, MAP_SHARED, fd, 0);
438 if (ptr == MAP_FAILED) {
439 LOGE("[NNCompiledCache] ReadCacheModelFile failed, failed to mmap file.");
440 close(fd);
441 return OH_NN_INVALID_FILE;
442 }
443
444 cache.data = ptr;
445 cache.length = static_cast<size_t>(fsize); // fsize should be non-negative, safe to cast.
446 cache.fd = fd;
447 return OH_NN_SUCCESS;
448 }
449
GetCrc16(char * buffer,size_t length) const450 unsigned short NNCompiledCache::GetCrc16(char* buffer, size_t length) const
451 {
452 unsigned int sum = 0;
453
454 if (buffer == nullptr) {
455 return static_cast<unsigned short>(~sum);
456 }
457
458 if (length < MAX_CACHE_SIZE) {
459 while (length > 1) {
460 sum += *(reinterpret_cast<unsigned short*>(buffer));
461 length -= sizeof(unsigned short);
462 buffer += sizeof(unsigned short);
463 }
464 } else {
465 size_t step = length / MAX_CACHE_SIZE;
466 while (length > sizeof(unsigned short) * step + 1) {
467 sum += *(reinterpret_cast<unsigned short*>(buffer));
468 length -= step * sizeof(unsigned short);
469 buffer += step * sizeof(unsigned short);
470 }
471 }
472
473 if (length > 0) {
474 buffer += length - 1;
475 sum += *(reinterpret_cast<unsigned char*>(buffer));
476 }
477
478 while (sum >> HEX_UNIT) {
479 sum = (sum >> HEX_UNIT) + (sum & 0xffff);
480 }
481
482 return static_cast<unsigned short>(~sum);
483 }
484
GetCacheFileLength(FILE * pFile,long & fileSize) const485 OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(FILE* pFile, long& fileSize) const
486 {
487 int ret = fseek(pFile, 0L, SEEK_END);
488 if (ret != 0) {
489 LOGE("[NNCompiledCache] GetCacheFileLength failed, fail to set the position of the next character "
490 "to be extracted from the input stream.");
491 return OH_NN_FAILED;
492 }
493
494 long handleValue = ftell(pFile);
495 if (handleValue == -1) {
496 LOGE("[NNCompiledCache] GetCacheFileLength failed, fail to get position of the input stream.");
497 return OH_NN_INVALID_FILE;
498 }
499
500 if (handleValue == NULL_PTR_LENGTH) {
501 LOGE("[NNCompiledCache] GetCacheFileLength failed, unable to read huge or empty input stream, "
502 "get cache file size=%{public}ld",
503 handleValue);
504 return OH_NN_INVALID_FILE;
505 }
506
507 fileSize = handleValue;
508 return OH_NN_SUCCESS;
509 }
510
VerifyCachePath(const std::string & cachePath) const511 OH_NN_ReturnCode NNCompiledCache::VerifyCachePath(const std::string& cachePath) const
512 {
513 // exception: input path is not start with '/'.
514 if (cachePath.find(ROOT_DIR_STR) != size_t(0)) {
515 LOGE("[NNCompiledCache] VerifyCachePath failed, input file dir=%{public}s is invalid, "
516 "should start with '/'.",
517 cachePath.c_str());
518 return OH_NN_INVALID_FILE;
519 }
520
521 // exception: input path contains continuous double '/'.
522 if (cachePath.find(DOUBLE_SLASH_STR) != std::string::npos) {
523 LOGE("[NNCompiledCache] VerifyCachePath failed, input file dir=%{public}s is invalid, "
524 "containing double '/'.",
525 cachePath.c_str());
526 return OH_NN_INVALID_FILE;
527 }
528
529 return OH_NN_SUCCESS;
530 }
531
ReleaseCacheBuffer(std::vector<Buffer> & buffers)532 void NNCompiledCache::ReleaseCacheBuffer(std::vector<Buffer>& buffers)
533 {
534 for (auto buffer : buffers) {
535 munmap(buffer.data, buffer.length);
536 close(buffer.fd);
537 }
538 buffers.clear();
539 }
540 } // namespace NeuralNetworkRuntime
541 } // namespace OHOS
542