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 : namespace AicpuSchedule {
24 : const uint32_t DEFAULT_GROUP_ID_TO_TSD_CLIENT = 30U;
25 59 : AicpuCustMc2MaintenanceThread& AicpuCustMc2MaintenanceThread::GetInstance(uint32_t type)
26 : {
27 59 : if (type == 0) {
28 58 : static AicpuCustMc2MaintenanceThread instance(type);
29 58 : return instance;
30 : }
31 1 : static AicpuCustMc2MaintenanceThread instance(type);
32 1 : return instance;
33 : }
34 :
35 3 : AicpuCustMc2MaintenanceThread::~AicpuCustMc2MaintenanceThread()
36 : {
37 3 : UnitCustMc2MaintenanceProcess();
38 3 : if (processThread_.joinable()) {
39 1 : processThread_.join();
40 : }
41 3 : }
42 :
43 2 : AicpuCustMc2MaintenanceThread::AicpuCustMc2MaintenanceThread(uint32_t type)
44 2 : : initFlag_(false),
45 2 : threadId_(0LU),
46 2 : processEventFuncPtr_(nullptr),
47 2 : processEventFuncParam_(nullptr),
48 2 : stopProcessEventFuncPtr_(nullptr),
49 2 : stopProcessEventFuncParam_(nullptr),
50 2 : type_(type)
51 2 : {}
52 2 : void AicpuCustMc2MaintenanceThread::SendCustMc2CreateThreadMsgToMain() const
53 : {
54 2 : TsdSubEventInfo msg = {};
55 2 : event_summary eventInfo = {};
56 2 : eventInfo.pid = static_cast<pid_t>(getpid());
57 2 : eventInfo.grp_id = DEFAULT_GROUP_ID_TO_TSD_CLIENT;
58 2 : eventInfo.dst_engine = CCPU_DEVICE;
59 2 : eventInfo.event_id = EVENT_CCPU_CTRL_MSG;
60 2 : eventInfo.subevent_id = TSD_EVENT_START_MC2_THREAD;
61 2 : eventInfo.msg_len = sizeof(TsdSubEventInfo);
62 2 : eventInfo.msg = PtrToPtr<TsdSubEventInfo, char_t>(&msg);
63 2 : struct CreateCtrlThreadArgs* createCtrlThreadArgsPtr = PtrToPtr<char_t, struct CreateCtrlThreadArgs>(msg.priMsg);
64 2 : createCtrlThreadArgsPtr->type = type_;
65 :
66 2 : uint32_t deviceId = AicpuDrvManager::GetInstance().GetDeviceId();
67 2 : const drvError_t ret = halEschedSubmitEvent(deviceId, &eventInfo);
68 2 : if (ret != DRV_ERROR_NONE) {
69 1 : aicpusd_err("Failed to submit, eventId: [%d], ret: [%d].", TSD_EVENT_START_MC2_THREAD, ret);
70 : }
71 :
72 4 : return;
73 : }
74 :
75 3 : int32_t AicpuCustMc2MaintenanceThread::CreateCustMc2MaintenanceThread()
76 : {
77 3 : if (initFlag_) {
78 1 : aicpusd_info("the thread no need to multiple init, threadId[%llu]", threadId_);
79 1 : return AICPU_SCHEDULE_OK;
80 : }
81 : try {
82 2 : if (processThread_.joinable()) {
83 1 : aicpusd_run_info("processThread join begin, threadId[%llu]", threadId_);
84 1 : processThread_.join();
85 1 : aicpusd_run_info("processThread join end, threadId[%llu]", threadId_);
86 : }
87 2 : processThread_ = std::thread(&AicpuCustMc2MaintenanceThread::StartProcessEvent, this);
88 0 : } catch (std::exception& e) {
89 0 : aicpusd_err("create thread file:%s", e.what());
90 0 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
91 0 : }
92 2 : return AICPU_SCHEDULE_OK;
93 : }
94 :
95 13 : int32_t AicpuCustMc2MaintenanceThread::InitCustMc2MaintenanceProcess(
96 : AicpuMC2MaintenanceFuncPtr loopFun, void* paramLoopFun, AicpuMC2MaintenanceFuncPtr stopNotifyFun,
97 : void* paramStopFun)
98 : {
99 13 : aicpusd_info("init cust mc2 maintenance process start, type[%u]", type_);
100 : uint32_t runMode;
101 13 : const aicpu::status_t status = aicpu::GetAicpuRunMode(runMode);
102 13 : if (status != aicpu::AICPU_ERROR_NONE) {
103 1 : aicpusd_err("Get current aicpu ctx failed. type[%u]", type_);
104 1 : return AICPU_SCHEDULE_ERROR_INNER_ERROR;
105 : }
106 12 : if (runMode != aicpu::AicpuRunMode::PROCESS_PCIE_MODE) {
107 2 : aicpusd_info("not pcie mode no need this thread type[%u]", type_);
108 2 : return AICPU_SCHEDULE_NOT_SUPPORT;
109 : }
110 10 : const std::lock_guard<std::mutex> lk(initMutex_);
111 10 : if (initFlag_) {
112 2 : aicpusd_info("the thread is already init, threadId[%llu], type[%u]", threadId_, type_);
113 2 : return AICPU_SCHEDULE_THREAD_ALREADY_EXISTS;
114 : }
115 8 : int32_t ret = 0;
116 8 : ret = RegisterProcessEventFunc(loopFun, paramLoopFun);
117 8 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
118 3 : return ret;
119 : }
120 5 : ret = RegisterStopProcessEventFunc(stopNotifyFun, paramStopFun);
121 5 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
122 2 : return ret;
123 : }
124 3 : const int32_t semRet = sem_init(&workerSme_, 0, 0U);
125 3 : if (semRet == -1) {
126 0 : aicpusd_err("workerSme_ init failed, type[%u], %s", type_, strerror(errno));
127 0 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
128 : }
129 3 : SendCustMc2CreateThreadMsgToMain();
130 3 : const int32_t semWaitRet = sem_wait(&workerSme_);
131 3 : if (semWaitRet == -1) {
132 1 : sem_destroy(&workerSme_);
133 1 : aicpusd_err("workerSme wait failed, type[%u], %s", type_, strerror(errno));
134 1 : return AICPU_SCHEDULE_ERROR_INIT_FAILED;
135 : }
136 2 : sem_destroy(&workerSme_);
137 2 : initFlag_ = true;
138 2 : aicpusd_info("init cust mc2 maintenance process finish. type[%u]", type_);
139 2 : return AICPU_SCHEDULE_OK;
140 10 : }
141 :
142 8 : int32_t AicpuCustMc2MaintenanceThread::SetCustMc2MaintenanceThreadAffinity()
143 : {
144 8 : std::vector<uint32_t> ccpuIds = AicpuDrvManager::GetInstance().GetCcpuList();
145 8 : if (ccpuIds.empty()) {
146 3 : aicpusd_run_info("ccpu list is empty no need bind core");
147 3 : return AICPU_SCHEDULE_OK;
148 : }
149 10 : if (AicpuUtil::IsEnvValEqual(ENV_NAME_PROCMGR_AICPU_CPUSET, "1")) {
150 1 : aicpusd_err("the chip is not supported, please check. type[%u]", type_);
151 1 : return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
152 : } else {
153 4 : pthread_t threadId = pthread_self();
154 4 : threadId_ = GetTid();
155 : cpu_set_t cpuset;
156 20 : for (const auto cpuId : ccpuIds) {
157 16 : CPU_SET(cpuId, &cpuset);
158 16 : aicpusd_info(
159 : "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 : } // namespace AicpuSchedule
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 : const struct AicpuSchedule::CreateCtrlThreadArgs* createCtrlThreadArgsPtr =
260 1 : PtrToPtr<const char_t, const struct AicpuSchedule::CreateCtrlThreadArgs>(msg->priMsg);
261 1 : if (createCtrlThreadArgsPtr == nullptr) {
262 0 : aicpusd_err("args ptr is null");
263 0 : return AicpuSchedule::AICPU_SCHEDULE_ERROR_INNER_ERROR;
264 : }
265 : (void)msg;
266 1 : uint32_t type = createCtrlThreadArgsPtr->type;
267 1 : aicpusd_info("aicpu create ctrl thread type[%u]", type);
268 1 : int32_t ret = AicpuSchedule::AicpuCustMc2MaintenanceThread::GetInstance(type).CreateCustMc2MaintenanceThread();
269 1 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
270 1 : aicpusd_err("Create Cust Mc2 Maintenance Thread failed, ret[%d], type[%u]", ret, type);
271 1 : return ret;
272 : }
273 0 : return AicpuSchedule::AICPU_SCHEDULE_OK;
274 : }
275 :
276 : #ifdef __cplusplus
277 : extern "C" {
278 : #endif // __cplusplus
279 13 : int32_t StartMC2MaintenanceThread(
280 : AicpuMC2MaintenanceFuncPtr loopFun, void* paramLoopFun, AicpuMC2MaintenanceFuncPtr stopNotifyFun,
281 : void* paramStopFun)
282 : {
283 13 : int32_t ret = AicpuSchedule::AicpuCustMc2MaintenanceThread::GetInstance(THREAD_TYPE_HCOM)
284 13 : .InitCustMc2MaintenanceProcess(loopFun, paramLoopFun, stopNotifyFun, paramStopFun);
285 13 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
286 11 : return ret;
287 : }
288 2 : return AicpuSchedule::AICPU_SCHEDULE_OK;
289 : }
290 0 : int32_t AicpuCreateCtrlThread(
291 : uint32_t type, AicpuMC2MaintenanceFuncPtr loopFun, void* paramLoopFun, AicpuMC2MaintenanceFuncPtr stopNotifyFun,
292 : void* paramStopFun)
293 : {
294 0 : if ((type != THREAD_TYPE_HCOM) && (type != THREAD_TYPE_ASCPP_PROF)) {
295 0 : aicpusd_err("Aicpu create ctrl thread failed, type is [%u], only support [0-1]", type);
296 0 : return AICPU_SCHEDULE_NOT_SUPPORT;
297 : }
298 0 : int32_t ret = AicpuSchedule::AicpuCustMc2MaintenanceThread::GetInstance(type).InitCustMc2MaintenanceProcess(
299 : loopFun, paramLoopFun, stopNotifyFun, paramStopFun);
300 0 : if (ret != AicpuSchedule::AICPU_SCHEDULE_OK) {
301 0 : return ret;
302 : }
303 0 : return AicpuSchedule::AICPU_SCHEDULE_OK;
304 : }
305 : #ifdef __cplusplus
306 : }
307 : #endif
|