Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "ae_so_manager.hpp"
12 : #include <memory>
13 : #include <mutex>
14 : #include <cstdlib>
15 : #include <string>
16 : #include <climits>
17 : #include <securec.h>
18 : #include <dlfcn.h>
19 : #include <fstream>
20 : #include <sstream>
21 : #include <vector>
22 : #include "ae_def.hpp"
23 : #include "ae_kernel_lib_aicpu.hpp"
24 :
25 : namespace cce {
26 : namespace {
27 : // aicpu so root dir, must be absolute path
28 : const std::string AICPU_SO_ROOT_DIR = "/usr/lib64/aicpu_kernels/";
29 : // aicpu so root dir, old path only for hccl
30 : const std::string AICPU_SO_ROOT_DIR_OLD_PATH = "/usr/lib64/";
31 : // cust so path for cust_aicpu_sd: CustAiCpuUser
32 : constexpr const char_t* CUST_USER_SO_PATH = "/home/CustAiCpuUser";
33 : // prefix of cust so dir name
34 : constexpr const char_t* CUSTOM_SO_DIR_NAME_PREFIX = "cust_aicpu_";
35 : // aicpu kernels tar uncompress path
36 : constexpr const char_t* AICPU_SO_UNCOMPRESS_DIR = "aicpu_kernels_device";
37 : // libretr_kernels.so
38 : constexpr const char_t* RETR_KERNELS_SO_NAME = "libretr_kernels.so";
39 : // libhccl_operator_call.so
40 : constexpr const char_t* HCCL_KERNELS_SO_NAME = "libhccl_operator_call.so";
41 : // libbuiltin_kernels.so
42 : constexpr const char_t* BUILTIN_KERNELS_SO_NAME = "libbuiltin_kernels.so";
43 : // pattern for custom so name
44 : constexpr const char_t* PATTERN_FOR_SO_NAME("abcdefghijklmnopqrstuvwxyz"
45 : "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890-_.");
46 : // env variable name: inner aicpu kernel so path
47 : constexpr const char_t* AICPU_INNER_SO_PATH_ENV_VAR_NAME = "ASCEND_AICPU_KERNEL_PATH";
48 : // env variable name: custom aicpu kernel so path
49 : // If modify the env name, please modify the same env name in aicpusd_cust_so_manager.cpp
50 : constexpr const char_t* AICPU_CUSTOM_SO_PATH_ENV_VAR = "ASCEND_CUST_AICPU_KERNEL_CACHE_PATH";
51 : // physical machine VFID == 0 物理机场景
52 : constexpr uint32_t DEFAULT_VFID = 0U;
53 : // min number of vDeviceId
54 : constexpr const uint32_t VDEVICE_MIN_CPU_NUM = 32U;
55 : // max number of vDeviceId
56 : constexpr const uint32_t VDEVICE_MAX_CPU_NUM = 64U;
57 : constexpr const uint32_t DIV_NUM = 2U;
58 : // version.info TurstList info
59 : const std::string TRUST_SO_LIST_PREFIX = "Trustlist=";
60 :
61 : constexpr const char_t* THREAD_MODE_SO_PATH_FIX = "aicpu_kernels";
62 : } // namespace
63 :
64 29 : SingleSoManager::~SingleSoManager()
65 : {
66 : // Step1. clear the critical section apiCacher_
67 29 : AE_RW_LOCK_WR_LOCK(&rwLock_);
68 29 : apiCacher_.clear();
69 29 : AE_RW_LOCK_UN_LOCK(&rwLock_);
70 :
71 : // Step2. destroy the Read Write lock
72 29 : AE_RW_LOCK_DESTROY(&rwLock_);
73 :
74 : // Step3. close so
75 29 : (void)CloseSo(soHandle_);
76 29 : soHandle_ = nullptr;
77 29 : }
78 :
79 28 : aeStatus_t SingleSoManager::Init(const std::string& guardDirName, const std::string& soFile)
80 : {
81 28 : soName_.clear();
82 28 : apiCacher_.clear();
83 :
84 28 : aeStatus_t ret = CheckSoFile(guardDirName, soFile);
85 28 : if (ret != AE_STATUS_SUCCESS) {
86 24 : AE_RUN_WARN_LOG(AE_MODULE_ID, "CheckSoFile failed, soFile[%s], ret[%u].", soFile.c_str(), ret);
87 24 : return ret;
88 : }
89 :
90 4 : void* handle = nullptr;
91 4 : ret = OpenSo(soFile, &handle);
92 4 : if ((ret == AE_STATUS_SUCCESS) && (handle != nullptr)) {
93 4 : soHandle_ = handle;
94 4 : soName_ = soFile;
95 : }
96 4 : return ret;
97 : }
98 :
99 34 : aeStatus_t SingleSoManager::CheckSoFile(const std::string& guardDirName, const std::string& soFile)
100 : {
101 34 : if (guardDirName.empty()) {
102 1 : AE_INFO_LOG(AE_MODULE_ID, "guardDirName is empty, no need check");
103 1 : return AE_STATUS_SUCCESS;
104 : }
105 :
106 33 : if (soFile.length() >= static_cast<std::string::size_type>(PATH_MAX)) {
107 1 : AE_ERR_LOG(AE_MODULE_ID, "soFile file length[%zu] must less than PATH_MAX[%u]", soFile.length(), PATH_MAX);
108 1 : return AE_STATUS_OPEN_SO_FAILED;
109 : }
110 :
111 32 : std::unique_ptr<char_t[]> path(new (std::nothrow) char_t[PATH_MAX]);
112 32 : if (path == nullptr) {
113 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Alloc memory for path failed.");
114 0 : return AE_STATUS_OPEN_SO_FAILED;
115 : }
116 :
117 32 : const auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
118 32 : if (eRet != EOK) {
119 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Mem set error, ret=%d", eRet);
120 1 : return AE_STATUS_OPEN_SO_FAILED;
121 : }
122 :
123 31 : if (realpath(soFile.data(), path.get()) == nullptr) {
124 27 : AE_WARN_LOG(AE_MODULE_ID, "Format to realpath failed:%s, path:%s", soFile.data(), path.get());
125 27 : return AE_STATUS_OPEN_SO_FAILED;
126 : }
127 :
128 4 : std::string tmpGuardDirName(guardDirName);
129 4 : if (tmpGuardDirName[tmpGuardDirName.size() - 1UL] != '/') {
130 1 : (void)tmpGuardDirName.append("/");
131 : }
132 :
133 4 : const std::string pathStr(path.get());
134 4 : const std::string realSoPath = GetRealCustSoPath();
135 5 : if ((strncmp(path.get(), tmpGuardDirName.c_str(), tmpGuardDirName.length()) != 0) &&
136 1 : (pathStr.find(realSoPath) == std::string::npos)) {
137 1 : AE_ERR_LOG(
138 : AE_MODULE_ID, "Invalid so file with dir:%s so:%s, should be %s or %s", path.get(), soFile.c_str(),
139 : tmpGuardDirName.data(), realSoPath.c_str());
140 1 : return AE_STATUS_OPEN_SO_FAILED;
141 : }
142 3 : return AE_STATUS_SUCCESS;
143 32 : }
144 :
145 4 : std::string SingleSoManager::GetRealCustSoPath()
146 : {
147 : aicpu::aicpuContext_t currentAicpuCtx;
148 4 : (void)aicpu::aicpuGetContext(¤tAicpuCtx);
149 :
150 4 : const uint32_t uniqueVfId = aicpu::GetUniqueVfId();
151 :
152 4 : std::string soPath = CUST_USER_SO_PATH;
153 4 : GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
154 4 : (void)soPath.append("lib/");
155 4 : return soPath;
156 0 : }
157 :
158 7 : void SingleSoManager::GetCustSoPathByUniqueVfId(std::string& soPath, const uint32_t uniqueVfId)
159 : {
160 7 : if (uniqueVfId == DEFAULT_VFID) {
161 7 : (void)soPath.append("/");
162 0 : } else if (uniqueVfId >= VDEVICE_MIN_CPU_NUM && uniqueVfId < VDEVICE_MAX_CPU_NUM) {
163 0 : const uint32_t custNum = (uniqueVfId - VDEVICE_MIN_CPU_NUM) / DIV_NUM + 1U;
164 0 : (void)soPath.append(std::to_string(custNum)).append("/");
165 0 : } else {
166 0 : (void)soPath.append(std::to_string(uniqueVfId)).append("/");
167 : }
168 7 : }
169 :
170 13 : aeStatus_t SingleSoManager::OpenSo(const std::string& soFile, void** const retHandle)
171 : {
172 : // Use API in glibc to open the so lib, load this so to process.
173 13 : std::unique_ptr<char_t[]> path(new (std::nothrow) char_t[PATH_MAX]);
174 13 : if (path == nullptr) {
175 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Alloc memory for path failed.");
176 0 : return AE_STATUS_OPEN_SO_FAILED;
177 : }
178 :
179 13 : const auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
180 13 : if (eRet != EOK) {
181 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Mem set error, ret=%d", eRet);
182 1 : return AE_STATUS_OPEN_SO_FAILED;
183 : }
184 :
185 12 : if (realpath(soFile.data(), path.get()) == nullptr) {
186 8 : AE_WARN_LOG(AE_MODULE_ID, "Format to realpath failed:[%s], path:[%s]", soFile.data(), path.get());
187 8 : return AE_STATUS_OPEN_SO_FAILED;
188 : }
189 :
190 4 : AE_INFO_LOG(AE_MODULE_ID, "Open so %s begin.", path.get());
191 4 : void* const handle = dlopen(
192 4 : path.get(), static_cast<int32_t>((static_cast<uint32_t>(RTLD_LAZY)) | (static_cast<uint32_t>(RTLD_GLOBAL))));
193 4 : if (handle == nullptr) {
194 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Open so %s failed with error:%s", path.get(), dlerror());
195 0 : return AE_STATUS_OPEN_SO_FAILED;
196 : }
197 :
198 4 : *retHandle = handle;
199 4 : AE_INFO_LOG(AE_MODULE_ID, "Open so %s success.", soFile.c_str());
200 4 : return AE_STATUS_SUCCESS;
201 13 : }
202 :
203 2 : aeStatus_t SingleSoManager::GetFunc(void* const soHandle, const char_t* const funcName, void** const retFuncAddr)
204 : {
205 2 : void* const theFuncAddr = dlsym(soHandle, funcName);
206 2 : if (static_cast<bool>(unlikely((theFuncAddr == nullptr)))) {
207 1 : AE_ERR_LOG(AE_MODULE_ID, "Get funcAddr %s from handle is NULL: %s", funcName, dlerror());
208 1 : return AE_STATUS_GET_KERNEL_NAME_FAILED;
209 : }
210 1 : *retFuncAddr = theFuncAddr;
211 1 : return AE_STATUS_SUCCESS;
212 : }
213 :
214 127 : aeStatus_t SingleSoManager::GetApi(
215 : const char_t* const soNamePtr, const char_t* const funcName, void** const funcAddrPtr)
216 : {
217 127 : if (static_cast<bool>(unlikely((soHandle_ == nullptr)))) {
218 3 : AE_RUN_WARN_LOG(AE_MODULE_ID, "soHandle_ is null, should be Init first.");
219 3 : return AE_STATUS_INNER_ERROR;
220 : }
221 :
222 124 : AE_RW_LOCK_RD_LOCK(&rwLock_);
223 248 : auto apiIter = apiCacher_.find(funcName);
224 124 : if (apiIter != apiCacher_.end()) {
225 116 : *funcAddrPtr = apiIter->second;
226 116 : AE_RW_LOCK_UN_LOCK(&rwLock_);
227 117 : return AE_STATUS_SUCCESS;
228 : }
229 7 : AE_RW_LOCK_UN_LOCK(&rwLock_);
230 :
231 7 : AE_RW_LOCK_WR_LOCK(&rwLock_);
232 14 : apiIter = apiCacher_.find(funcName);
233 7 : if (apiIter != apiCacher_.end()) {
234 0 : *funcAddrPtr = apiIter->second;
235 0 : AE_RW_LOCK_UN_LOCK(&rwLock_);
236 0 : return AE_STATUS_SUCCESS;
237 : }
238 :
239 : // get func
240 7 : void* theFuncAddr = nullptr;
241 7 : const aeStatus_t ret = GetFunc(soHandle_, funcName, &theFuncAddr);
242 7 : if (ret != AE_STATUS_SUCCESS) {
243 1 : AE_RW_LOCK_UN_LOCK(&rwLock_);
244 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Get func %s from so %s failed, ret[%u].", funcName, soNamePtr, ret);
245 1 : return ret;
246 : }
247 : // cache func
248 12 : apiCacher_[funcName] = theFuncAddr;
249 6 : *funcAddrPtr = theFuncAddr;
250 6 : AE_RW_LOCK_UN_LOCK(&rwLock_);
251 6 : AE_RUN_INFO_LOG(AE_MODULE_ID, "Get api %s from so %s success.", funcName, soNamePtr);
252 6 : return AE_STATUS_SUCCESS;
253 : }
254 :
255 3 : aeStatus_t SingleSoManager::GetApi(
256 : const char_t* const soFile, const char_t* const funcName, void** const funcAddrPtr, void** const retHandle)
257 : {
258 3 : void* handle = nullptr;
259 3 : const aeStatus_t retOpenSo = OpenSo(soFile, &handle);
260 3 : if ((retOpenSo == AE_STATUS_SUCCESS) && (handle != nullptr)) {
261 1 : void* theFuncAddr = nullptr;
262 1 : const aeStatus_t retGetFunc = GetFunc(handle, funcName, &theFuncAddr);
263 1 : if ((retGetFunc == AE_STATUS_SUCCESS) && (theFuncAddr != nullptr)) {
264 1 : *funcAddrPtr = theFuncAddr;
265 : }
266 :
267 1 : *retHandle = handle;
268 1 : return retGetFunc;
269 : }
270 :
271 2 : AE_ERR_LOG(AE_MODULE_ID, "Open so failed when get api, soFile[%s], ret[%u].", soFile, retOpenSo);
272 2 : return retOpenSo;
273 : }
274 :
275 55 : aeStatus_t SingleSoManager::CloseSo(void* const retHandle)
276 : {
277 55 : if (retHandle != nullptr) {
278 8 : const int32_t ret = dlclose(retHandle);
279 8 : if (ret != 0) {
280 1 : AE_ERR_LOG(AE_MODULE_ID, "Close so failed with error:%s", dlerror());
281 1 : return AE_STATUS_INNER_ERROR;
282 : } else {
283 7 : AE_DEBUG_LOG(AE_MODULE_ID, "Close success:");
284 7 : return AE_STATUS_SUCCESS;
285 : }
286 : }
287 47 : return AE_STATUS_SUCCESS;
288 : }
289 :
290 81 : MultiSoManager::~MultiSoManager()
291 : {
292 : // Step1. clear the critical section apiCacher_
293 81 : AE_RW_LOCK_WR_LOCK(&rwLock_);
294 84 : for (auto iter = soCacher_.begin(); iter != soCacher_.end(); ++iter) {
295 3 : const SingleSoManager* const soMngr = iter->second;
296 3 : if (soMngr != nullptr) {
297 3 : delete soMngr; // Release each SingleSoManager * stored in cache
298 : }
299 : }
300 81 : soCacher_.clear();
301 81 : AE_RW_LOCK_UN_LOCK(&rwLock_);
302 : // Step2. destroy the Read Write lock
303 81 : AE_RW_LOCK_DESTROY(&rwLock_);
304 81 : };
305 :
306 8 : aeStatus_t MultiSoManager::Init()
307 : {
308 8 : soCacher_.clear();
309 8 : const aicpu::status_t status = aicpu::GetAicpuRunMode(runMode_);
310 8 : if (status != aicpu::AICPU_ERROR_NONE) {
311 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Get aicpu runmode failed.");
312 1 : return AE_STATUS_INNER_ERROR;
313 : }
314 : // get aicpu so path
315 7 : const char_t* const innerDirName = getenv(AICPU_INNER_SO_PATH_ENV_VAR_NAME);
316 7 : if (innerDirName != nullptr) {
317 1 : const std::string str = innerDirName;
318 1 : const size_t len = str.length();
319 1 : if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
320 0 : AE_ERR_LOG(AE_MODULE_ID, "Length of inner so dir %zu is invalid.", len);
321 0 : return AE_STATUS_INNER_ERROR;
322 : }
323 1 : innerKernelPath_ = str;
324 1 : if (innerKernelPath_[innerKernelPath_.size() - 1UL] != '/') {
325 0 : (void)innerKernelPath_.append("/");
326 : }
327 1 : }
328 : // get cust aicpu so path
329 7 : const char_t* const custDirName = getenv(AICPU_CUSTOM_SO_PATH_ENV_VAR);
330 7 : if (custDirName != nullptr) {
331 1 : const std::string str = custDirName;
332 1 : const size_t len = str.length();
333 1 : if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
334 0 : AE_ERR_LOG(AE_MODULE_ID, "Length of cust so dir %zu is invalid.", len);
335 0 : return AE_STATUS_INNER_ERROR;
336 : }
337 1 : custKernelPath_ = str;
338 1 : if (custKernelPath_[custKernelPath_.size() - 1UL] != '/') {
339 0 : (void)custKernelPath_.append("/");
340 : }
341 1 : }
342 7 : return AE_STATUS_SUCCESS;
343 : }
344 :
345 124 : aeStatus_t MultiSoManager::GetApi(
346 : const aicpu::KernelType kernelType, const char_t* const soName, const char_t* const funcName,
347 : void** const funcAddrPtr)
348 : {
349 124 : SingleSoManager* soMgr = nullptr;
350 124 : const aeStatus_t ret = LoadSo(kernelType, soName, soMgr);
351 124 : if ((ret != AE_STATUS_SUCCESS) || (soMgr == nullptr)) {
352 3 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Load so %s failed.", soName);
353 3 : return AE_STATUS_OPEN_SO_FAILED;
354 : }
355 122 : return soMgr->GetApi(soName, funcName, funcAddrPtr);
356 : }
357 :
358 12 : aeStatus_t MultiSoManager::GetSoPath(
359 : const aicpu::KernelType kernelType, const std::string& soName, std::string& soPath) const
360 : {
361 12 : if (kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM || kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM_KFC) {
362 0 : return GetCustSoPath(soPath);
363 : }
364 12 : return GetInnerSoPath(soName, soPath);
365 : }
366 :
367 11 : aeStatus_t MultiSoManager::GetThreadModeSoPath(std::string& soPath) const
368 : {
369 11 : const char_t* const innerDirName = getenv("HOME");
370 11 : if (innerDirName != nullptr) {
371 10 : const std::string str = innerDirName;
372 10 : const size_t len = str.length();
373 10 : if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
374 0 : AE_ERR_LOG(AE_MODULE_ID, "Length[%zu] of inner so dir is invalid.", len);
375 0 : return AE_STATUS_INNER_ERROR;
376 : }
377 10 : soPath = str;
378 10 : if (soPath[soPath.size() - 1UL] != '/') {
379 10 : (void)soPath.append("/");
380 : }
381 10 : (void)soPath.append(THREAD_MODE_SO_PATH_FIX)
382 10 : .append("/")
383 20 : .append(std::to_string(aicpu::GetUniqueVfId()))
384 10 : .append("/")
385 10 : .append(AICPU_SO_UNCOMPRESS_DIR)
386 10 : .append("/");
387 10 : return AE_STATUS_SUCCESS;
388 10 : } else {
389 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Get HOME env failed, get thread mode so path failed.");
390 1 : return AE_STATUS_INNER_ERROR;
391 : }
392 : }
393 21 : aeStatus_t MultiSoManager::GetInnerSoPath(const std::string& soName, std::string& soPath) const
394 : {
395 : uint32_t runMode;
396 21 : aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
397 21 : if (status != aicpu::AICPU_ERROR_NONE) {
398 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
399 1 : return AE_STATUS_INNER_ERROR;
400 : }
401 :
402 : // aicpu kernel path for lhisi from env: ASCEND_AICPU_KERNEL_PATH
403 20 : if ((runMode == aicpu::AicpuRunMode::THREAD_MODE) && (!innerKernelPath_.empty())) {
404 1 : soPath = innerKernelPath_;
405 1 : return AE_STATUS_SUCCESS;
406 : }
407 :
408 : // libretr_kernels.so in /usr/lib64/aicpu_kernel/
409 19 : if (soName == RETR_KERNELS_SO_NAME) {
410 1 : soPath = AICPU_SO_ROOT_DIR;
411 1 : return AE_STATUS_SUCCESS;
412 : }
413 :
414 : // libhccl_operator_call.so in /usr/lib64/
415 18 : if ((soName == HCCL_KERNELS_SO_NAME) || (soName == BUILTIN_KERNELS_SO_NAME)) {
416 1 : soPath = AICPU_SO_ROOT_DIR_OLD_PATH;
417 1 : return AE_STATUS_SUCCESS;
418 : }
419 :
420 17 : if (runMode == aicpu::AicpuRunMode::THREAD_MODE) {
421 7 : if (GetThreadModeSoPath(soPath) == AE_STATUS_SUCCESS) {
422 7 : return AE_STATUS_SUCCESS;
423 : }
424 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "thread mode home path invalid use default path [%s].", soPath.c_str());
425 : }
426 : // get aicpu context
427 : aicpu::aicpuContext_t currentAicpuCtx;
428 10 : status = aicpu::aicpuGetContext(¤tAicpuCtx);
429 10 : if (status != aicpu::AICPU_ERROR_NONE) {
430 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
431 1 : return AE_STATUS_INNER_ERROR;
432 : }
433 : // libtf_kernels.so and libaicpu_kernels.so and libcpu_kernels.so and libpt_kernels.so path from context
434 9 : soPath = AICPU_SO_ROOT_DIR;
435 9 : (void)soPath.append(std::to_string(aicpu::GetUniqueVfId())).append("/").append(AICPU_SO_UNCOMPRESS_DIR).append("/");
436 :
437 9 : return AE_STATUS_SUCCESS;
438 : }
439 :
440 9 : aeStatus_t MultiSoManager::BuildCustSoPath(std::string& soPath, const uint32_t uniqueVfId) const
441 : {
442 : uint32_t runMode;
443 9 : const aicpu::status_t statusMode = aicpu::GetAicpuRunMode(runMode);
444 9 : if (statusMode != aicpu::AICPU_ERROR_NONE) {
445 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
446 1 : return AE_STATUS_INNER_ERROR;
447 : }
448 : // dc
449 8 : if (runMode == aicpu::AicpuRunMode::PROCESS_PCIE_MODE) {
450 1 : soPath = CUST_USER_SO_PATH;
451 1 : SingleSoManager::GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
452 7 : } else if (runMode == aicpu::AicpuRunMode::PROCESS_SOCKET_MODE) {
453 3 : const char_t* const custDirName = getenv("HOME");
454 3 : if (custDirName == nullptr) {
455 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current dir name by HOME in socket_mode failed.");
456 1 : return AE_STATUS_INNER_ERROR;
457 : }
458 2 : soPath = custDirName;
459 2 : AE_RUN_INFO_LOG(AE_MODULE_ID, "Get soPath[%s] in socket_mode", soPath.c_str());
460 2 : SingleSoManager::GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
461 : } else {
462 4 : const char_t* const curDirName = getenv("HOME");
463 4 : if (curDirName == nullptr) {
464 2 : AE_ERR_LOG(AE_MODULE_ID, "Get current home directory failed.");
465 3 : return AE_STATUS_INNER_ERROR;
466 : }
467 2 : const std::string dirName = curDirName;
468 2 : const size_t len = dirName.length();
469 2 : if ((len == 0LU) || (len >= static_cast<size_t>(PATH_MAX))) {
470 1 : AE_ERR_LOG(AE_MODULE_ID, "Length of current dir name %zu is invalid.", len);
471 1 : return AE_STATUS_INNER_ERROR;
472 : }
473 1 : soPath = dirName;
474 1 : if (soPath[soPath.size() - 1LU] != '/') {
475 1 : (void)soPath.append("/");
476 : }
477 2 : }
478 4 : return AE_STATUS_SUCCESS;
479 : }
480 :
481 8 : aeStatus_t MultiSoManager::GetCustSoPath(std::string& soPath) const
482 : {
483 : // get aicpu context
484 : aicpu::aicpuContext_t currentAicpuCtx;
485 8 : const aicpu::status_t status = aicpu::aicpuGetContext(¤tAicpuCtx);
486 8 : if (status != aicpu::AICPU_ERROR_NONE) {
487 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
488 1 : return AE_STATUS_INNER_ERROR;
489 : }
490 7 : const uint32_t uniqueVfId = aicpu::GetUniqueVfId();
491 : // minirc or ctrlcpu, cust so load in current user root path; else, so load in cust aicpu_sd thread
492 : // lhisi, so load path from env ASCEND_CUST_AICPU_KERNEL_PATH
493 7 : if (!custKernelPath_.empty()) {
494 0 : soPath = custKernelPath_;
495 : } else {
496 7 : const auto ret = BuildCustSoPath(soPath, uniqueVfId);
497 7 : if (ret != AE_STATUS_SUCCESS) {
498 4 : AE_ERR_LOG(AE_MODULE_ID, "BuildCustSoPath failed.");
499 4 : return ret;
500 : }
501 : }
502 3 : (void)soPath.append(CUSTOM_SO_DIR_NAME_PREFIX)
503 3 : .append(std::to_string(currentAicpuCtx.deviceId))
504 3 : .append("_")
505 6 : .append(std::to_string(uniqueVfId))
506 3 : .append("_")
507 6 : .append(std::to_string(static_cast<int32_t>(currentAicpuCtx.hostPid)))
508 3 : .append("/");
509 3 : return AE_STATUS_SUCCESS;
510 : }
511 :
512 8 : aeStatus_t MultiSoManager::LoadSo(const aicpu::KernelType kernelType, const std::string& soName)
513 : {
514 8 : SingleSoManager* soMgr = nullptr;
515 16 : return LoadSo(kernelType, soName, soMgr);
516 : }
517 :
518 132 : aeStatus_t MultiSoManager::LoadSo(
519 : const aicpu::KernelType kernelType, const std::string& soName, SingleSoManager*& soMgr)
520 : {
521 132 : if (soName.empty()) {
522 1 : AE_ERR_LOG(AE_MODULE_ID, "So name is empty.");
523 1 : return AE_STATUS_BAD_PARAM;
524 : }
525 :
526 131 : if (!aicpu::IsCustAicpuSd()) {
527 131 : if ((runMode_ != aicpu::AicpuRunMode::THREAD_MODE) &&
528 124 : ((kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM) || (kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM_KFC))) {
529 1 : AE_ERR_LOG(AE_MODULE_ID, "runmode is not THREAD_MODE AND kernelType is [%u]", kernelType);
530 1 : return AE_STATUS_BAD_PARAM;
531 : }
532 : }
533 :
534 130 : AE_RW_LOCK_RD_LOCK(&rwLock_);
535 131 : auto soIter = soCacher_.find(soName);
536 131 : if ((soCacher_.end() != soIter) && (soIter->second != nullptr)) {
537 118 : soMgr = soIter->second;
538 118 : AE_RW_LOCK_UN_LOCK(&rwLock_);
539 118 : return AE_STATUS_SUCCESS;
540 : }
541 13 : AE_RW_LOCK_UN_LOCK(&rwLock_);
542 :
543 13 : AE_RW_LOCK_WR_LOCK(&rwLock_);
544 13 : soIter = soCacher_.find(soName);
545 13 : if ((soCacher_.end() != soIter) && (soIter->second != nullptr)) {
546 0 : soMgr = soIter->second;
547 0 : AE_RW_LOCK_UN_LOCK(&rwLock_);
548 0 : return AE_STATUS_SUCCESS;
549 : }
550 13 : const auto ret = CreateSingleSoMgr(kernelType, soName, soMgr);
551 13 : if (ret != AE_STATUS_SUCCESS) {
552 8 : AE_RW_LOCK_UN_LOCK(&rwLock_);
553 8 : AE_RUN_WARN_LOG(AE_MODULE_ID, "CreateSingleSoMgr failed, soName[%s], ret[%u].", soName.c_str(), ret);
554 8 : return ret;
555 : }
556 5 : AE_RW_LOCK_UN_LOCK(&rwLock_);
557 5 : return AE_STATUS_SUCCESS;
558 : }
559 :
560 13 : aeStatus_t MultiSoManager::CreateSingleSoMgr(
561 : const aicpu::KernelType kernelType, const std::string& soName, SingleSoManager*& soMgr)
562 : {
563 : // check so name
564 13 : if (soName.find_first_not_of(PATTERN_FOR_SO_NAME) != std::string::npos) {
565 0 : AE_ERR_LOG(AE_MODULE_ID, "So name %s is not invalid. Please check!", soName.c_str());
566 0 : return AE_STATUS_BAD_PARAM;
567 : }
568 : // get so real path
569 13 : std::string realSoPath;
570 13 : auto ret = GetSoPath(kernelType, soName, realSoPath);
571 13 : if (ret != AE_STATUS_SUCCESS) {
572 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "GetSoPath failed, soName[%s], ret[%u].", soName.c_str(), ret);
573 1 : return ret;
574 : }
575 12 : std::string soFile(realSoPath);
576 12 : (void)soFile.append(soName);
577 12 : AE_INFO_LOG(AE_MODULE_ID, "soname[%s]", soFile.c_str());
578 : // This thread get the lock and create the new single so Manager
579 12 : SingleSoManager* const newSSoMngr = new (std::nothrow) SingleSoManager();
580 12 : AE_MEMORY_LOG(
581 : AE_MODULE_ID, "MallocMemory, func=new, size=%zu, purpose=SingleSoManager object", sizeof(SingleSoManager));
582 12 : if (newSSoMngr == nullptr) {
583 0 : AE_ERR_LOG(AE_MODULE_ID, "Create newSSoMngr ptr failed");
584 0 : return AE_STATUS_INNER_ERROR;
585 : }
586 12 : ret = newSSoMngr->Init(realSoPath, soFile);
587 12 : if (ret != AE_STATUS_SUCCESS) {
588 7 : AE_RUN_INFO_LOG(
589 : AE_MODULE_ID, "So does not exist, try to load at another path. currentSoFile=%s.", soFile.c_str());
590 7 : if (realSoPath != AICPU_SO_ROOT_DIR) {
591 : // try to load so from /usr/lib64/aicpu_kernel/
592 7 : std::string oriPath = realSoPath;
593 7 : realSoPath = AICPU_SO_ROOT_DIR;
594 7 : soFile = realSoPath + soName;
595 7 : ret = newSSoMngr->Init(realSoPath, soFile);
596 7 : if (ret != AE_STATUS_SUCCESS) {
597 7 : ret = GetSoInHostPidPath(soName, oriPath, newSSoMngr, soFile);
598 : }
599 7 : }
600 : }
601 :
602 : // check init result
603 12 : if (ret != AE_STATUS_SUCCESS) {
604 7 : delete newSSoMngr;
605 7 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Single so manager init failed, soFile is %s.", soFile.c_str());
606 7 : return ret;
607 : }
608 : // Cache it so that we can get it from cache next time.
609 5 : soCacher_[soName] = newSSoMngr;
610 5 : soMgr = newSSoMngr;
611 5 : AE_INFO_LOG(AE_MODULE_ID, "Loaded so successfully, soFile=%s.", soFile.c_str());
612 5 : return AE_STATUS_SUCCESS;
613 13 : }
614 :
615 1 : aeStatus_t MultiSoManager::CloseSo(const std::string& soName)
616 : {
617 1 : if (soName.empty()) {
618 0 : AE_ERR_LOG(AE_MODULE_ID, "So name is empty.");
619 0 : return AE_STATUS_BAD_PARAM;
620 : }
621 :
622 1 : AE_RW_LOCK_WR_LOCK(&rwLock_);
623 1 : const auto iter = soCacher_.find(soName);
624 1 : if (iter != soCacher_.end()) {
625 1 : const SingleSoManager* const sSoMngr = iter->second;
626 1 : if (sSoMngr != nullptr) {
627 1 : delete sSoMngr;
628 : }
629 1 : (void)soCacher_.erase(iter);
630 : }
631 1 : AE_RW_LOCK_UN_LOCK(&rwLock_);
632 :
633 1 : return AE_STATUS_SUCCESS;
634 : }
635 :
636 7 : aeStatus_t MultiSoManager::GetSoInHostPidPath(
637 : const std::string& soName, std::string& oriPath, SingleSoManager* const newSSoMngr, std::string& soFile) const
638 : {
639 : aicpu::aicpuContext_t currentAicpuCtx;
640 7 : const aicpu::status_t status = aicpu::aicpuGetContext(¤tAicpuCtx);
641 7 : if (status != aicpu::AICPU_ERROR_NONE) {
642 0 : AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
643 0 : return AE_STATUS_INNER_ERROR;
644 : }
645 7 : oriPath.append(std::to_string(currentAicpuCtx.hostPid))
646 7 : .append("_")
647 14 : .append(std::to_string(currentAicpuCtx.deviceId))
648 7 : .append("/");
649 7 : soFile = oriPath + soName;
650 7 : AE_RUN_INFO_LOG(AE_MODULE_ID, "So does not exist, try to load at another path. currentSoFile=%s.", soFile.c_str());
651 7 : return newSSoMngr->Init(oriPath, soFile);
652 : }
653 : } // namespace cce
|