已合并
feat: 支持关闭 AICPU kernel timeout monitor(#794) #3735
feat: 支持关闭 AICPU kernel timeout monitor(#794) #3735
已合并
pantong创建于 7月21日
19 个文件变更+454-9
@@ -81,6 +81,7 @@ enum __attribute__((visibility("default"))) AICPUCustSubEvent {
81 AICPU_SUB_EVENT_REPORT_CUST_DUMPDATA, // aicpusd do cust datadump81 AICPU_SUB_EVENT_REPORT_CUST_DUMPDATA, // aicpusd do cust datadump
82 AICPU_SUB_EVENT_REPORT_UDF_DUMPDATA, // aicpusd do udf datadump82 AICPU_SUB_EVENT_REPORT_UDF_DUMPDATA, // aicpusd do udf datadump
83 AICPU_SUB_EVENT_CUST_LOAD_PLATFORM, // custom scheduler process load platform info event83 AICPU_SUB_EVENT_CUST_LOAD_PLATFORM, // custom scheduler process load platform info event
84+ AICPU_SUB_EVENT_CUST_CLOSE_MONITOR, // notify cust-sd to close aicpu kernel timeout monitor
84};85};
85 86 
86struct __attribute__((visibility("default"))) AICPUSubEventStreamInfo {87struct __attribute__((visibility("default"))) AICPUSubEventStreamInfo {
@@ -156,6 +157,10 @@ struct __attribute__((visibility("default"))) AICPUOpenCustomSoEventMsg {
156 char_t kernelSoName[MAX_CUST_SO_NAME_LEN];157 char_t kernelSoName[MAX_CUST_SO_NAME_LEN];
157} __attribute__((packed));158} __attribute__((packed));
158 159 
160+struct __attribute__((visibility("default"))) AICPUCloseMonitorEventMsg {
161+ uint8_t closeFlag;
162+} __attribute__((packed));
163+ 
159struct __attribute__((visibility("default"))) CpuSchedInitParam {164struct __attribute__((visibility("default"))) CpuSchedInitParam {
160 uint32_t deviceId;165 uint32_t deviceId;
161 pid_t hostPid;166 pid_t hostPid;
@@ -282,4 +287,4 @@ struct __attribute__((visibility("default"))) SomaMemMng {
282 char rsv[4];287 char rsv[4];
283} __attribute__((packed));288} __attribute__((packed));
284}289}
285-#endif // AICPUSD_AICPUSD_INFO_H290+#endif // AICPUSD_AICPUSD_INFO_H
@@ -169,6 +169,18 @@ int32_t AicpuEventProcess::AICPUEventOpenCustomSo(const event_info_priv& privEve
169 return AICPU_SCHEDULE_OK;169 return AICPU_SCHEDULE_OK;
170}170}
171 171 
172+int32_t AicpuEventProcess::AICPUEventCustCloseMonitor(const TsdSubEventInfo* const eventInfo)
173+{
174+ if (eventInfo == nullptr) {
175+ aicpusd_err("Close monitor event info is nullptr.");
176+ return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
177+ }
178+ const auto msg = PtrToPtr<const char_t, const AICPUCloseMonitorEventMsg>(eventInfo->priMsg);
179+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(msg->closeFlag == 1U);
180+ aicpusd_info("Cust receive close monitor event, closeFlag[%u].", msg->closeFlag);
181+ return AICPU_SCHEDULE_OK;
182+}
183+ 
172int32_t AicpuEventProcess::AICPUEventCustUpdateProfilingMode(const event_info_priv& privEventInfo) const184int32_t AicpuEventProcess::AICPUEventCustUpdateProfilingMode(const event_info_priv& privEventInfo) const
173{185{
174 const AICPUSubEventInfo* const info = PtrToPtr<const char_t, const AICPUSubEventInfo>(privEventInfo.msg);186 const AICPUSubEventInfo* const info = PtrToPtr<const char_t, const AICPUSubEventInfo>(privEventInfo.msg);
@@ -20,6 +20,7 @@
20#include "aicpu_context.h"20#include "aicpu_context.h"
21#include "type_def.h"21#include "type_def.h"
22#include "aicpusd_sqe_adapter.h"22#include "aicpusd_sqe_adapter.h"
23+#include "tsd.h"
23 24 
24namespace AicpuSchedule {25namespace AicpuSchedule {
25class AicpuEventProcess {26class AicpuEventProcess {
@@ -84,6 +85,8 @@ public:
84 */85 */
85 int32_t ProcessMsgVersionEvent(AicpuSqeAdapter& aicpuSqeAdapter) const;86 int32_t ProcessMsgVersionEvent(AicpuSqeAdapter& aicpuSqeAdapter) const;
86 87 
88+ static int32_t AICPUEventCustCloseMonitor(const TsdSubEventInfo* const eventInfo);
89+ 
87private:90private:
88 AicpuEventProcess();91 AicpuEventProcess();
89 92 
@@ -14,6 +14,7 @@
14#include "ascend_hal.h"14#include "ascend_hal.h"
15#include "status.h"15#include "status.h"
16#include "aicpusd_event_manager.h"16#include "aicpusd_event_manager.h"
17+#include "aicpusd_event_process.h"
17#include "aicpusd_status.h"18#include "aicpusd_status.h"
18#include "aicpusd_drv_manager.h"19#include "aicpusd_drv_manager.h"
19#include "aicpusd_threads_process.h"20#include "aicpusd_threads_process.h"
@@ -41,6 +42,17 @@ void RegOpenCustSoCallBack()
41 return;42 return;
42 }43 }
43}44}
45+ 
46+void RegCloseMonitorCallBack()
47+{
48+ SubProcEventCallBackInfo closeMonitorInfo = {};
49+ closeMonitorInfo.callBackFunc = AicpuEventProcess::AICPUEventCustCloseMonitor;
50+ closeMonitorInfo.eventType = AICPU_SUB_EVENT_CUST_CLOSE_MONITOR;
51+ const int32_t ret = RegEventMsgCallBackFunc(&closeMonitorInfo);
52+ if (ret != 0) {
53+ aicpusd_run_warn("Register close monitor callback failed. eventId[%u]", closeMonitorInfo.eventType);
54+ }
55+}
44} // namespace56} // namespace
45constexpr int32_t SUCCESS_VALUE = 0;57constexpr int32_t SUCCESS_VALUE = 0;
46constexpr int32_t ATTACH_TIME_OUT = 20000; // attach fail after 20s blocking attach58constexpr int32_t ATTACH_TIME_OUT = 20000; // attach fail after 20s blocking attach
@@ -407,6 +419,7 @@ int32_t AicpuScheduleInterface::CustAicpuMainProcess(int32_t argc, char_t* argv[
407 }419 }
408 AicpuSchedule::RegCreateCustMc2MaintenanceThreadCallBack();420 AicpuSchedule::RegCreateCustMc2MaintenanceThreadCallBack();
409 AicpuSchedule::RegOpenCustSoCallBack();421 AicpuSchedule::RegOpenCustSoCallBack();
422+ AicpuSchedule::RegCloseMonitorCallBack();
410 // response start message to tsd423 // response start message to tsd
411 int32_t rspRet = static_cast<int32_t>(tsd::TSD_OK);424 int32_t rspRet = static_cast<int32_t>(tsd::TSD_OK);
412 if (startParams.GetGrpNameNum() > 0U) {425 if (startParams.GetGrpNameNum() > 0U) {
@@ -139,7 +139,7 @@ int32_t AicpuMonitor::SetTaskTimeoutFlag()
139 139 
140void AicpuMonitor::SetTaskStartTime(const uint64_t taskIndex)140void AicpuMonitor::SetTaskStartTime(const uint64_t taskIndex)
141{141{
142- if ((taskTimeoutFlag_) && (online_)) {142+ if ((!IsMonitorClosed()) && (taskTimeoutFlag_) && (online_)) {
143 taskTimer_[taskIndex].SetStartTick(aicpu::GetSystemTick());143 taskTimer_[taskIndex].SetStartTick(aicpu::GetSystemTick());
144 taskTimer_[taskIndex].SetRunFlag(true);144 taskTimer_[taskIndex].SetRunFlag(true);
145 }145 }
@@ -218,7 +218,7 @@ void AicpuMonitor::Stop()
218 218 
219void AicpuMonitor::HandleTaskTimeout()219void AicpuMonitor::HandleTaskTimeout()
220{220{
221- if (!taskTimeoutFlag_) {221+ if (!taskTimeoutFlag_ || IsMonitorClosed()) {
222 return;222 return;
223 }223 }
224 224 
@@ -65,6 +65,10 @@ public:
65 void SetTaskStartTime(const uint64_t taskIndex);65 void SetTaskStartTime(const uint64_t taskIndex);
66 void SetTaskEndTime(const uint64_t taskIndex);66 void SetTaskEndTime(const uint64_t taskIndex);
67 67 
68+ void SetCloseMonitorFlag(const bool closeFlag) { closeMonitorFlag_.store(closeFlag); }
69+ 
70+ bool IsMonitorClosed() const { return closeMonitorFlag_.load(); }
71+ 
68 int32_t Run();72 int32_t Run();
69 73 
70 void Stop();74 void Stop();
@@ -101,6 +105,7 @@ private:
101 bool running_;105 bool running_;
102 uint32_t aicpuCoreNum_;106 uint32_t aicpuCoreNum_;
103 bool online_; // true when exist in process mode; false when exist in thread mode107 bool online_; // true when exist in process mode; false when exist in thread mode
108+ std::atomic<bool> closeMonitorFlag_{false};
104};109};
105} // namespace AicpuSchedule110} // namespace AicpuSchedule
106#endif // CORE_AICPUSD_MONITOR_H111#endif // CORE_AICPUSD_MONITOR_H
@@ -119,6 +119,7 @@ set(hwts_kernel_src_file
119 ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_queue.cpp119 ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_queue.cpp
120 ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_model_control.cpp120 ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_model_control.cpp
121 ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_soma.cpp121 ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_soma.cpp
122+ ${CMAKE_CURRENT_SOURCE_DIR}/core/hwts_kernel/hwts_kernel_close_monitor.cpp
122)123)
123 124 
124 125 
@@ -25,6 +25,7 @@
25#include "aicpusd_resource_manager.h"25#include "aicpusd_resource_manager.h"
26#include "aicpusd_threads_process.h"26#include "aicpusd_threads_process.h"
27#include "aicpusd_worker.h"27#include "aicpusd_worker.h"
28+#include "aicpusd_feature_ctrl.h"
28 29 
29namespace {30namespace {
30// aicpu task timeout31// aicpu task timeout
@@ -249,7 +250,7 @@ int32_t AicpuMonitor::SetModelTimeoutFlag()
249// index used inner, it is valid250// index used inner, it is valid
250void AicpuMonitor::SetTaskStartTime(const uint32_t taskId)251void AicpuMonitor::SetTaskStartTime(const uint32_t taskId)
251{252{
252- if ((taskTimeoutFlag_) && (online_)) {253+ if ((!IsMonitorClosed()) && (taskTimeoutFlag_) && (online_)) {
253 aicpuTaskTimer_[static_cast<uint64_t>(taskId)].SetStartTick(aicpu::GetSystemTick());254 aicpuTaskTimer_[static_cast<uint64_t>(taskId)].SetStartTick(aicpu::GetSystemTick());
254 aicpuTaskTimer_[static_cast<uint64_t>(taskId)].SetRunFlag(true);255 aicpuTaskTimer_[static_cast<uint64_t>(taskId)].SetRunFlag(true);
255 }256 }
@@ -450,7 +451,7 @@ void AicpuMonitor::SetOpTimeoutFlag(const bool flag)
450 451 
451void AicpuMonitor::HandleTaskTimeout()452void AicpuMonitor::HandleTaskTimeout()
452{453{
453- if (!taskTimeoutFlag_) {454+ if (!taskTimeoutFlag_ || IsMonitorClosed()) {
454 return;455 return;
455 }456 }
456 457 
@@ -84,6 +84,8 @@ public:
84 84 
85 void SetOpExecuteTimeOut(const uint32_t timeOutEn, const uint32_t opExecuteTimeOut);85 void SetOpExecuteTimeOut(const uint32_t timeOutEn, const uint32_t opExecuteTimeOut);
86 void SetOpTimeoutFlag(const bool flag);86 void SetOpTimeoutFlag(const bool flag);
87+ void SetCloseMonitorFlag(const bool closeFlag) { closeMonitorFlag_.store(closeFlag); }
88+ bool IsMonitorClosed() const { return closeMonitorFlag_.load(); }
87 int32_t Run();89 int32_t Run();
88 void StopMonitor();90 void StopMonitor();
89 ~AicpuMonitor();91 ~AicpuMonitor();
@@ -134,7 +136,8 @@ private:
134 bool online_; // true when exist in process mode; false when exist in thread mode136 bool online_; // true when exist in process mode; false when exist in thread mode
135 std::atomic<bool> opTimeoutFlag_;137 std::atomic<bool> opTimeoutFlag_;
136 std::mutex opTimerMapMutex_;138 std::mutex opTimerMapMutex_;
139+ std::atomic<bool> closeMonitorFlag_{false};
137};140};
138} // namespace AicpuSchedule141} // namespace AicpuSchedule
139 142 
140-#endif // CORE_AICPUSD_MONITOR_H143+#endif // CORE_AICPUSD_MONITOR_H
@@ -0,0 +1,42 @@
1+/**
2+ * Copyright (c) 2026 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 "hwts_kernel_close_monitor.h"
12+ 
13+#include "aicpusd_monitor.h"
14+ 
15+namespace AicpuSchedule {
16+namespace {
17+const std::string CLOSE_AICPU_MONITOR = "CloseAicpuMonitor";
18+struct CloseAicpuMonitorArgs {
19+ uint8_t monitorEn; /* 1=close aicpu self monitor, 0=open */
20+ uint8_t retcode; /* set to 0 on success; errors are returned by Compute */
21+ uint8_t rsv[2];
22+};
23+} // namespace
24+ 
25+int32_t CloseAicpuMonitorTsKernel::Compute(const aicpu::HwtsTsKernel& tsKernelInfo)
26+{
27+ aicpusd_info("Begin to process ts kernel CloseAicpuMonitor event.");
28+ const auto args = PtrToPtr<void, CloseAicpuMonitorArgs>(ValueToPtr(tsKernelInfo.kernelBase.cceKernel.paramBase));
29+ if (args == nullptr) {
30+ aicpusd_err("param base for CloseAicpuMonitor is null.");
31+ return AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID;
32+ }
33+ const bool closeFlag = (args->monitorEn == 1U);
34+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(closeFlag);
35+ args->retcode = 0U;
D
DDevLeev8月6日

[仅供参考] 一致性:CloseAicpuMonitorArgs.retcode 注释为 0=success,1=fail,但代码仅在成功路径置 0,失败路径(args==nullptr)提前返回、未回写 retcode。当前逻辑无实际缺陷(唯一失败即空指针,无可写目标),但 retcode 语义未被真正使用。

建议:确认调用方是否依赖该字段。

likedislike
36+ aicpusd_info(
37+ "Process CloseAicpuMonitor, monitorEn[%u], closeFlag[%d].", args->monitorEn, static_cast<int32_t>(closeFlag));
38+ return AICPU_SCHEDULE_OK;
39+}
40+ 
41+REGISTER_HWTS_KERNEL(CLOSE_AICPU_MONITOR, CloseAicpuMonitorTsKernel);
42+} // namespace AicpuSchedule
@@ -0,0 +1,24 @@
1+/**
2+ * Copyright (c) 2026 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+#ifndef HWTS_KERNEL_CLOSE_MONITOR_H
12+#define HWTS_KERNEL_CLOSE_MONITOR_H
13+ 
14+#include "hwts_kernel.h"
15+ 
16+namespace AicpuSchedule {
17+class CloseAicpuMonitorTsKernel : public HwTsKernelHandler {
18+public:
19+ CloseAicpuMonitorTsKernel() = default;
20+ ~CloseAicpuMonitorTsKernel() override = default;
21+ int32_t Compute(const aicpu::HwtsTsKernel& tsKernelInfo) override;
22+};
23+} // namespace AicpuSchedule
24+#endif // HWTS_KERNEL_CLOSE_MONITOR_H
@@ -12,6 +12,7 @@
12 12 
13#include "aicpusd_cust_so_manager.h"13#include "aicpusd_cust_so_manager.h"
14#include "aicpusd_drv_manager.h"14#include "aicpusd_drv_manager.h"
15+#include "aicpusd_monitor.h"
15#include "hwts_kernel_common.h"16#include "hwts_kernel_common.h"
16 17 
17namespace AicpuSchedule {18namespace AicpuSchedule {
@@ -157,6 +158,14 @@ int32_t CustOperationCommon::StartCustProcess(const uint32_t loadLibNum, const c
157 }158 }
158 }159 }
159 160 
161+ if (AicpuMonitor::GetInstance().IsMonitorClosed()) {
D
DDevLeev8月6日

[建议修改] 功能正确性:StartCustProcess 中当 IsMonitorClosed() 为真时,NotifyCustCloseMonitor 一旦失败即 return closeRet,直接中断自定义进程启动。这把 DFX 特性(关闭监控)的失败耦合成了功能主链路(custom SO 加载)的失败。

建议:评估监控关闭同步失败时是否应仅告警并继续启动,而非阻断 custom 进程启动。

likedislike
162+ const int32_t closeRet = NotifyCustCloseMonitor(custAicpuPid);
163+ if (closeRet != AICPU_SCHEDULE_OK) {
164+ aicpusd_err("Notify custaicpu to close monitor failed, ret[%d], pid[%d].", closeRet, custAicpuPid);
165+ return closeRet;
166+ }
167+ }
168+ 
160 aicpusd_run_info("StartCustProcess end");169 aicpusd_run_info("StartCustProcess end");
161 return AICPU_SCHEDULE_OK;170 return AICPU_SCHEDULE_OK;
162}171}
@@ -212,6 +221,40 @@ int32_t CustOperationCommon::AicpuNotifyLoadSoEventToCustCtrlCpu(
212 return AICPU_SCHEDULE_OK;221 return AICPU_SCHEDULE_OK;
213}222}
214 223 
224+int32_t CustOperationCommon::NotifyCustCloseMonitor(const int32_t custAicpuPid) const
225+{
226+ TsdSubEventInfo info = {};
227+ info.deviceId = AicpuDrvManager::GetInstance().GetDeviceId();
228+ info.srcPid = static_cast<uint32_t>(getpid());
229+ info.dstPid = static_cast<uint32_t>(custAicpuPid);
230+ info.hostPid = static_cast<uint32_t>(AicpuDrvManager::GetInstance().GetHostPid());
231+ info.vfId = static_cast<uint8_t>(AicpuDrvManager::GetInstance().GetVfId());
232+ info.procType = 1U;
233+ info.eventType = static_cast<uint32_t>(AICPU_SUB_EVENT_CUST_CLOSE_MONITOR);
234+ auto closeMonitorMsg = PtrToPtr<char_t, AICPUCloseMonitorEventMsg>(info.priMsg);
235+ closeMonitorMsg->closeFlag = 1U;
236+ 
237+ event_summary closeMonitorEvent = {};
238+ closeMonitorEvent.dst_engine = CCPU_DEVICE;
239+ closeMonitorEvent.policy = ONLY;
240+ closeMonitorEvent.pid = custAicpuPid;
241+ closeMonitorEvent.grp_id = CCPU_DEFAULT_GROUP_ID;
242+ closeMonitorEvent.event_id = EVENT_CCPU_CTRL_MSG;
243+ closeMonitorEvent.subevent_id = static_cast<uint32_t>(AICPU_SUB_EVENT_CUST_CLOSE_MONITOR);
244+ closeMonitorEvent.msg = PtrToPtr<TsdSubEventInfo, char_t>(&info);
245+ closeMonitorEvent.msg_len = static_cast<uint32_t>(sizeof(info));
246+ 
247+ const drvError_t ret = halEschedSubmitEvent(info.deviceId, &closeMonitorEvent);
248+ if (ret != DRV_ERROR_NONE) {
249+ aicpusd_err(
250+ "Send close monitor event to custaicpu failed, ret[%d], pid[%d], group[%u], event[%d].", ret, custAicpuPid,
251+ closeMonitorEvent.grp_id, closeMonitorEvent.event_id);
252+ return AICPU_SCHEDULE_ERROR_DRV_ERR;
253+ }
254+ aicpusd_run_info("Submit close monitor event to custaicpu success.");
255+ return AICPU_SCHEDULE_OK;
256+}
257+ 
215int32_t LoadOpFromBuffTsKernel::Compute(const aicpu::HwtsTsKernel& tsKernelInfo)258int32_t LoadOpFromBuffTsKernel::Compute(const aicpu::HwtsTsKernel& tsKernelInfo)
216{259{
217 aicpusd_run_info("Begin to process ts kernel loadOpFromBuf");260 aicpusd_run_info("Begin to process ts kernel loadOpFromBuf");
@@ -380,4 +423,4 @@ int32_t DeleteCustOpTsKernel::Compute(const aicpu::HwtsTsKernel& tsKernelInfo)
380REGISTER_HWTS_KERNEL(LOADOP_FROM_BUFF, LoadOpFromBuffTsKernel);423REGISTER_HWTS_KERNEL(LOADOP_FROM_BUFF, LoadOpFromBuffTsKernel);
381REGISTER_HWTS_KERNEL(BATCH_LOADSO_FROM_BUFF, BatchLoadSoFromBuffTsKernel);424REGISTER_HWTS_KERNEL(BATCH_LOADSO_FROM_BUFF, BatchLoadSoFromBuffTsKernel);
382REGISTER_HWTS_KERNEL(DELETE_CUSTOP, DeleteCustOpTsKernel);425REGISTER_HWTS_KERNEL(DELETE_CUSTOP, DeleteCustOpTsKernel);
383-} // namespace AicpuSchedule426+} // namespace AicpuSchedule
@@ -29,6 +29,7 @@ public:
29 int32_t AicpuNotifyLoadSoEventToCustCtrlCpu(29 int32_t AicpuNotifyLoadSoEventToCustCtrlCpu(
30 const uint32_t deviceId, const uint32_t hostPid, const uint32_t vfId, const int32_t custAicpuPid,30 const uint32_t deviceId, const uint32_t hostPid, const uint32_t vfId, const int32_t custAicpuPid,
31 const uint32_t loadLibNum, const char_t* const loadLibName[]) const;31 const uint32_t loadLibNum, const char_t* const loadLibName[]) const;
32+ int32_t NotifyCustCloseMonitor(const int32_t custAicpuPid) const;
32};33};
33 34 
34class LoadOpFromBuffTsKernel : public HwTsKernelHandler, public CustOperationCommon {35class LoadOpFromBuffTsKernel : public HwTsKernelHandler, public CustOperationCommon {
@@ -146,6 +146,44 @@ TEST_F(AICPUCustMonitorTEST, SetTaskEndTimeSucc)
146 moniter.SetTaskEndTime(0);146 moniter.SetTaskEndTime(0);
147}147}
148 148 
149+TEST_F(AICPUCustMonitorTEST, SetTaskEndTimeClearsTimerWhenMonitorClosed)
150+{
151+ AicpuMonitor monitor;
152+ monitor.taskTimeoutFlag_ = true;
153+ monitor.online_ = true;
154+ monitor.taskTimer_.reset(new (std::nothrow) TaskTimer[1]);
155+ monitor.taskInfo_.reset(new (std::nothrow) TaskInfoForMonitor[1]);
156+ monitor.taskTimer_[0].SetRunFlag(true);
157+ monitor.taskInfo_[0].isHwts = true;
158+ monitor.SetCloseMonitorFlag(true);
159+ 
160+ monitor.SetTaskEndTime(0);
161+ 
162+ EXPECT_FALSE(monitor.taskTimer_[0].GetRunFlag());
163+ EXPECT_FALSE(monitor.taskInfo_[0].isHwts);
164+}
165+ 
166+TEST_F(AICPUCustMonitorTEST, MonitorClosedSkipsTaskStartAndTimeout)
167+{
168+ AicpuMonitor monitor;
169+ monitor.taskTimeoutFlag_ = true;
170+ monitor.online_ = true;
171+ monitor.aicpuCoreNum_ = 1U;
172+ monitor.taskTimeoutTick_ = 1U;
173+ monitor.taskTimer_.reset(new (std::nothrow) TaskTimer[1]);
174+ monitor.taskInfo_.reset(new (std::nothrow) TaskInfoForMonitor[1]);
175+ monitor.SetCloseMonitorFlag(true);
176+ 
177+ monitor.SetTaskStartTime(0U);
178+ EXPECT_FALSE(monitor.taskTimer_[0].GetRunFlag());
179+ 
180+ monitor.taskTimer_[0].SetStartTick(1U);
181+ monitor.taskTimer_[0].SetRunFlag(true);
182+ MOCKER(aicpu::GetSystemTick).expects(never());
183+ MOCKER(TsdDestroy).expects(never());
184+ monitor.HandleTaskTimeout();
185+}
186+ 
149TEST_F(AICPUCustMonitorTEST, MonitorRunSemInitFail)187TEST_F(AICPUCustMonitorTEST, MonitorRunSemInitFail)
150{188{
151 AicpuMonitor monitor;189 AicpuMonitor monitor;
@@ -146,6 +146,16 @@ drvError_t drvQueryProcessHostPidFake5(
146 return DRV_ERROR_NO_PROCESS;146 return DRV_ERROR_NO_PROCESS;
147}147}
148auto mockerOpen = reinterpret_cast<int (*)(const char*, int)>(open);148auto mockerOpen = reinterpret_cast<int (*)(const char*, int)>(open);
149+uint32_t g_closeMonitorCallbackRegisterCount = 0U;
150+ 
151+int32_t CaptureEventCallback(const SubProcEventCallBackInfo* const callbackInfo)
152+{
153+ if (callbackInfo->eventType == AICPU_SUB_EVENT_CUST_CLOSE_MONITOR) {
154+ EXPECT_EQ(callbackInfo->callBackFunc, AicpuEventProcess::AICPUEventCustCloseMonitor);
155+ ++g_closeMonitorCallbackRegisterCount;
156+ }
157+ return 0;
158+}
149} // namespace159} // namespace
150 160 
151extern int32_t SecureCompute();161extern int32_t SecureCompute();
@@ -170,12 +180,15 @@ TEST_F(AICPUCustScheduleTEST, MainTest)
170 int32_t argc = 10;180 int32_t argc = 10;
171 181 
172 MOCKER_CPP(&AicpuScheduleInterface::InitAICPUScheduler).stubs().will(returnValue(0));182 MOCKER_CPP(&AicpuScheduleInterface::InitAICPUScheduler).stubs().will(returnValue(0));
183+ g_closeMonitorCallbackRegisterCount = 0U;
184+ MOCKER(RegEventMsgCallBackFunc).stubs().will(invoke(CaptureEventCallback));
173 int ret = ComputeProcessMain(argc, argv);185 int ret = ComputeProcessMain(argc, argv);
174 EXPECT_EQ(ret, AICPU_SCHEDULE_OK);186 EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
175 187 
176 MOCKER(StartUpRspAndWaitProcess).stubs().will(returnValue(1));188 MOCKER(StartUpRspAndWaitProcess).stubs().will(returnValue(1));
177 ret = ComputeProcessMain(argc, argv);189 ret = ComputeProcessMain(argc, argv);
178 EXPECT_EQ(ret, -1);190 EXPECT_EQ(ret, -1);
191+ EXPECT_EQ(g_closeMonitorCallbackRegisterCount, 2U);
179}192}
180 193 
181TEST_F(AICPUCustScheduleTEST, MainTestErr)194TEST_F(AICPUCustScheduleTEST, MainTestErr)
@@ -2024,6 +2037,37 @@ TEST_F(AICPUCustScheduleTEST, ActiveTheBlockThread)
2024 EXPECT_EQ(ret, AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID);2037 EXPECT_EQ(ret, AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID);
2025}2038}
2026 2039 
2040+TEST_F(AICPUCustScheduleTEST, ProcessCloseMonitorMessageSuccess)
2041+{
2042+ TsdSubEventInfo eventInfo = {};
2043+ auto closeMonitorMsg = reinterpret_cast<AICPUCloseMonitorEventMsg*>(eventInfo.priMsg);
2044+ closeMonitorMsg->closeFlag = 1U;
2045+ 
2046+ const int32_t ret = AicpuEventProcess::AICPUEventCustCloseMonitor(&eventInfo);
2047+ 
2048+ EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
2049+ EXPECT_TRUE(AicpuMonitor::GetInstance().IsMonitorClosed());
2050+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(false);
2051+}
2052+ 
2053+TEST_F(AICPUCustScheduleTEST, ProcessCloseMonitorMessageOpenMonitor)
2054+{
2055+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(true);
2056+ TsdSubEventInfo eventInfo = {};
2057+ auto closeMonitorMsg = reinterpret_cast<AICPUCloseMonitorEventMsg*>(eventInfo.priMsg);
2058+ closeMonitorMsg->closeFlag = 0U;
2059+ 
2060+ const int32_t ret = AicpuEventProcess::AICPUEventCustCloseMonitor(&eventInfo);
2061+ 
2062+ EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
2063+ EXPECT_FALSE(AicpuMonitor::GetInstance().IsMonitorClosed());
2064+}
2065+ 
2066+TEST_F(AICPUCustScheduleTEST, ProcessCloseMonitorMessageNull)
2067+{
2068+ EXPECT_EQ(AicpuEventProcess::AICPUEventCustCloseMonitor(nullptr), AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID);
2069+}
2070+ 
2027TEST_F(AICPUCustScheduleTEST, CustProcessLoadPlatform)2071TEST_F(AICPUCustScheduleTEST, CustProcessLoadPlatform)
2028{2072{
2029 int32_t ret = 0;2073 int32_t ret = 0;
@@ -186,6 +186,7 @@ set(hwts_kernel_src_file
186 ${SRC_PATH}/core/hwts_kernel/hwts_kernel_queue.cpp186 ${SRC_PATH}/core/hwts_kernel/hwts_kernel_queue.cpp
187 ${SRC_PATH}/core/hwts_kernel/hwts_kernel_model_control.cpp187 ${SRC_PATH}/core/hwts_kernel/hwts_kernel_model_control.cpp
188 ${SRC_PATH}/core/hwts_kernel/hwts_kernel_soma.cpp188 ${SRC_PATH}/core/hwts_kernel/hwts_kernel_soma.cpp
189+ ${SRC_PATH}/core/hwts_kernel/hwts_kernel_close_monitor.cpp
189)190)
190 191 
191set(event_process_kernel_test_src_file192set(event_process_kernel_test_src_file
@@ -209,6 +210,7 @@ set(event_process_kernel_test_src_file
209 testcase/hwts_kernel/hwts_kernel_check_supported_test.cpp210 testcase/hwts_kernel/hwts_kernel_check_supported_test.cpp
210 testcase/hwts_kernel/hwts_kernel_process_data_exception_test.cpp211 testcase/hwts_kernel/hwts_kernel_process_data_exception_test.cpp
211 testcase/hwts_kernel/hwts_kernel_soma_memmng_test.cpp212 testcase/hwts_kernel/hwts_kernel_soma_memmng_test.cpp
213+ testcase/hwts_kernel/hwts_kernel_close_monitor_test.cpp
212)214)
213 215 
214# ---- 共享源文件组(各 UT target 复用,避免重复定义)----216# ---- 共享源文件组(各 UT target 复用,避免重复定义)----
@@ -202,6 +202,45 @@ TEST_F(AicpuMonitorTEST, SendKillMsgToTsdFail)
202 EXPECT_EQ(monitor.running_, false);202 EXPECT_EQ(monitor.running_, false);
203}203}
204 204 
205+TEST_F(AicpuMonitorTEST, SetTaskEndTimeClearsTimerWhenMonitorClosed)
206+{
207+ AicpuMonitor monitor;
208+ monitor.taskTimeoutFlag_ = true;
209+ monitor.online_ = true;
210+ monitor.aicpuTaskTimer_.reset(new (std::nothrow) TaskTimer[1]);
211+ monitor.monitorTaskInfo_.reset(new (std::nothrow) TaskInfoForMonitor[1]);
212+ monitor.aicpuTaskTimer_[0].SetRunFlag(true);
213+ monitor.monitorTaskInfo_[0].isHwts = true;
214+ monitor.SetCloseMonitorFlag(true);
215+ 
216+ monitor.SetTaskEndTime(0);
217+ 
218+ EXPECT_FALSE(monitor.aicpuTaskTimer_[0].GetRunFlag());
219+ EXPECT_FALSE(monitor.monitorTaskInfo_[0].isHwts);
220+}
221+ 
222+TEST_F(AicpuMonitorTEST, MonitorClosedSkipsTaskStartAndTimeout)
223+{
224+ AicpuMonitor monitor;
225+ monitor.taskTimeoutFlag_ = true;
226+ monitor.online_ = true;
227+ monitor.aicpuCoreNum_ = 1U;
228+ monitor.taskTimeoutTick_ = 1U;
229+ monitor.aicpuTaskTimer_.reset(new (std::nothrow) TaskTimer[1]);
230+ monitor.aicpuStreamTaskTimer_.reset(new (std::nothrow) TaskTimer[MAX_MODEL_COUNT]);
231+ monitor.monitorTaskInfo_.reset(new (std::nothrow) TaskInfoForMonitor[1]);
232+ monitor.SetCloseMonitorFlag(true);
233+ 
234+ monitor.SetTaskStartTime(0U);
235+ EXPECT_FALSE(monitor.aicpuTaskTimer_[0].GetRunFlag());
236+ 
237+ monitor.aicpuTaskTimer_[0].SetStartTick(1U);
238+ monitor.aicpuTaskTimer_[0].SetRunFlag(true);
239+ MOCKER(aicpu::GetSystemTick).expects(never());
240+ MOCKER(TsdDestroy).expects(never());
241+ monitor.HandleTaskTimeout();
242+}
243+ 
205TEST_F(AicpuMonitorTEST, HandleTaskTimeout)244TEST_F(AicpuMonitorTEST, HandleTaskTimeout)
206{245{
207 AicpuMonitor m;246 AicpuMonitor m;
@@ -437,4 +476,4 @@ TEST_F(AicpuMonitorTEST, HandleTaskTimeoutSuccess)
437 EXPECT_EQ(ret, AICPU_SCHEDULE_OK);476 EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
438 monitor.taskTimeoutFlag_ = false;477 monitor.taskTimeoutFlag_ = false;
439 monitor.HandleTaskTimeout();478 monitor.HandleTaskTimeout();
440-}479+}
@@ -21,6 +21,7 @@
21#include "aicpusd_event_process.h"21#include "aicpusd_event_process.h"
22#include "aicpusd_drv_manager.h"22#include "aicpusd_drv_manager.h"
23#include "aicpusd_model.h"23#include "aicpusd_model.h"
24+#include "aicpusd_monitor.h"
24#include "aicpusd_resource_manager.h"25#include "aicpusd_resource_manager.h"
25#include "hwts_kernel_cust_so.h"26#include "hwts_kernel_cust_so.h"
26#include "hwts_kernel_cust_so.h"27#include "hwts_kernel_cust_so.h"
@@ -81,6 +82,23 @@ TEST_F(CustOperationCommonTest, NowaitGrp)
81 GlobalMockObject::verify();82 GlobalMockObject::verify();
82}83}
83 84 
85+TEST_F(CustOperationCommonTest, CloseMonitorNotifyFailureBlocksStart)
86+{
87+ const uint32_t loadLibNum = 1U;
88+ const std::unique_ptr<const char_t*[]> soNames(new (std::nothrow) const char_t*[loadLibNum]);
89+ MOCKER(&CreateOrFindCustPid).stubs().will(invoke(CreateOrFindCustPidFake));
90+ MOCKER(&halGrpQuery).stubs().will(invoke(halGrpQueryFake));
91+ MOCKER_CPP(&CustOperationCommon::AicpuNotifyLoadSoEventToCustCtrlCpu).stubs().will(returnValue(AICPU_SCHEDULE_OK));
92+ MOCKER_CPP(&CustOperationCommon::NotifyCustCloseMonitor).stubs().will(returnValue(AICPU_SCHEDULE_ERROR_DRV_ERR));
93+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(true);
94+ 
95+ const int32_t ret = commonKernel_.StartCustProcess(loadLibNum, soNames.get());
96+ 
97+ EXPECT_EQ(ret, AICPU_SCHEDULE_ERROR_DRV_ERR);
98+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(false);
99+ GlobalMockObject::verify();
100+}
101+ 
84TEST_F(CustOperationCommonTest, AicpuNotifyLoadSoEventToCustCtrlCpu_success)102TEST_F(CustOperationCommonTest, AicpuNotifyLoadSoEventToCustCtrlCpu_success)
85{103{
86 const uint32_t deviceId = 0;104 const uint32_t deviceId = 0;
@@ -1026,4 +1044,4 @@ TEST_F(BatchLoadSoFromBuffKernelTest, TsKernelBatchLoadOpFromBuf_fail0)
1026 1044 
1027 free(p);1045 free(p);
1028 EXPECT_EQ(retStatus, AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID);1046 EXPECT_EQ(retStatus, AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID);
1029-}1047+}
@@ -0,0 +1,151 @@
1+/**
2+ * Copyright (c) 2026 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 "gtest/gtest.h"
12+#include "mockcpp/mockcpp.hpp"
13+#include "tsd.h"
14+#define private public
15+#include "aicpusd_model.h"
16+#include "hwts_kernel_close_monitor.h"
17+#include "hwts_kernel_register.h"
18+#include "hwts_kernel_cust_so.h"
19+#include "aicpusd_monitor.h"
20+#undef private
21+#include "aicpusd_context.h"
22+#include "aicpusd_drv_manager.h"
23+#include "hwts_kernel_stub.h"
24+ 
25+using namespace AicpuSchedule;
26+ 
27+class CloseAicpuMonitorKernelTest : public EventProcessKernelTest {
28+protected:
29+ CloseAicpuMonitorTsKernel kernel_;
30+};
31+ 
32+namespace {
33+drvError_t SubmitCustCloseMonitorSuccess(unsigned int devId, event_summary* event)
34+{
35+ EXPECT_EQ(devId, 1U);
36+ EXPECT_EQ(event->dst_engine, CCPU_DEVICE);
37+ EXPECT_EQ(event->policy, ONLY);
38+ EXPECT_EQ(event->pid, 12345);
39+ EXPECT_EQ(event->grp_id, 30U);
40+ EXPECT_EQ(event->event_id, EVENT_CCPU_CTRL_MSG);
41+ EXPECT_EQ(event->subevent_id, AICPU_SUB_EVENT_CUST_CLOSE_MONITOR);
42+ EXPECT_EQ(event->msg_len, sizeof(TsdSubEventInfo));
43+ auto info = reinterpret_cast<TsdSubEventInfo*>(event->msg);
44+ EXPECT_EQ(info->deviceId, 1U);
45+ EXPECT_EQ(info->srcPid, static_cast<uint32_t>(getpid()));
46+ EXPECT_EQ(info->dstPid, 12345U);
47+ EXPECT_EQ(info->hostPid, 54321U);
48+ EXPECT_EQ(info->vfId, 3U);
49+ EXPECT_EQ(info->procType, 1U);
50+ EXPECT_EQ(info->eventType, AICPU_SUB_EVENT_CUST_CLOSE_MONITOR);
51+ auto closeMonitorMsg = reinterpret_cast<AICPUCloseMonitorEventMsg*>(info->priMsg);
52+ EXPECT_EQ(closeMonitorMsg->closeFlag, 1U);
53+ return DRV_ERROR_NONE;
54+}
55+} // namespace
56+ 
57+TEST_F(CloseAicpuMonitorKernelTest, CloseMonitorSuccess)
58+{
59+ aicpu::HwtsTsKernel tsKernelInfo;
60+ aicpu::HwtsCceKernel cceKernel;
61+ char kernelName[] = "CloseAicpuMonitor";
62+ cceKernel.kernelName = reinterpret_cast<uint64_t>(reinterpret_cast<uintptr_t>(kernelName));
63+ struct {
64+ uint8_t monitorEn;
65+ uint8_t retcode;
66+ uint8_t rsv[2];
67+ } args = {1U, 0xFF, {0U, 0U}};
68+ cceKernel.paramBase = reinterpret_cast<uint64_t>(&args);
69+ tsKernelInfo.kernelType = 2;
70+ tsKernelInfo.kernelBase.cceKernel = cceKernel;
71+ 
72+ int ret = kernel_.Compute(tsKernelInfo);
73+ EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
74+ EXPECT_EQ(args.retcode, 0U);
75+ EXPECT_TRUE(AicpuMonitor::GetInstance().IsMonitorClosed());
76+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(false);
77+}
78+ 
79+TEST_F(CloseAicpuMonitorKernelTest, OpenMonitorSuccess)
80+{
81+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(true);
82+ aicpu::HwtsTsKernel tsKernelInfo;
83+ aicpu::HwtsCceKernel cceKernel;
84+ char kernelName[] = "CloseAicpuMonitor";
85+ cceKernel.kernelName = reinterpret_cast<uint64_t>(reinterpret_cast<uintptr_t>(kernelName));
86+ struct {
87+ uint8_t monitorEn;
88+ uint8_t retcode;
89+ uint8_t rsv[2];
90+ } args = {0U, 0xFF, {0U, 0U}};
91+ cceKernel.paramBase = reinterpret_cast<uint64_t>(&args);
92+ tsKernelInfo.kernelType = 2;
93+ tsKernelInfo.kernelBase.cceKernel = cceKernel;
94+ 
95+ int ret = kernel_.Compute(tsKernelInfo);
96+ EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
97+ EXPECT_EQ(args.retcode, 0U);
98+ EXPECT_FALSE(AicpuMonitor::GetInstance().IsMonitorClosed());
99+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(false);
100+}
101+ 
102+TEST_F(CloseAicpuMonitorKernelTest, CheckKernelSupported)
103+{
104+ int32_t ret = HwTsKernelRegister::Instance().CheckTsKernelSupported("CloseAicpuMonitor");
105+ EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
106+}
107+ 
108+TEST_F(CloseAicpuMonitorKernelTest, CheckKernelSupportedNotFound)
109+{
110+ int32_t ret = HwTsKernelRegister::Instance().CheckTsKernelSupported("CloseAicpuMonitorNotExist");
111+ EXPECT_NE(ret, AICPU_SCHEDULE_OK);
112+}
113+ 
114+TEST_F(CloseAicpuMonitorKernelTest, NullParamBase)
115+{
116+ aicpu::HwtsTsKernel tsKernelInfo;
117+ aicpu::HwtsCceKernel cceKernel;
118+ char kernelName[] = "CloseAicpuMonitor";
119+ cceKernel.kernelName = reinterpret_cast<uint64_t>(reinterpret_cast<uintptr_t>(kernelName));
120+ cceKernel.paramBase = 0U;
121+ tsKernelInfo.kernelType = 2;
122+ tsKernelInfo.kernelBase.cceKernel = cceKernel;
123+ 
124+ int ret = kernel_.Compute(tsKernelInfo);
125+ EXPECT_EQ(ret, AICPU_SCHEDULE_ERROR_PARAMETER_NOT_VALID);
126+ AicpuMonitor::GetInstance().SetCloseMonitorFlag(false);
127+}
128+ 
129+TEST_F(CloseAicpuMonitorKernelTest, NotifyCustCloseMonitorSuccess)
130+{
131+ MOCKER_CPP(&AicpuDrvManager::GetDeviceId).stubs().will(returnValue(1U));
132+ MOCKER_CPP(&AicpuDrvManager::GetHostPid).stubs().will(returnValue(54321));
133+ MOCKER_CPP(&AicpuDrvManager::GetVfId).stubs().will(returnValue(3U));
134+ int32_t custPid = 12345;
135+ MOCKER(halEschedSubmitEvent).stubs().will(invoke(SubmitCustCloseMonitorSuccess));
136+ LoadOpFromBuffTsKernel loadKernel;
137+ int ret = loadKernel.NotifyCustCloseMonitor(custPid);
138+ EXPECT_EQ(ret, AICPU_SCHEDULE_OK);
139+ GlobalMockObject::verify();
140+}
141+ 
142+TEST_F(CloseAicpuMonitorKernelTest, NotifyCustCloseMonitorFailed)
143+{
144+ MOCKER_CPP(&AicpuDrvManager::GetDeviceId).stubs().will(returnValue(1U));
145+ int32_t custPid = 12345;
146+ MOCKER(halEschedSubmitEvent).stubs().will(returnValue(DRV_ERROR_INNER_ERR));
147+ LoadOpFromBuffTsKernel loadKernel;
148+ int ret = loadKernel.NotifyCustCloseMonitor(custPid);
149+ EXPECT_EQ(ret, AICPU_SCHEDULE_ERROR_DRV_ERR);
150+ GlobalMockObject::verify();
151+}