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 "aicpu_cust_sd_mc2_maintenance_thread.h"
11 : #include <cstring>
12 : #include <sched.h>
13 : #include <semaphore.h>
14 : #include "aicpusd_drv_manager.h"
15 : #include "aicpusd_info.h"
16 : #include "aicpusd_util.h"
17 : #include "aicpusd_status.h"
18 : #include "aicpu_cust_sd_proc_mgr_sys_operator_agent.h"
19 : #include "aicpusd_interface_process.h"
20 : #include "tsd.h"
21 : #include "aicpu_cust_sd_mc2_maintenance_thread_api.h"
22 :
23 :
24 : namespace AicpuSchedule {
25 : const uint32_t DEFAULT_GROUP_ID_TO_TSD_CLIENT = 30U;
26 59 : AicpuCustMc2MaintenanceThread &AicpuCustMc2MaintenanceThread::GetInstance(uint32_t type)
27 : {
28 59 : if (type == 0) {
29 58 : static AicpuCustMc2MaintenanceThread instance(type);
30 58 : return instance;
31 : }
32 1 : static AicpuCustMc2MaintenanceThread instance(type);
33 1 : return instance;
34 : }
35 :
36 3 : AicpuCustMc2MaintenanceThread::~AicpuCustMc2MaintenanceThread()
37 : {
38 3 : UnitCustMc2MaintenanceProcess();
39 3 : if (processThread_.joinable()) {
40 1 : processThread_.join();
41 : }
42 3 : }
43 :
44 2 : AicpuCustMc2MaintenanceThread::AicpuCustMc2MaintenanceThread(uint32_t type)
45 2 : : initFlag_(false),
46 2 : threadId_(0LU),
47 2 : processEventFuncPtr_(nullptr),
48 2 : processEventFuncParam_(nullptr),
49 2 : stopProcessEventFuncPtr_(nullptr),
50 2 : stopProcessEventFuncParam_(nullptr),
51 2 : type_(type)
52 : {
53 2 : }
54 2 : void AicpuCustMc2MaintenanceThread::SendCustMc2CreateThreadMsgToMain() const
55 : {
56 2 : TsdSubEventInfo msg = {};
57 2 : event_summary eventInfo = {};
58 2 : eventInfo.pid = static_cast<pid_t>(getpid());
59 2 : eventInfo.grp_id = DEFAULT_GROUP_ID_TO_TSD_CLIENT;
60 2 : eventInfo.dst_engine = CCPU_DEVICE;
61 2 : eventInfo.event_id = EVENT_CCPU_CTRL_MSG;
62 2 : eventInfo.subevent_id = TSD_EVENT_START_MC2_THREAD;
63 2 : eventInfo.msg_len = sizeof(TsdSubEventInfo);
64 2 : eventInfo.msg = PtrToPtr<TsdSubEventInfo, char_t>(&msg);
65 2 : struct CreateCtrlThreadArgs *createCtrlThreadArgsPtr = PtrToPtr<char_t, struct CreateCtrlThreadArgs>(msg.priMsg);
66 2 : createCtrlThreadArgsPtr->type = type_;
67 :
68 2 : uint32_t deviceId = AicpuDrvManager::GetInstance().GetDeviceId();
69 2 : const drvError_t ret = halEschedSubmitEvent(deviceId, &eventInfo);
70 2 : if (ret != DRV_ERROR_NONE) {
71 1 : aicpusd_err("Failed to submit, eventId: [%d], ret: [%d].", TSD_EVENT_START_MC2_THREAD, ret);
72 : }
73 :
74 4 : return;
75 : }
76 :
77 3 : int32_t AicpuCustMc2MaintenanceThread::CreateCustMc2MaintenanceThread()
78 : {
79 3 : if (initFlag_) {
80 1 : aicpusd_info("the thread no need to multiple init, threadId[%llu]", threadId_);
81 1 : return AICPU_SCHEDULE_OK;
82 : }
83 : try {
84 2 : if (processThread_.joinable()) {
85 1 : aicpusd_run_info("processThread join begin, threadId[%llu]", threadId_);
86 1 : processThread_.join();
87 1 : aicpusd_run_info("processThread join end, threadId[%llu]", threadId_);
88 : }
89 2 : processThread_ = std::thread(&AicpuCustMc2MaintenanceThread::StartProcessEvent, this);
90 0 : } catch (std::exception &e) {
91 0 : aicpusd_err("create thread file:%s", e.what());
92 0 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
93 0 : }
94 2 : return AICPU_SCHEDULE_OK;
95 : }
96 :
97 13 : int32_t AicpuCustMc2MaintenanceThread::InitCustMc2MaintenanceProcess(AicpuMC2MaintenanceFuncPtr loopFun,
98 : void *paramLoopFun, AicpuMC2MaintenanceFuncPtr stopNotifyFun, void *paramStopFun)
99 : {
100 13 : aicpusd_info("init cust mc2 maintenance process start, type[%u]", type_);
101 : uint32_t runMode;
102 13 : const aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
103 13 : if (status != aicpu::AICPU_ERROR_NONE) {
104 1 : aicpusd_err("Get current aicpu ctx failed. type[%u]", type_);
105 1 : return AICPU_SCHEDULE_ERROR_INNER_ERROR;
106 : }
107 12 : if (runMode != aicpu::AicpuRunMode::PROCESS_PCIE_MODE) {
108 2 : aicpusd_info("not pcie mode no need this thread type[%u]", type_);
109 2 : return AICPU_SCHEDULE_NOT_SUPPORT;
110 : }
111 10 : const std::lock_guard<std::mutex> lk(initMutex_);
112 10 : if (initFlag_) {
113 2 : aicpusd_info("the thread is already init, threadId[%llu], type[%u]", threadId_, type_);
114 2 : return AICPU_SCHEDULE_THREAD_ALREADY_EXISTS;
115 : }
116 8 : int32_t ret = 0;
117 8 : ret = RegisterProcessEventFunc(loopFun, paramLoopFun);
118 8 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
119 3 : return ret;
120 : }
121 5 : ret = RegisterStopProcessEventFunc(stopNotifyFun, paramStopFun);
122 5 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
123 2 : return ret;
124 : }
125 3 : const int32_t semRet = sem_init(&workerSme_, 0, 0U);
126 3 : if (semRet == -1) {
127 0 : aicpusd_err("workerSme_ init failed, type[%u], %s", type_, strerror(errno));
128 0 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
129 : }
130 3 : SendCustMc2CreateThreadMsgToMain();
131 3 : const int32_t semWaitRet = sem_wait(&workerSme_);
132 3 : if (semWaitRet == -1) {
133 1 : sem_destroy(&workerSme_);
134 1 : aicpusd_err("workerSme wait failed, type[%u], %s", type_, strerror(errno));
135 1 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
136 : }
137 2 : sem_destroy(&workerSme_);
138 2 : initFlag_ = true;
139 2 : aicpusd_info("init cust mc2 maintenance process finish. type[%u]", type_);
140 2 : return AICPU_SCHEDULE_OK;
141 10 : }
142 :
143 8 : int32_t AicpuCustMc2MaintenanceThread::SetCustMc2MaintenanceThreadAffinity()
144 : {
145 8 : std::vector<uint32_t> ccpuIds = AicpuDrvManager::GetInstance().GetCcpuList();
146 8 : if (ccpuIds.empty()) {
147 3 : aicpusd_run_info("ccpu list is empty no need bind core");
148 3 : return AICPU_SCHEDULE_OK;
149 : }
150 10 : if (AicpuUtil::IsEnvValEqual(ENV_NAME_PROCMGR_AICPU_CPUSET, "1")) {
151 1 : aicpusd_err("the chip is not supported, please check. type[%u]", type_);
152 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
153 : } else {
154 4 : pthread_t threadId = pthread_self();
155 4 : threadId_ = GetTid();
156 : cpu_set_t cpuset;
157 20 : for (const auto cpuId: ccpuIds) {
158 16 : CPU_SET(cpuId, &cpuset);
159 16 : aicpusd_info("prepare bind threadId=%lu to cpuId=%u, type=%u", threadId, static_cast<uint32_t>(cpuId), type_);
160 : }
161 4 : const int32_t ret = pthread_setaffinity_np(threadId, sizeof(cpu_set_t), &cpuset);
162 4 : if (ret != 0) {
163 2 : aicpusd_err("aicpu bind tid by self, res[%d], error[%s]. type[%u]", ret, strerror(errno), type_);
164 2 : return AICPU_SCHEDULE_ERROR_INNER_ERROR;
165 : } else {
166 2 : aicpusd_run_info("aicpu bind by self success. type[%u]", type_);
167 2 : return AICPU_SCHEDULE_OK;
168 : }
169 : }
170 8 : }
171 3 : void AicpuCustMc2MaintenanceThread::StartProcessEvent()
172 : {
173 3 : if (SetCustMc2MaintenanceThreadAffinity() != AICPU_SCHEDULE_OK) {
174 1 : aicpusd_err("CustMc2 Maintenance thread bind core failed. type[%u]", type_);
175 1 : sem_post(&workerSme_);
176 1 : return;
177 : }
178 2 : sem_post(&workerSme_);
179 2 : aicpusd_run_info("post work sem finish. type[%u]", type_);
180 2 : ProcessEventFunc();
181 2 : ClearCustMc2MaintenanceProcess();
182 2 : aicpusd_run_info("CustMc2 thread ProcessEventFunc finished. type[%u]", type_);
183 : }
184 3 : void AicpuCustMc2MaintenanceThread::ProcessEventFunc() const
185 : {
186 3 : if (processEventFuncPtr_ == nullptr) {
187 3 : aicpusd_err("the processEventFuncPtr not register. type[%u]", type_);
188 3 : return;
189 : }
190 0 : processEventFuncPtr_(processEventFuncParam_);
191 : }
192 :
193 2 : void AicpuCustMc2MaintenanceThread::ClearCustMc2MaintenanceProcess()
194 : {
195 2 : aicpusd_info("ClearCustMc2MaintenanceProcess start. type[%u]", type_);
196 2 : processEventFuncPtr_ = nullptr;
197 2 : processEventFuncParam_ = nullptr;
198 2 : stopProcessEventFuncPtr_ = nullptr;
199 2 : stopProcessEventFuncParam_ = nullptr;
200 2 : initFlag_ = false;
201 2 : aicpusd_info("ClearCustMc2MaintenanceProcess finish. type[%u]", type_);
202 2 : }
203 :
204 6 : void AicpuCustMc2MaintenanceThread::StopProcessEventFunc() const
205 : {
206 : // 调用结束回调
207 6 : if (stopProcessEventFuncPtr_ == nullptr) {
208 3 : aicpusd_err("the stopProcessEventFuncPtr not register. type[%u]", type_);
209 3 : return;
210 : }
211 3 : stopProcessEventFuncPtr_(stopProcessEventFuncParam_);
212 : }
213 :
214 5 : void AicpuCustMc2MaintenanceThread::UnitCustMc2MaintenanceProcess()
215 : {
216 5 : aicpusd_info("UnitCustMc2MaintenanceProcess start. type[%u]", type_);
217 5 : const std::lock_guard<std::mutex> lk(initMutex_);
218 5 : if (!initFlag_) {
219 2 : aicpusd_info("the thread is already stop");
220 2 : return;
221 : }
222 3 : StopProcessEventFunc();
223 3 : aicpusd_info("StopProcessEventFunc finished. type[%u]", type_);
224 3 : processEventFuncPtr_ = nullptr;
225 3 : processEventFuncParam_ = nullptr;
226 3 : stopProcessEventFuncPtr_ = nullptr;
227 3 : stopProcessEventFuncParam_ = nullptr;
228 3 : initFlag_ = false;
229 3 : aicpusd_info("UnitCustMc2MaintenanceProcess finish. type[%u]", type_);
230 5 : }
231 8 : int32_t AicpuCustMc2MaintenanceThread::RegisterProcessEventFunc(AicpuMC2MaintenanceFuncPtr funPtr, void *param)
232 : {
233 8 : if (funPtr == nullptr) {
234 3 : aicpusd_err("the process funPtr is null. type[%u]", type_);
235 3 : return AICPU_SCHEDULE_PARAMETER_IS_NULL;
236 : }
237 5 : processEventFuncPtr_ = funPtr;
238 5 : processEventFuncParam_ = param;
239 5 : return AICPU_SCHEDULE_OK;
240 : }
241 :
242 5 : int32_t AicpuCustMc2MaintenanceThread::RegisterStopProcessEventFunc(AicpuMC2MaintenanceFuncPtr funPtr, void *param)
243 : {
244 5 : if (funPtr == nullptr) {
245 2 : aicpusd_err("the stop funPtr is null. type[%u]", type_);
246 2 : return AICPU_SCHEDULE_PARAMETER_IS_NULL;
247 : }
248 3 : stopProcessEventFuncPtr_ = funPtr;
249 3 : stopProcessEventFuncParam_ = param;
250 3 : return AICPU_SCHEDULE_OK;
251 : }
252 : }
253 2 : int32_t CreateCustMc2MaintenanceThread(const struct TsdSubEventInfo * const msg)
254 : {
255 2 : if (msg == nullptr) {
256 1 : aicpusd_err("msg is null");
257 1 : return AicpuSchedule::AICPU_SCHEDULE_ERROR_INNER_ERROR;
258 : }
259 1 : const struct AicpuSchedule::CreateCtrlThreadArgs *createCtrlThreadArgsPtr = PtrToPtr<const char_t, const struct AicpuSchedule::CreateCtrlThreadArgs>(msg->priMsg);
260 1 : if (createCtrlThreadArgsPtr == nullptr) {
261 0 : aicpusd_err("args ptr is null");
262 0 : return AicpuSchedule::AICPU_SCHEDULE_ERROR_INNER_ERROR;
263 : }
264 : (void)msg;
265 1 : uint32_t type = createCtrlThreadArgsPtr->type;
266 1 : aicpusd_info("aicpu create ctrl thread type[%u]", type);
267 1 : int32_t ret = AicpuSchedule::AicpuCustMc2MaintenanceThread::GetInstance(type).CreateCustMc2MaintenanceThread();
268 1 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
269 1 : aicpusd_err("Create Cust Mc2 Maintenance Thread failed, ret[%d], type[%u]", ret, type);
270 1 : return ret;
271 : }
272 0 : return AicpuSchedule::AICPU_SCHEDULE_OK;
273 : }
274 :
275 : #ifdef __cplusplus
276 : extern "C" {
277 : #endif // __cplusplus
278 13 : int32_t StartMC2MaintenanceThread(AicpuMC2MaintenanceFuncPtr loopFun,
279 : void *paramLoopFun, AicpuMC2MaintenanceFuncPtr stopNotifyFun, void *paramStopFun)
280 : {
281 13 : int32_t ret = AicpuSchedule::AicpuCustMc2MaintenanceThread::GetInstance(THREAD_TYPE_HCOM).InitCustMc2MaintenanceProcess(loopFun,
282 : paramLoopFun, stopNotifyFun, paramStopFun);
283 13 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
284 11 : return ret;
285 : }
286 2 : return AicpuSchedule::AICPU_SCHEDULE_OK;
287 : }
288 0 : int32_t AicpuCreateCtrlThread(uint32_t type, AicpuMC2MaintenanceFuncPtr loopFun,
289 : void *paramLoopFun, AicpuMC2MaintenanceFuncPtr stopNotifyFun, void *paramStopFun)
290 : {
291 0 : if ((type != THREAD_TYPE_HCOM) && (type != THREAD_TYPE_ASCPP_PROF)) {
292 0 : aicpusd_err("Aicpu create ctrl thread failed, type is [%u], only support [0-1]", type);
293 0 : return AICPU_SCHEDULE_NOT_SUPPORT;
294 : }
295 0 : int32_t ret = AicpuSchedule::AicpuCustMc2MaintenanceThread::GetInstance(type).InitCustMc2MaintenanceProcess(loopFun,
296 : paramLoopFun, stopNotifyFun, paramStopFun);
297 0 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
298 0 : return ret;
299 : }
300 0 : return AicpuSchedule::AICPU_SCHEDULE_OK;
301 : }
302 : #ifdef __cplusplus
303 : }
304 : #endif
|