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 : }
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(AE_MODULE_ID, "Invalid so file with dir:%s so:%s, should be %s or %s",
138 : path.get(), soFile.c_str(), tmpGuardDirName.data(), realSoPath.c_str());
139 1 : return AE_STATUS_OPEN_SO_FAILED;
140 : }
141 3 : return AE_STATUS_SUCCESS;
142 32 : }
143 :
144 4 : std::string SingleSoManager::GetRealCustSoPath()
145 : {
146 : aicpu::aicpuContext_t currentAicpuCtx;
147 4 : (void)aicpu::aicpuGetContext(¤tAicpuCtx);
148 :
149 4 : const uint32_t uniqueVfId = aicpu::GetUniqueVfId();
150 :
151 4 : std::string soPath = CUST_USER_SO_PATH;
152 4 : GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
153 4 : (void)soPath.append("lib/");
154 4 : return soPath;
155 0 : }
156 :
157 7 : void SingleSoManager::GetCustSoPathByUniqueVfId(std::string &soPath, const uint32_t uniqueVfId)
158 : {
159 7 : if (uniqueVfId == DEFAULT_VFID) {
160 7 : (void)soPath.append("/");
161 0 : } else if (uniqueVfId >= VDEVICE_MIN_CPU_NUM && uniqueVfId < VDEVICE_MAX_CPU_NUM) {
162 0 : const uint32_t custNum = (uniqueVfId - VDEVICE_MIN_CPU_NUM) / DIV_NUM + 1U;
163 0 : (void)soPath.append(std::to_string(custNum)).append("/");
164 0 : } else {
165 0 : (void)soPath.append(std::to_string(uniqueVfId)).append("/");
166 : }
167 7 : }
168 :
169 13 : aeStatus_t SingleSoManager::OpenSo(const std::string &soFile, void ** const retHandle)
170 : {
171 : // Use API in glibc to open the so lib, load this so to process.
172 13 : std::unique_ptr<char_t []> path(new (std::nothrow) char_t[PATH_MAX]);
173 13 : if (path == nullptr) {
174 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Alloc memory for path failed.");
175 0 : return AE_STATUS_OPEN_SO_FAILED;
176 : }
177 :
178 13 : const auto eRet = memset_s(path.get(), PATH_MAX, 0, PATH_MAX);
179 13 : if (eRet != EOK) {
180 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Mem set error, ret=%d", eRet);
181 1 : return AE_STATUS_OPEN_SO_FAILED;
182 : }
183 :
184 12 : if (realpath(soFile.data(), path.get()) == nullptr) {
185 8 : AE_WARN_LOG(AE_MODULE_ID, "Format to realpath failed:[%s], path:[%s]", soFile.data(), path.get());
186 8 : return AE_STATUS_OPEN_SO_FAILED;
187 : }
188 :
189 4 : AE_INFO_LOG(AE_MODULE_ID, "Open so %s begin.", path.get());
190 4 : void * const handle = dlopen(path.get(), static_cast<int32_t>(
191 : (static_cast<uint32_t>(RTLD_LAZY))|(static_cast<uint32_t>(RTLD_GLOBAL))));
192 4 : if (handle == nullptr) {
193 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Open so %s failed with error:%s", path.get(), dlerror());
194 0 : return AE_STATUS_OPEN_SO_FAILED;
195 : }
196 :
197 4 : *retHandle = handle;
198 4 : AE_INFO_LOG(AE_MODULE_ID, "Open so %s success.", soFile.c_str());
199 4 : return AE_STATUS_SUCCESS;
200 13 : }
201 :
202 2 : aeStatus_t SingleSoManager::GetFunc(void * const soHandle, const char_t * const funcName, void ** const retFuncAddr)
203 : {
204 2 : void * const theFuncAddr = dlsym(soHandle, funcName);
205 2 : if (static_cast<bool>(unlikely((theFuncAddr == nullptr)))) {
206 1 : AE_ERR_LOG(AE_MODULE_ID, "Get funcAddr %s from handle is NULL: %s", funcName, dlerror());
207 1 : return AE_STATUS_GET_KERNEL_NAME_FAILED;
208 : }
209 1 : *retFuncAddr = theFuncAddr;
210 1 : return AE_STATUS_SUCCESS;
211 : }
212 :
213 127 : aeStatus_t SingleSoManager::GetApi(const char_t * const soNamePtr, const char_t * const funcName,
214 : void ** const funcAddrPtr)
215 : {
216 127 : if (static_cast<bool>(unlikely((soHandle_ == nullptr)))) {
217 3 : AE_RUN_WARN_LOG(AE_MODULE_ID, "soHandle_ is null, should be Init first.");
218 3 : return AE_STATUS_INNER_ERROR;
219 : }
220 :
221 124 : AE_RW_LOCK_RD_LOCK(&rwLock_);
222 248 : auto apiIter = apiCacher_.find(funcName);
223 124 : if (apiIter != apiCacher_.end()) {
224 116 : *funcAddrPtr = apiIter->second;
225 116 : AE_RW_LOCK_UN_LOCK(&rwLock_);
226 117 : return AE_STATUS_SUCCESS;
227 : }
228 7 : AE_RW_LOCK_UN_LOCK(&rwLock_);
229 :
230 7 : AE_RW_LOCK_WR_LOCK(&rwLock_);
231 14 : apiIter = apiCacher_.find(funcName);
232 7 : if (apiIter != apiCacher_.end()) {
233 0 : *funcAddrPtr = apiIter->second;
234 0 : AE_RW_LOCK_UN_LOCK(&rwLock_);
235 0 : return AE_STATUS_SUCCESS;
236 : }
237 :
238 : // get func
239 7 : void *theFuncAddr = nullptr;
240 7 : const aeStatus_t ret = GetFunc(soHandle_, funcName, &theFuncAddr);
241 7 : if (ret != AE_STATUS_SUCCESS) {
242 1 : AE_RW_LOCK_UN_LOCK(&rwLock_);
243 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Get func %s from so %s failed, ret[%u].", funcName, soNamePtr, ret);
244 1 : return ret;
245 : }
246 : // cache func
247 12 : apiCacher_[funcName] = theFuncAddr;
248 6 : *funcAddrPtr = theFuncAddr;
249 6 : AE_RW_LOCK_UN_LOCK(&rwLock_);
250 6 : AE_RUN_INFO_LOG(AE_MODULE_ID, "Get api %s from so %s success.", funcName, soNamePtr);
251 6 : return AE_STATUS_SUCCESS;
252 : }
253 :
254 3 : aeStatus_t SingleSoManager::GetApi(const char_t * const soFile, const char_t * const funcName,
255 : void ** const funcAddrPtr, void ** const retHandle)
256 : {
257 3 : void *handle = nullptr;
258 3 : const aeStatus_t retOpenSo = OpenSo(soFile, &handle);
259 3 : if ((retOpenSo == AE_STATUS_SUCCESS) && (handle != nullptr)) {
260 1 : void *theFuncAddr = nullptr;
261 1 : const aeStatus_t retGetFunc = GetFunc(handle, funcName, &theFuncAddr);
262 1 : if ((retGetFunc == AE_STATUS_SUCCESS) && (theFuncAddr != nullptr)) {
263 1 : *funcAddrPtr = theFuncAddr;
264 : }
265 :
266 1 : *retHandle = handle;
267 1 : return retGetFunc;
268 : }
269 :
270 2 : AE_ERR_LOG(AE_MODULE_ID, "Open so failed when get api, soFile[%s], ret[%u].", soFile, retOpenSo);
271 2 : return retOpenSo;
272 : }
273 :
274 55 : aeStatus_t SingleSoManager::CloseSo(void * const retHandle)
275 : {
276 55 : if (retHandle != nullptr) {
277 8 : const int32_t ret = dlclose(retHandle);
278 8 : if (ret != 0) {
279 1 : AE_ERR_LOG(AE_MODULE_ID, "Close so failed with error:%s", dlerror());
280 1 : return AE_STATUS_INNER_ERROR;
281 : } else {
282 7 : AE_DEBUG_LOG(AE_MODULE_ID, "Close success:");
283 7 : return AE_STATUS_SUCCESS;
284 : }
285 : }
286 47 : return AE_STATUS_SUCCESS;
287 : }
288 :
289 81 : MultiSoManager::~MultiSoManager()
290 : {
291 : // Step1. clear the critical section apiCacher_
292 81 : AE_RW_LOCK_WR_LOCK(&rwLock_);
293 84 : for (auto iter = soCacher_.begin(); iter != soCacher_.end(); ++iter) {
294 3 : const SingleSoManager * const soMngr = iter->second;
295 3 : if (soMngr != nullptr) {
296 3 : delete soMngr; // Release each SingleSoManager * stored in cache
297 : }
298 : }
299 81 : soCacher_.clear();
300 81 : AE_RW_LOCK_UN_LOCK(&rwLock_);
301 : // Step2. destroy the Read Write lock
302 81 : AE_RW_LOCK_DESTROY(&rwLock_);
303 81 : };
304 :
305 8 : aeStatus_t MultiSoManager::Init()
306 : {
307 8 : soCacher_.clear();
308 8 : const aicpu::status_t status = aicpu::GetAicpuRunMode(runMode_);
309 8 : if (status != aicpu::AICPU_ERROR_NONE) {
310 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Get aicpu runmode failed.");
311 1 : return AE_STATUS_INNER_ERROR;
312 : }
313 : // get aicpu so path
314 7 : const char_t * const innerDirName = getenv(AICPU_INNER_SO_PATH_ENV_VAR_NAME);
315 7 : if (innerDirName != nullptr) {
316 1 : const std::string str = innerDirName;
317 1 : const size_t len = str.length();
318 1 : if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
319 0 : AE_ERR_LOG(AE_MODULE_ID, "Length of inner so dir %zu is invalid.", len);
320 0 : return AE_STATUS_INNER_ERROR;
321 : }
322 1 : innerKernelPath_ = str;
323 1 : if (innerKernelPath_[innerKernelPath_.size() - 1UL] != '/') {
324 0 : (void)innerKernelPath_.append("/");
325 : }
326 1 : }
327 : // get cust aicpu so path
328 7 : const char_t * const custDirName = getenv(AICPU_CUSTOM_SO_PATH_ENV_VAR);
329 7 : if (custDirName != nullptr) {
330 1 : const std::string str = custDirName;
331 1 : const size_t len = str.length();
332 1 : if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
333 0 : AE_ERR_LOG(AE_MODULE_ID, "Length of cust so dir %zu is invalid.", len);
334 0 : return AE_STATUS_INNER_ERROR;
335 : }
336 1 : custKernelPath_ = str;
337 1 : if (custKernelPath_[custKernelPath_.size() - 1UL] != '/') {
338 0 : (void)custKernelPath_.append("/");
339 : }
340 1 : }
341 7 : return AE_STATUS_SUCCESS;
342 : }
343 :
344 125 : aeStatus_t MultiSoManager::GetApi(const aicpu::KernelType kernelType, const char_t * const soName,
345 : const char_t * const funcName, void ** const funcAddrPtr)
346 : {
347 125 : SingleSoManager *soMgr = nullptr;
348 125 : const aeStatus_t ret = LoadSo(kernelType, soName, soMgr);
349 125 : if ((ret != AE_STATUS_SUCCESS) || (soMgr == nullptr)) {
350 3 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Load so %s failed.", soName);
351 3 : return AE_STATUS_OPEN_SO_FAILED;
352 : }
353 122 : return soMgr->GetApi(soName, funcName, funcAddrPtr);
354 : }
355 :
356 12 : aeStatus_t MultiSoManager::GetSoPath(const aicpu::KernelType kernelType, const std::string &soName,
357 : std::string &soPath) const
358 : {
359 12 : if (kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM || kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM_KFC) {
360 0 : return GetCustSoPath(soPath);
361 : }
362 12 : return GetInnerSoPath(soName, soPath);
363 : }
364 :
365 11 : aeStatus_t MultiSoManager::GetThreadModeSoPath(std::string &soPath) const
366 : {
367 11 : const char_t * const innerDirName = getenv("HOME");
368 11 : if (innerDirName != nullptr) {
369 10 : const std::string str = innerDirName;
370 10 : const size_t len = str.length();
371 10 : if ((len == 0U) || (len >= static_cast<size_t>(PATH_MAX))) {
372 0 : AE_ERR_LOG(AE_MODULE_ID, "Length[%zu] of inner so dir is invalid.", len);
373 0 : return AE_STATUS_INNER_ERROR;
374 : }
375 10 : soPath = str;
376 10 : if (soPath[soPath.size() - 1UL] != '/') {
377 10 : (void)soPath.append("/");
378 : }
379 10 : (void)soPath.append(THREAD_MODE_SO_PATH_FIX).append("/")
380 20 : .append(std::to_string(aicpu::GetUniqueVfId())).append("/")
381 10 : .append(AICPU_SO_UNCOMPRESS_DIR).append("/");
382 10 : return AE_STATUS_SUCCESS;
383 10 : } else {
384 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Get HOME env failed, get thread mode so path failed.");
385 1 : return AE_STATUS_INNER_ERROR;
386 : }
387 : }
388 21 : aeStatus_t MultiSoManager::GetInnerSoPath(const std::string &soName, std::string &soPath) const
389 : {
390 : uint32_t runMode;
391 21 : aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
392 21 : if (status != aicpu::AICPU_ERROR_NONE) {
393 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
394 1 : return AE_STATUS_INNER_ERROR;
395 : }
396 :
397 : // aicpu kernel path for lhisi from env: ASCEND_AICPU_KERNEL_PATH
398 20 : if ((runMode == aicpu::AicpuRunMode::THREAD_MODE) && (!innerKernelPath_.empty())) {
399 1 : soPath = innerKernelPath_;
400 1 : return AE_STATUS_SUCCESS;
401 : }
402 :
403 : // libretr_kernels.so in /usr/lib64/aicpu_kernel/
404 19 : if (soName == RETR_KERNELS_SO_NAME) {
405 1 : soPath = AICPU_SO_ROOT_DIR;
406 1 : return AE_STATUS_SUCCESS;
407 : }
408 :
409 : // libhccl_operator_call.so in /usr/lib64/
410 18 : if ((soName == HCCL_KERNELS_SO_NAME) || (soName == BUILTIN_KERNELS_SO_NAME)) {
411 1 : soPath = AICPU_SO_ROOT_DIR_OLD_PATH;
412 1 : return AE_STATUS_SUCCESS;
413 : }
414 :
415 17 : if (runMode == aicpu::AicpuRunMode::THREAD_MODE) {
416 7 : if (GetThreadModeSoPath(soPath) == AE_STATUS_SUCCESS) {
417 7 : return AE_STATUS_SUCCESS;
418 : }
419 0 : AE_RUN_WARN_LOG(AE_MODULE_ID, "thread mode home path invalid use default path [%s].", soPath.c_str());
420 : }
421 : // get aicpu context
422 : aicpu::aicpuContext_t currentAicpuCtx;
423 10 : status = aicpu::aicpuGetContext(¤tAicpuCtx);
424 10 : if (status != aicpu::AICPU_ERROR_NONE) {
425 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
426 1 : return AE_STATUS_INNER_ERROR;
427 : }
428 : // libtf_kernels.so and libaicpu_kernels.so and libcpu_kernels.so and libpt_kernels.so path from context
429 9 : soPath = AICPU_SO_ROOT_DIR;
430 9 : (void)soPath.append(std::to_string(aicpu::GetUniqueVfId())).append("/").append(AICPU_SO_UNCOMPRESS_DIR).append("/");
431 :
432 9 : return AE_STATUS_SUCCESS;
433 : }
434 :
435 9 : aeStatus_t MultiSoManager::BuildCustSoPath(std::string &soPath, const uint32_t uniqueVfId) const
436 : {
437 : uint32_t runMode;
438 9 : const aicpu::status_t statusMode = aicpu::GetAicpuRunMode(runMode);
439 9 : if (statusMode != aicpu::AICPU_ERROR_NONE) {
440 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current aicpu ctx failed.");
441 1 : return AE_STATUS_INNER_ERROR;
442 : }
443 : // dc
444 8 : if (runMode == aicpu::AicpuRunMode::PROCESS_PCIE_MODE) {
445 1 : soPath = CUST_USER_SO_PATH;
446 1 : SingleSoManager::GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
447 7 : } else if (runMode == aicpu::AicpuRunMode::PROCESS_SOCKET_MODE) {
448 3 : const char_t * const custDirName = getenv("HOME");
449 3 : if (custDirName == nullptr) {
450 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current dir name by HOME in socket_mode failed.");
451 1 : return AE_STATUS_INNER_ERROR;
452 : }
453 2 : soPath = custDirName;
454 2 : AE_RUN_INFO_LOG(AE_MODULE_ID, "Get soPath[%s] in socket_mode", soPath.c_str());
455 2 : SingleSoManager::GetCustSoPathByUniqueVfId(soPath, uniqueVfId);
456 : } else {
457 4 : const char_t * const curDirName = getenv("HOME");
458 4 : if (curDirName == nullptr) {
459 2 : AE_ERR_LOG(AE_MODULE_ID, "Get current home directory failed.");
460 3 : return AE_STATUS_INNER_ERROR;
461 : }
462 2 : const std::string dirName = curDirName;
463 2 : const size_t len = dirName.length();
464 2 : if ((len == 0LU) || (len >= static_cast<size_t>(PATH_MAX))) {
465 1 : AE_ERR_LOG(AE_MODULE_ID, "Length of current dir name %zu is invalid.", len);
466 1 : return AE_STATUS_INNER_ERROR;
467 : }
468 1 : soPath = dirName;
469 1 : if (soPath[soPath.size() - 1LU] != '/') {
470 1 : (void)soPath.append("/");
471 : }
472 2 : }
473 4 : return AE_STATUS_SUCCESS;
474 : }
475 :
476 8 : aeStatus_t MultiSoManager::GetCustSoPath(std::string &soPath) const
477 : {
478 : // get aicpu context
479 : aicpu::aicpuContext_t currentAicpuCtx;
480 8 : const aicpu::status_t status = aicpu::aicpuGetContext(¤tAicpuCtx);
481 8 : if (status != aicpu::AICPU_ERROR_NONE) {
482 1 : AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
483 1 : return AE_STATUS_INNER_ERROR;
484 : }
485 7 : const uint32_t uniqueVfId = aicpu::GetUniqueVfId();
486 : // minirc or ctrlcpu, cust so load in current user root path; else, so load in cust aicpu_sd thread
487 : // lhisi, so load path from env ASCEND_CUST_AICPU_KERNEL_PATH
488 7 : if (!custKernelPath_.empty()) {
489 0 : soPath = custKernelPath_;
490 : } else {
491 7 : const auto ret = BuildCustSoPath(soPath, uniqueVfId);
492 7 : if (ret != AE_STATUS_SUCCESS) {
493 4 : AE_ERR_LOG(AE_MODULE_ID, "BuildCustSoPath failed.");
494 4 : return ret;
495 : }
496 : }
497 3 : (void)soPath.append(CUSTOM_SO_DIR_NAME_PREFIX)
498 3 : .append(std::to_string(currentAicpuCtx.deviceId)).append("_")
499 6 : .append(std::to_string(uniqueVfId)).append("_")
500 3 : .append(std::to_string(static_cast<int32_t>(currentAicpuCtx.hostPid))).append("/");
501 3 : return AE_STATUS_SUCCESS;
502 : }
503 :
504 8 : aeStatus_t MultiSoManager::LoadSo(const aicpu::KernelType kernelType, const std::string &soName)
505 : {
506 8 : SingleSoManager *soMgr = nullptr;
507 16 : return LoadSo(kernelType, soName, soMgr);
508 : }
509 :
510 133 : aeStatus_t MultiSoManager::LoadSo(const aicpu::KernelType kernelType,
511 : const std::string &soName, SingleSoManager *&soMgr)
512 : {
513 133 : if (soName.empty()) {
514 1 : AE_ERR_LOG(AE_MODULE_ID, "So name is empty.");
515 1 : return AE_STATUS_BAD_PARAM;
516 : }
517 :
518 132 : if (!aicpu::IsCustAicpuSd()) {
519 132 : if ((runMode_ != aicpu::AicpuRunMode::THREAD_MODE) && ((kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM) ||
520 : (kernelType == aicpu::KERNEL_TYPE_AICPU_CUSTOM_KFC))) {
521 1 : AE_ERR_LOG(AE_MODULE_ID, "runmode is not THREAD_MODE AND kernelType is [%u]", kernelType);
522 1 : return AE_STATUS_BAD_PARAM;
523 : }
524 : }
525 :
526 131 : AE_RW_LOCK_RD_LOCK(&rwLock_);
527 131 : auto soIter = soCacher_.find(soName);
528 130 : if ((soCacher_.end() != soIter) && (soIter->second != nullptr)) {
529 117 : soMgr = soIter->second;
530 117 : AE_RW_LOCK_UN_LOCK(&rwLock_);
531 118 : return AE_STATUS_SUCCESS;
532 : }
533 13 : AE_RW_LOCK_UN_LOCK(&rwLock_);
534 :
535 13 : AE_RW_LOCK_WR_LOCK(&rwLock_);
536 13 : soIter = soCacher_.find(soName);
537 13 : if ((soCacher_.end() != soIter) && (soIter->second != nullptr)) {
538 0 : soMgr = soIter->second;
539 0 : AE_RW_LOCK_UN_LOCK(&rwLock_);
540 0 : return AE_STATUS_SUCCESS;
541 : }
542 13 : const auto ret = CreateSingleSoMgr(kernelType, soName, soMgr);
543 13 : if (ret != AE_STATUS_SUCCESS) {
544 8 : AE_RW_LOCK_UN_LOCK(&rwLock_);
545 8 : AE_RUN_WARN_LOG(AE_MODULE_ID, "CreateSingleSoMgr failed, soName[%s], ret[%u].", soName.c_str(), ret);
546 8 : return ret;
547 : }
548 5 : AE_RW_LOCK_UN_LOCK(&rwLock_);
549 5 : return AE_STATUS_SUCCESS;
550 : }
551 :
552 13 : aeStatus_t MultiSoManager::CreateSingleSoMgr(const aicpu::KernelType kernelType,
553 : const std::string &soName, SingleSoManager *&soMgr)
554 : {
555 : // check so name
556 13 : if (soName.find_first_not_of(PATTERN_FOR_SO_NAME) != std::string::npos) {
557 0 : AE_ERR_LOG(AE_MODULE_ID, "So name %s is not invalid. Please check!", soName.c_str());
558 0 : return AE_STATUS_BAD_PARAM;
559 : }
560 : // get so real path
561 13 : std::string realSoPath;
562 13 : auto ret = GetSoPath(kernelType, soName, realSoPath);
563 13 : if (ret != AE_STATUS_SUCCESS) {
564 1 : AE_RUN_WARN_LOG(AE_MODULE_ID, "GetSoPath failed, soName[%s], ret[%u].", soName.c_str(), ret);
565 1 : return ret;
566 : }
567 12 : std::string soFile(realSoPath);
568 12 : (void)soFile.append(soName);
569 12 : AE_INFO_LOG(AE_MODULE_ID, "soname[%s]", soFile.c_str());
570 : // This thread get the lock and create the new single so Manager
571 12 : SingleSoManager * const newSSoMngr = new(std::nothrow) SingleSoManager();
572 12 : AE_MEMORY_LOG(AE_MODULE_ID, "MallocMemory, func=new, size=%zu, purpose=SingleSoManager object",
573 : sizeof(SingleSoManager));
574 12 : if (newSSoMngr == nullptr) {
575 0 : AE_ERR_LOG(AE_MODULE_ID, "Create newSSoMngr ptr failed");
576 0 : return AE_STATUS_INNER_ERROR;
577 : }
578 12 : ret = newSSoMngr->Init(realSoPath, soFile);
579 12 : if (ret != AE_STATUS_SUCCESS) {
580 7 : AE_RUN_INFO_LOG(AE_MODULE_ID, "So does not exist, try to load at another path. currentSoFile=%s.", soFile.c_str());
581 7 : if (realSoPath != AICPU_SO_ROOT_DIR) {
582 : // try to load so from /usr/lib64/aicpu_kernel/
583 7 : std::string oriPath = realSoPath;
584 7 : realSoPath = AICPU_SO_ROOT_DIR;
585 7 : soFile = realSoPath + soName;
586 7 : ret = newSSoMngr->Init(realSoPath, soFile);
587 7 : if (ret != AE_STATUS_SUCCESS) {
588 7 : ret = GetSoInHostPidPath(soName, oriPath, newSSoMngr, soFile);
589 : }
590 7 : }
591 : }
592 :
593 : // check init result
594 12 : if (ret != AE_STATUS_SUCCESS) {
595 7 : delete newSSoMngr;
596 7 : AE_RUN_WARN_LOG(AE_MODULE_ID, "Single so manager init failed, soFile is %s.", soFile.c_str());
597 7 : return ret;
598 : }
599 : // Cache it so that we can get it from cache next time.
600 5 : soCacher_[soName] = newSSoMngr;
601 5 : soMgr = newSSoMngr;
602 5 : AE_INFO_LOG(AE_MODULE_ID, "Loaded so successfully, soFile=%s.", soFile.c_str());
603 5 : return AE_STATUS_SUCCESS;
604 13 : }
605 :
606 1 : aeStatus_t MultiSoManager::CloseSo(const std::string &soName)
607 : {
608 1 : if (soName.empty()) {
609 0 : AE_ERR_LOG(AE_MODULE_ID, "So name is empty.");
610 0 : return AE_STATUS_BAD_PARAM;
611 : }
612 :
613 1 : AE_RW_LOCK_WR_LOCK(&rwLock_);
614 1 : const auto iter = soCacher_.find(soName);
615 1 : if (iter != soCacher_.end()) {
616 1 : const SingleSoManager * const sSoMngr = iter->second;
617 1 : if (sSoMngr != nullptr) {
618 1 : delete sSoMngr;
619 : }
620 1 : (void)soCacher_.erase(iter);
621 : }
622 1 : AE_RW_LOCK_UN_LOCK(&rwLock_);
623 :
624 1 : return AE_STATUS_SUCCESS;
625 : }
626 :
627 7 : aeStatus_t MultiSoManager::GetSoInHostPidPath(const std::string &soName, std::string &oriPath,
628 : SingleSoManager * const newSSoMngr, std::string &soFile) const
629 : {
630 : aicpu::aicpuContext_t currentAicpuCtx;
631 7 : const aicpu::status_t status = aicpu::aicpuGetContext(¤tAicpuCtx);
632 7 : if (status != aicpu::AICPU_ERROR_NONE) {
633 0 : AE_ERR_LOG(AE_MODULE_ID, "Get current ctx failed.");
634 0 : return AE_STATUS_INNER_ERROR;
635 : }
636 7 : oriPath.append(std::to_string(currentAicpuCtx.hostPid)).append("_").
637 7 : append(std::to_string(currentAicpuCtx.deviceId)).append("/");
638 7 : soFile = oriPath + soName;
639 7 : AE_RUN_INFO_LOG(AE_MODULE_ID, "So does not exist, try to load at another path. currentSoFile=%s.",
640 : soFile.c_str());
641 7 : return newSSoMngr->Init(oriPath, soFile);
642 : }
643 : }
|