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 : #include <string>
11 : #include <vector>
12 : #include <sstream>
13 : #include <unistd.h>
14 : #include <dlfcn.h>
15 : #include <sys/file.h>
16 : #include <sys/ioctl.h>
17 : #include <exception>
18 : #include "core/aicpusd_interface_process.h"
19 : #include "core/aicpusd_event_process.h"
20 : #include "core/aicpusd_event_manager.h"
21 : #include "core/aicpusd_resource_limit.h"
22 : #include "core/aicpusd_worker.h"
23 : #include "aicpusd_profiler.h"
24 : #include "aicpusd_lastword.h"
25 : #include "common/aicpusd_args_parser.h"
26 : #include "aicpusd_util.h"
27 : #include "aicpusd_status.h"
28 : #include "aicpusd_common.h"
29 : #include "securec.h"
30 : #include "tsd.h"
31 : #include "aicpusd_weak_log.h"
32 : #include "driver/ascend_hal.h"
33 : #include "common/aicpusd_context.h"
34 : #include "aicpusd_mc2_maintenance_thread_api.h"
35 : #include "aicpusd_feature_ctrl.h"
36 : #include "aicpusd_cust_dump_process.h"
37 : #include "aicpusd_send_platform_Info_to_custom.h"
38 :
39 : namespace AicpuSchedule {
40 : namespace {
41 : constexpr int32_t SUCCESS_VALUE = 0;
42 : const std::string ERROR_MSG_INVALID_PARAM = "E39001";
43 : const std::string ERROR_MSG_DRV_ERROR = "E39002";
44 : const std::string ERROR_MSG_CGROUP_FAILED = "E30007";
45 : const std::string ERROR_MSG_AICPU_INIT_FAILED = "E39004";
46 : const std::string QUEUE_SCHEDULE_SO_NAME = "libqueue_schedule.so";
47 : void* g_qslibHandle = nullptr;
48 :
49 26 : void SetLogLevel(AicpuSchedule::ArgsParser& startParams)
50 : {
51 26 : if (&dlog_setlevel != nullptr) {
52 26 : if (dlog_setlevel(-1, startParams.GetLogLevel(), startParams.GetEventLevel()) != SUCCESS_VALUE) {
53 4 : aicpusd_warn("Set log level failed");
54 : }
55 26 : if ((startParams.GetCcecpuLogLevel() >= DEBUG_LOG) && (startParams.GetCcecpuLogLevel() <= ERROR_LOG)) {
56 0 : if (dlog_setlevel(CCECPU, startParams.GetCcecpuLogLevel(), startParams.GetEventLevel()) != SUCCESS_VALUE) {
57 0 : aicpusd_warn("Set ccecpu log level failed");
58 : }
59 : }
60 26 : if ((startParams.GetAicpuLogLevel() >= DEBUG_LOG) && (startParams.GetAicpuLogLevel() <= ERROR_LOG)) {
61 0 : if (dlog_setlevel(AICPU, startParams.GetAicpuLogLevel(), startParams.GetEventLevel()) != SUCCESS_VALUE) {
62 0 : aicpusd_warn("Set aicpu log level failed");
63 : }
64 : }
65 : }
66 26 : LogAttr logAttr = {};
67 26 : logAttr.type = APPLICATION;
68 26 : logAttr.pid = startParams.GetHostPid();
69 26 : logAttr.deviceId = startParams.GetDeviceId();
70 26 : logAttr.mode = 0;
71 26 : if (DlogSetAttrAicpu(logAttr) != SUCCESS_VALUE) {
72 1 : aicpusd_warn("Set log attr failed");
73 : }
74 26 : }
75 : /**
76 : * attach host group based on parameters send by tsd.
77 : * @param grpNameListStr group name list
78 : * @param grpNameNum group name number
79 : * @return true:success, false:failed
80 : */
81 20 : bool AttachHostGroup(const std::vector<std::string>& groupNameVec, const uint32_t grpNameNum)
82 : {
83 20 : if (grpNameNum == 0U) {
84 4 : aicpusd_info("There is not group need to be attached");
85 4 : return true;
86 : }
87 16 : if (groupNameVec.empty()) {
88 1 : aicpusd_err("Aicpu start failed. Wrong parameters of groupNum[%d] with empty group name", grpNameNum);
89 1 : return false;
90 : }
91 15 : if (static_cast<uint32_t>(groupNameVec.size()) != grpNameNum) {
92 1 : aicpusd_err(
93 : "Aicpu start failed. parse group name num[%d] is consistence with num[%u] in parameter",
94 : groupNameVec.size(), grpNameNum);
95 1 : return false;
96 : }
97 :
98 37 : for (size_t i = 0UL; i < groupNameVec.size(); ++i) {
99 24 : const auto drvRet = halGrpAttach(groupNameVec[i].c_str(), -1);
100 24 : if (drvRet != DRV_ERROR_NONE) {
101 1 : aicpusd_err("halGrpAttach group[%s] failed. ret[%d]", groupNameVec[i].c_str(), drvRet);
102 1 : return false;
103 : }
104 23 : aicpusd_run_info("halGrpAttach group[%s] successfully.", groupNameVec[i].c_str());
105 : }
106 13 : return true;
107 : }
108 :
109 9 : void ReportErrorMsg(const int32_t errCode, const uint32_t deviceId, const uint32_t hostPid, const uint32_t vfId)
110 : {
111 9 : std::string errStr;
112 9 : switch (errCode) {
113 1 : case AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID: {
114 1 : errStr = ERROR_MSG_INVALID_PARAM;
115 1 : break;
116 : }
117 3 : case AICPU_SCHEDULE_ERROR_DRV_ERR: {
118 3 : errStr = ERROR_MSG_DRV_ERROR;
119 3 : break;
120 : }
121 1 : case AICPU_SCHEDULE_ERROR_CGROUP_FAILED: {
122 1 : errStr = ERROR_MSG_CGROUP_FAILED;
123 1 : break;
124 : }
125 1 : case AICPU_SCHEDULE_ERROR_INIT_FAILED: {
126 1 : errStr = ERROR_MSG_AICPU_INIT_FAILED;
127 1 : break;
128 : }
129 3 : default: {
130 3 : errStr = ERROR_MSG_AICPU_INIT_FAILED;
131 3 : break;
132 : }
133 : }
134 9 : DlogFlushAicpu();
135 9 : sleep(1); // sleep 1s to avoid log loss
136 9 : const int32_t ret = TsdReportStartOrStopErrCode(
137 9 : deviceId, TSD_COMPUTE, hostPid, vfId, errStr.c_str(), static_cast<uint32_t>(errStr.size()));
138 9 : if (ret != 0) {
139 1 : aicpusd_err("TsdReportStartOrStopErrCode failed. ret[%d]", ret);
140 1 : sleep(1); // sleep 1s to avoid log loss
141 : }
142 :
143 9 : DlogFlushAicpu();
144 9 : }
145 :
146 17 : void SendPidQosMsgToTsd(const uint32_t pidQos, const uint32_t deviceId, const uint32_t hostPid, const uint32_t vfId)
147 : {
148 : TsdCapabilityMsgInfo qosPidMsg;
149 17 : qosPidMsg.subCapabityType = TSD_EVENT_GET_CAPABILITY;
150 17 : qosPidMsg.resultInfo = pidQos;
151 17 : ReportMsgToTsd(deviceId, TSD_COMPUTE, hostPid, vfId, reinterpret_cast<const char_t* const>(&qosPidMsg));
152 17 : }
153 :
154 17 : void RegQueueScheduleModuleCallBack()
155 : {
156 17 : g_qslibHandle = dlopen(QUEUE_SCHEDULE_SO_NAME.c_str(), RTLD_LAZY);
157 17 : if (g_qslibHandle == nullptr) {
158 9 : aicpusd_warn("cannot open %s", QUEUE_SCHEDULE_SO_NAME.c_str());
159 9 : return;
160 : }
161 :
162 : const SubProcEventCallBackFuncInfo startQsFunc =
163 8 : reinterpret_cast<SubProcEventCallBackFuncInfo>(dlsym(g_qslibHandle, "StartQueueScheduleModule"));
164 8 : if (startQsFunc == nullptr) {
165 1 : aicpusd_err("cannot find StartQueueScheduleModule");
166 1 : (void)dlclose(g_qslibHandle);
167 1 : g_qslibHandle = nullptr;
168 1 : return;
169 : }
170 :
171 : SubProcEventCallBackInfo startCallBackInfo;
172 7 : startCallBackInfo.callBackFunc = startQsFunc;
173 7 : startCallBackInfo.eventType = TSD_EVENT_START_QS_MODULE;
174 7 : int32_t ret = RegEventMsgCallBackFunc(&startCallBackInfo);
175 7 : if (ret != 0) {
176 2 : aicpusd_err("reg StartQueueScheduleModule failed");
177 2 : (void)dlclose(g_qslibHandle);
178 2 : g_qslibHandle = nullptr;
179 2 : return;
180 : }
181 :
182 : const SubProcEventCallBackFuncInfo stopQsFunc =
183 5 : reinterpret_cast<SubProcEventCallBackFuncInfo>(dlsym(g_qslibHandle, "StopQueueScheduleModule"));
184 5 : if (stopQsFunc == nullptr) {
185 1 : UnRegEventMsgCallBackFunc(TSD_EVENT_START_QS_MODULE);
186 1 : aicpusd_err("cannot find StopQueueScheduleModule");
187 1 : (void)dlclose(g_qslibHandle);
188 1 : g_qslibHandle = nullptr;
189 1 : return;
190 : }
191 :
192 : SubProcEventCallBackInfo stopCallBackInfo;
193 4 : stopCallBackInfo.callBackFunc = stopQsFunc;
194 4 : stopCallBackInfo.eventType = TSD_EVENT_STOP_QS_MODULE;
195 :
196 4 : ret = RegEventMsgCallBackFunc(&stopCallBackInfo);
197 4 : if (ret != 0) {
198 1 : UnRegEventMsgCallBackFunc(TSD_EVENT_START_QS_MODULE);
199 1 : aicpusd_err("reg StopQueueScheduleModule failed");
200 1 : (void)dlclose(g_qslibHandle);
201 1 : g_qslibHandle = nullptr;
202 1 : return;
203 : }
204 :
205 3 : aicpusd_run_info("Register queue schedule module callback successfully.");
206 3 : return;
207 : }
208 :
209 17 : void RegCreateMc2MantenanceThreadCallBack()
210 : {
211 17 : SubProcEventCallBackInfo createMc2MantenanceThreadInfo = {};
212 17 : createMc2MantenanceThreadInfo.callBackFunc = CreateMc2MantenanceThread;
213 17 : createMc2MantenanceThreadInfo.eventType = TSD_EVENT_START_MC2_THREAD;
214 17 : int32_t ret = RegEventMsgCallBackFunc(&createMc2MantenanceThreadInfo);
215 17 : if (ret != 0) {
216 3 : aicpusd_err("reg Create Mc2 Maintenance Thread failed");
217 3 : return;
218 : }
219 : }
220 :
221 17 : void RegCreateDatadumpThreadCallBack()
222 : {
223 17 : SubProcEventCallBackInfo createDatadumpThreadInfo = {};
224 17 : createDatadumpThreadInfo.callBackFunc = CreateDatadumpThread;
225 17 : createDatadumpThreadInfo.eventType = TSD_EVENT_START_UDF_DATADUMP_THREAD;
226 17 : int32_t ret = RegEventMsgCallBackFunc(&createDatadumpThreadInfo);
227 17 : if (ret != 0) {
228 3 : aicpusd_err("reg Create datadump Thread failed");
229 3 : return;
230 : }
231 : }
232 :
233 17 : void RegCustProcessLoadPlatformCallBack()
234 : {
235 17 : SubProcEventCallBackInfo sendLoadPlatformInfoToCustInfo = {};
236 17 : sendLoadPlatformInfoToCustInfo.callBackFunc = SendLoadPlatformInfoToCust;
237 17 : sendLoadPlatformInfoToCustInfo.eventType = TSD_EVENT_LOAD_PLATFORM_TO_CUST;
238 17 : int32_t ret = RegEventMsgCallBackFunc(&sendLoadPlatformInfoToCustInfo);
239 17 : if (ret != 0) {
240 3 : aicpusd_err("reg send load platform to cust failed");
241 3 : return;
242 : }
243 : }
244 :
245 16 : void StopQsSubModuleInAicpu(const uint32_t deviceId, const uint32_t hostPid, const uint32_t vfId)
246 : {
247 16 : if (g_qslibHandle == nullptr) {
248 13 : aicpusd_warn("cannot open so %s", QUEUE_SCHEDULE_SO_NAME.c_str());
249 14 : return;
250 : }
251 3 : TsdSubEventInfo eventInfo = {};
252 3 : eventInfo.deviceId = deviceId;
253 3 : eventInfo.hostPid = hostPid;
254 3 : eventInfo.vfId = vfId;
255 : const SubProcEventCallBackFuncInfo stopQsFunc =
256 3 : reinterpret_cast<SubProcEventCallBackFuncInfo>(dlsym(g_qslibHandle, "StopQueueScheduleModule"));
257 3 : if (stopQsFunc == nullptr) {
258 1 : aicpusd_err("cannot find StopQueueScheduleModule");
259 1 : (void)dlclose(g_qslibHandle);
260 1 : g_qslibHandle = nullptr;
261 1 : return;
262 : }
263 2 : const int32_t ret = stopQsFunc(&eventInfo);
264 2 : if (ret != 0) {
265 0 : aicpusd_err("StopQueueScheduleModule fail");
266 : }
267 2 : (void)dlclose(g_qslibHandle);
268 2 : g_qslibHandle = nullptr;
269 : }
270 :
271 32 : bool SendVfMsgToDrv(const uint32_t cmd, const uint32_t deviceId, const uint32_t vfId)
272 : {
273 32 : if (FeatureCtrl::IsVfMode(deviceId, vfId)) {
274 6 : const int32_t fd = open("/dev/qos", O_RDWR);
275 6 : if (fd < 0) {
276 4 : aicpusd_warn("no such file. error[%s],errorno[%d]", strerror(errno), errno);
277 4 : return false;
278 : }
279 : VfMsgInfo vfMsg;
280 2 : vfMsg.deviceId = deviceId;
281 2 : vfMsg.vfId = vfId;
282 2 : const auto ret = ioctl(fd, cmd, PtrToPtr<VfMsgInfo, void>(&vfMsg));
283 2 : if (ret != 0) {
284 0 : aicpusd_warn("ioctl failed, error[%s],errorno[%d]", strerror(errno), errno);
285 0 : (void)close(fd);
286 0 : return false;
287 : }
288 2 : (void)close(fd);
289 : }
290 28 : return true;
291 : }
292 :
293 1 : void CloseQslibHandle()
294 : {
295 1 : if (g_qslibHandle != nullptr) {
296 0 : (void)dlclose(g_qslibHandle);
297 0 : g_qslibHandle = nullptr;
298 0 : return;
299 : }
300 : }
301 : } // namespace
302 : } // namespace AicpuSchedule
303 :
304 : /**
305 : * main of compute process.
306 : * @param argc argv length
307 : * @param argv arg values
308 : * @return 0:success, other:failed
309 : */
310 : #ifndef aicpusd_UT
311 : int32_t main(int32_t argc, char* argv[])
312 : #else
313 39 : int32_t ComputeProcessMain(int32_t argc, char* argv[])
314 : #endif
315 : {
316 : try {
317 39 : AicpuSchedule::ArgsParser startParams;
318 39 : if (!startParams.ParseArgs(argc, argv)) {
319 13 : return -1;
320 : }
321 26 : AicpuSchedule::SetLogLevel(startParams);
322 26 : aicpusd_run_info("Start parameter. %s", startParams.GetParaParsedStr().c_str());
323 :
324 26 : const uint32_t vfId = startParams.GetVfId();
325 26 : const pid_t pid = startParams.GetHostPid();
326 26 : const uint32_t deviceId = startParams.GetDeviceId();
327 26 : const uint32_t aicpuProcNum = startParams.GetAicpuProcNum();
328 26 : AicpuSchedule::AicpuScheduleInterface::GetInstance().SetBatchLoadMode(aicpuProcNum);
329 26 : if (!AicpuSchedule::AddToCgroup(deviceId, vfId)) {
330 1 : AicpuSchedule::ReportErrorMsg(
331 : AicpuSchedule::AICPU_SCHEDULE_ERROR_CGROUP_FAILED, deviceId, static_cast<uint32_t>(pid), vfId);
332 1 : return -1;
333 : }
334 : // Make sure AicpusdLastword are created first,to ensure the last exit
335 25 : AicpuSchedule::AicpusdLastword::GetInstance();
336 25 : AicpuSchedule::AicpuProfiler::ProfilerAgentInit();
337 25 : AicpuSchedule::AicpuEventManager::GetInstance().InitEventMgr(false, true, 0U);
338 25 : std::vector<uint32_t> deviceVec(1, deviceId);
339 :
340 75 : int32_t ret = AicpuSchedule::AicpuScheduleInterface::GetInstance().InitAICPUScheduler(
341 50 : deviceVec, pid, startParams.GetPidSign(), startParams.GetProfilingMode(), vfId, true,
342 50 : startParams.GetHostProcName());
343 25 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
344 5 : aicpusd_err("Aicpu scheduler start failed, ret=%d", ret);
345 5 : AicpuSchedule::ReportErrorMsg(ret, deviceId, static_cast<uint32_t>(pid), vfId);
346 5 : (void)AicpuSchedule::AicpuScheduleInterface::GetInstance().StopAICPUScheduler(deviceVec, pid);
347 5 : return -1;
348 : }
349 :
350 20 : std::string libPath = "";
351 20 : (void)AicpuSchedule::AicpuUtil::GetEnvVal(AicpuSchedule::ENV_NAME_LD_LIBRARY_PATH, libPath);
352 20 : aicpusd_run_info("Aicpu schedule start successfully, LD_LIBRARY_PATH=%s", libPath.c_str());
353 :
354 : // start attach and init process.
355 : // Attach group before send success to make sure aicpusd own the authority to access mbuff send by RTS
356 20 : if (!AicpuSchedule::AttachHostGroup(startParams.GetGrpNameList(), startParams.GetGrpNameNum())) {
357 3 : aicpusd_err("AttachHostGroup execute failed.");
358 3 : AicpuSchedule::ReportErrorMsg(
359 : AicpuSchedule::AICPU_SCHEDULE_ERROR_DRV_ERR, deviceId, static_cast<uint32_t>(pid), vfId);
360 3 : return -1;
361 : }
362 :
363 17 : aicpusd_run_info("Aicpu schedule attach and init successfully.");
364 : // send pid qos to tsd current send default value 0 to tsd
365 17 : AicpuSchedule::SendPidQosMsgToTsd(
366 : static_cast<uint32_t>(PRIORITY_LEVEL1), deviceId, static_cast<uint32_t>(pid), vfId);
367 :
368 : // reg queue schedule start and stop callback func
369 17 : AicpuSchedule::RegQueueScheduleModuleCallBack();
370 17 : AicpuSchedule::RegCreateMc2MantenanceThreadCallBack();
371 17 : AicpuSchedule::RegCreateDatadumpThreadCallBack();
372 17 : AicpuSchedule::RegCustProcessLoadPlatformCallBack();
373 :
374 17 : const int32_t rspRet = StartupResponse(deviceVec[0U], TSD_COMPUTE, static_cast<uint32_t>(pid), vfId);
375 17 : if (rspRet != AicpuSchedule::SUCCESS_VALUE) {
376 1 : aicpusd_err("Aicpu startup response return not ok, error code[%d].", rspRet);
377 1 : AicpuSchedule::CloseQslibHandle();
378 1 : return -1;
379 : }
380 16 : aicpusd_run_info("Aicpu startup response return successfully.");
381 :
382 16 : (void)AicpuSchedule::SendVfMsgToDrv(VM_QOS_PROCESS_STARTUP, deviceId, vfId);
383 :
384 : // wait for shutdown
385 16 : const int32_t waitRet = WaitForShutDown(deviceVec[0U]);
386 16 : if (waitRet != AicpuSchedule::SUCCESS_VALUE) {
387 1 : aicpusd_err("wait for shut down return not ok return not ok, error code[%d].", waitRet);
388 1 : ret = -1;
389 : } else {
390 15 : aicpusd_info("wait for shut down return successfully.");
391 15 : ret = 0;
392 : }
393 :
394 16 : AicpuSchedule::StopQsSubModuleInAicpu(deviceId, static_cast<uint32_t>(pid), vfId);
395 16 : (void)AicpuSchedule::AicpuScheduleInterface::GetInstance().StopAICPUScheduler(deviceVec, pid);
396 16 : aicpusd_run_info("Aicpu schedule stopped");
397 :
398 16 : (void)AicpuSchedule::SendVfMsgToDrv(VM_QOS_PROCESS_SUSPEND, deviceId, vfId);
399 : // flush cache log to slogd
400 16 : DlogFlushAicpu();
401 16 : return ret;
402 39 : } catch (const std::exception& e) {
403 0 : aicpusd_err("Execute main failed, reason=%s", e.what());
404 0 : return -1;
405 0 : }
406 : }
|