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 <fstream>
12 : #include <algorithm>
13 : #include "profiling_adp.h"
14 : #include "aicpusd_util.h"
15 : #include "aicpusd_status.h"
16 : #include "aicpusd_profiler.h"
17 : #include "aicpusd_event_manager.h"
18 : #include "aicpusd_interface_process.h"
19 : #include "aicpusd_sub_module_interface.h"
20 :
21 : namespace AicpuSchedule {
22 : namespace {
23 : constexpr uint32_t MAX_PARAM_NUM = 12U;
24 : const std::string ERROR_MSG_INVALID_PARAM = "E39001";
25 : const std::string ERROR_MSG_DRV_ERROR = "E39002";
26 : const std::string ERROR_MSG_CGROUP_FAILED = "E30007";
27 : const std::string ERROR_MSG_AICPU_INIT_FAILED = "E39004";
28 : } // namespace
29 :
30 5 : int32_t SubModuleInterface::StartAicpuSchedulerModule(const struct TsdSubEventInfo * const eventInfo)
31 : {
32 5 : aicpusd_run_info("Enter aicpu schedule sub module start process.");
33 : // set event key
34 5 : SetTsdEventKey(eventInfo);
35 :
36 : // args parse
37 5 : ArgsParser startParas;
38 5 : if (!ParseArgsFromFile(startParas)) {
39 1 : aicpusd_err("Read aicpu submodule start paras from file failed");
40 1 : return -1;
41 : }
42 :
43 : // init aicpu
44 4 : AicpuProfiler::ProfilerAgentInit();
45 4 : AicpuEventManager::GetInstance().InitEventMgr(false, true, 0U);
46 4 : const std::vector<uint32_t> deviceVec(1, tsdEventKey_.deviceId);
47 12 : const int32_t ret = AicpuScheduleInterface::GetInstance().InitAICPUScheduler(deviceVec, tsdEventKey_.hostPid,
48 8 : startParas.GetPidSign(), startParas.GetProfilingMode(), tsdEventKey_.vfId, true);
49 4 : if (ret != AICPU_SCHEDULE_OK) {
50 1 : aicpusd_err("Aicpu schedule start failed, ret[%d].", ret);
51 1 : ReportErrMsgToTsd(ret);
52 1 : (void)AicpuScheduleInterface::GetInstance().StopAICPUScheduler(deviceVec,
53 1 : static_cast<pid_t>(tsdEventKey_.hostPid));
54 1 : return -1;
55 : }
56 :
57 3 : std::string libPath = "";
58 3 : (void)AicpuUtil::GetEnvVal(ENV_NAME_LD_LIBRARY_PATH, libPath);
59 3 : aicpusd_run_info("Aicpu schedule start success, LD_LIBRARY_PATH=%s.", libPath.c_str());
60 :
61 3 : if (!AttachHostGroup(startParas)) {
62 1 : aicpusd_err("AttachHostGroup execute failed.");
63 1 : ReportErrMsgToTsd(AICPU_SCHEDULE_ERROR_DRV_ERR);
64 1 : return -1;
65 : }
66 :
67 2 : SendPidQosMsgToTsd(static_cast<uint32_t>(PRIORITY_LEVEL1));
68 :
69 2 : const int32_t rspRet = SendSubModuleRsponse(TSD_EVENT_START_AICPU_SD_MODULE_RSP);
70 2 : if (rspRet != 0) {
71 1 : aicpusd_err("Aicpu startup response return not ok, error code[%d].", rspRet);
72 1 : return -1;
73 : }
74 :
75 1 : startFlag_ = true;
76 1 : aicpusd_run_info("Aicpu schedule sub module start success.");
77 1 : return 0;
78 5 : }
79 :
80 3 : int32_t SubModuleInterface::StopAicpuSchedulerModule(const struct TsdSubEventInfo *const eventInfo)
81 : {
82 3 : aicpusd_run_info("Enter aicpu schedule sub module stop process.");
83 3 : if (!startFlag_.load()) {
84 2 : aicpusd_run_info("No need to stop aicpu sub module.");
85 2 : return AICPU_SCHEDULE_SUCCESS;
86 : }
87 :
88 1 : SetTsdEventKey(eventInfo);
89 1 : const std::vector<uint32_t> deviceVec(1, tsdEventKey_.deviceId);
90 1 : (void)AicpuScheduleInterface::GetInstance().StopAICPUScheduler(deviceVec,
91 1 : static_cast<pid_t>(tsdEventKey_.hostPid));
92 1 : aicpusd_run_info("Aicpu schedule stopped.");
93 1 : const int32_t rspRet = SendSubModuleRsponse(TSD_EVENT_STOP_AICPU_SD_MODULE_RSP);
94 1 : if (rspRet != 0) {
95 1 : aicpusd_err("Aicpu stop response return not ok, error code[%d].", rspRet);
96 1 : return -1;
97 : }
98 :
99 0 : startFlag_ = false;
100 0 : aicpusd_run_info("Aicpu schedule sub module stop success.");
101 0 : return AICPU_SCHEDULE_SUCCESS;
102 1 : }
103 :
104 7 : void SubModuleInterface::SetTsdEventKey(const struct TsdSubEventInfo * const eventInfo)
105 : {
106 7 : tsdEventKey_.deviceId = eventInfo->deviceId;
107 7 : tsdEventKey_.hostPid = eventInfo->hostPid;
108 7 : tsdEventKey_.vfId = eventInfo->vfId;
109 7 : }
110 :
111 1 : bool SubModuleInterface::ParseArgsFromFile(ArgsParser &startParas) const
112 : {
113 1 : const std::string argsFilePath = BuildArgsFilePath();
114 2 : ScopeGuard fileDelGuard([&argsFilePath] () { DeleteArgsFile(argsFilePath); });
115 :
116 1 : std::ifstream argsFile;
117 1 : argsFile.open(argsFilePath, std::ifstream::in);
118 1 : if (!argsFile.is_open()) {
119 1 : aicpusd_err("Start file[%s] open failed, reason=%s", argsFilePath.c_str(), strerror(errno));
120 1 : return false;
121 : }
122 0 : ScopeGuard fileCloseGuard([&argsFile] () { argsFile.close(); });
123 :
124 0 : uint32_t item = 0U;
125 0 : std::vector<std::string> fileLines;
126 0 : std::string tempParam;
127 0 : while ((item < MAX_PARAM_NUM) && (getline(argsFile, tempParam))) {
128 0 : fileLines.emplace_back(tempParam);
129 0 : ++item;
130 : }
131 :
132 0 : return startParas.ParseArgs(fileLines);
133 1 : }
134 :
135 2 : std::string SubModuleInterface::BuildArgsFilePath() const
136 : {
137 2 : const uint32_t curPid = static_cast<uint32_t>(getpid());
138 4 : const std::string fileName = "aicpu_sd_start_param_" + std::to_string(tsdEventKey_.deviceId) +
139 6 : "_" + std::to_string(tsdEventKey_.vfId) + "_" + std::to_string(curPid);
140 4 : std::string pathFreFix = "/home/HwHiAiUser/";
141 4 : if (AicpuUtil::IsEnvValEqual(ENV_NAME_REG_ASCEND_MONITOR, "0")) {
142 0 : pathFreFix = "/home/mdc/";
143 : }
144 :
145 4 : return pathFreFix.append(fileName);
146 2 : }
147 :
148 3 : void SubModuleInterface::DeleteArgsFile(const std::string &argsFilePath)
149 : {
150 3 : const int32_t ret = remove(argsFilePath.c_str());
151 3 : if (ret != 0) {
152 1 : aicpusd_err("Remove file[%s] failed, ret=%d, reason=%s", argsFilePath.c_str(), ret, strerror(errno));
153 1 : return;
154 : }
155 :
156 2 : aicpusd_run_info("Remove file[%s] success", argsFilePath.c_str());
157 : }
158 :
159 6 : void SubModuleInterface::ReportErrMsgToTsd(const int32_t errCode) const
160 : {
161 : const std::map<int32_t, std::string> errStrMaps = {
162 : {AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID, ERROR_MSG_INVALID_PARAM},
163 : {AICPU_SCHEDULE_ERROR_DRV_ERR, ERROR_MSG_DRV_ERROR},
164 : {AICPU_SCHEDULE_ERROR_CGROUP_FAILED, ERROR_MSG_CGROUP_FAILED},
165 : {AICPU_SCHEDULE_ERROR_INIT_FAILED, ERROR_MSG_AICPU_INIT_FAILED}
166 36 : };
167 6 : std::string errStr = ERROR_MSG_AICPU_INIT_FAILED;
168 6 : const auto &iter = errStrMaps.find(errCode);
169 6 : if (iter != errStrMaps.end()) {
170 4 : errStr = iter->second;
171 : }
172 :
173 6 : const int32_t ret = TsdReportStartOrStopErrCode(tsdEventKey_.deviceId, TSD_COMPUTE, tsdEventKey_.hostPid,
174 6 : tsdEventKey_.vfId, errStr.c_str(),
175 6 : static_cast<uint32_t>(errStr.size()));
176 6 : if (ret != 0) {
177 4 : aicpusd_err("ReportErrorMsgToTsd failed. ret=%d", ret);
178 : }
179 12 : }
180 :
181 7 : bool SubModuleInterface::AttachHostGroup(const ArgsParser &startParas)
182 : {
183 : // Only attach group which is in aicpu group but not in qs group
184 7 : std::vector<std::string> grpNameList = startParas.GetGrpNameList();
185 7 : const std::vector<std::string> qsGrpNameList = startParas.GetQsGrpNameList();
186 21 : for (const auto &key : qsGrpNameList) {
187 14 : const auto iter = std::remove(grpNameList.begin(), grpNameList.end(), key);
188 14 : grpNameList.erase(iter, grpNameList.end());
189 : }
190 :
191 7 : const uint32_t grpNameNum = startParas.GetGrpNameNum();
192 7 : if ((grpNameNum == 0U) || (grpNameList.size() == 0UL)) {
193 3 : aicpusd_info("There is no group need to be attached");
194 3 : return true;
195 : }
196 :
197 4 : if (static_cast<uint32_t>(grpNameList.size()) > grpNameNum) {
198 1 : aicpusd_err("Aicpu start failed. Wrong parameters of groupNum[%d] with empty group name", grpNameNum);
199 1 : return false;
200 : }
201 :
202 6 : for (const std::string &iter : grpNameList) {
203 4 : const auto drvRet = halGrpAttach(iter.c_str(), -1);
204 4 : if (drvRet != DRV_ERROR_NONE) {
205 1 : aicpusd_err("halGrpAttach group[%s] failed. ret[%d]", iter.c_str(), drvRet);
206 1 : return false;
207 : }
208 3 : aicpusd_run_info("halGrpAttach group[%s] success.", iter.c_str());
209 : }
210 :
211 2 : return true;
212 7 : }
213 :
214 3 : void SubModuleInterface::SendPidQosMsgToTsd(const uint32_t pidQos) const
215 : {
216 : TsdCapabilityMsgInfo qosPidMsg;
217 3 : qosPidMsg.subCapabityType = TSD_EVENT_GET_CAPABILITY;
218 3 : qosPidMsg.resultInfo = pidQos;
219 3 : ReportMsgToTsd(tsdEventKey_.deviceId, TSD_COMPUTE, tsdEventKey_.hostPid, tsdEventKey_.vfId,
220 : PtrToPtr<TsdCapabilityMsgInfo, const char_t>(&qosPidMsg));
221 3 : }
222 :
223 2 : int32_t SubModuleInterface::SendSubModuleRsponse(const uint32_t eventType) const
224 : {
225 4 : return SubModuleProcessResponse(tsdEventKey_.deviceId, TSD_COMPUTE, tsdEventKey_.hostPid,
226 2 : tsdEventKey_.vfId, eventType);
227 : }
228 : } // namespace AicpuSchedule
229 :
230 : extern "C" {
231 5 : int32_t StartAicpuSchedulerModule(const struct TsdSubEventInfo *const eventInfo)
232 : {
233 5 : return AicpuSchedule::SubModuleInterface::GetInstance().StartAicpuSchedulerModule(eventInfo);
234 : }
235 :
236 3 : int32_t StopAicpuSchedulerModule(const struct TsdSubEventInfo *const eventInfo)
237 : {
238 3 : return AicpuSchedule::SubModuleInterface::GetInstance().StopAicpuSchedulerModule(eventInfo);
239 : }
240 : }
|