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