LCOV - code coverage report
Current view: top level - server - queue_schedule.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 84.6 % 552 467
Test Date: 2026-07-28 10:54:05 Functions: 95.8 % 24 23

            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 "queue_schedule.h"
      12              : #include <unistd.h>
      13              : #include <sched.h>
      14              : #include <csignal>
      15              : #include <cerrno>
      16              : #include <string>
      17              : #include "driver/ascend_hal.h"
      18              : #include "server/bqs_server.h"
      19              : #include "server/router_server.h"
      20              : #include "bind_relation.h"
      21              : #include "bind_cpu_utils.h"
      22              : #include "statistic_manager.h"
      23              : #include "subscribe_manager.h"
      24              : #include "queue_manager.h"
      25              : #include "profile_manager.h"
      26              : #include "entity_manager.h"
      27              : #include "hccl_process.h"
      28              : #include "common/bqs_util.h"
      29              : #include "queue_schedule_sub_module_interface.h"
      30              : #include "qs_interface_process.h"
      31              : #include "queue_schedule_hal_interface_ref.h"
      32              : #include "tsd.h"
      33              : #include "schedule_config.h"
      34              : #include "dynamic_sched_mgr.hpp"
      35              : #include "fsm/state_define.h"
      36              : #include "common/bqs_feature_ctrl.h"
      37              : #include "qs_args_parser.h"
      38              : #include "queue_schedule_feature_ctrl.h"
      39              : 
      40              : namespace bqs {
      41              : namespace {
      42              : constexpr uint32_t HOST_NAME_MAX_LEN = 128U;
      43              : constexpr const char_t *AOS_SD = "AOS_SD";
      44              : constexpr const size_t FIRST_ARRAY_INDEX = 0LU;
      45              : constexpr const uint32_t DAEMON_WAIT_TIMEOUT = 30U;
      46              : constexpr const uint32_t HOST_ENQUEUE_THREAD_NUM = 10U;
      47              : constexpr const uint32_t HOST_F2NF_THREAD_NUM = 10U;
      48              : // max qos num for hccl event: must greater than thread num in F2NF group
      49              : constexpr const uint32_t MAX_QOS_NUM_FOR_HCCL_EVENT = 12U;
      50              : // max qos num for f2nf event
      51              : constexpr const uint32_t MAX_QOS_NUM_FOR_F2NF_EVENT = 1U;
      52              : constexpr const char_t *ENQUEUE_THREAD_NAME_PREFIX = "enqueue_";
      53              : constexpr const char_t *F2NF_THREAD_NAME_PREFIX = "f2nf_";
      54              : constexpr const char_t *DAEMON_THREAD_NAME_PREFIX = "daemon";
      55              : constexpr const uint32_t ERROR_LOG_SAMPLE_INTERVAL = 1000U;
      56              : 
      57            1 : void DynamicScheduleByResponse(const uint32_t key, const uint32_t index,
      58              :     const std::vector<dgw::DynamicSchedMgr::ResponseInfo> &responses)
      59              : {
      60            1 :     BQS_LOG_INFO("responses size is %zu", responses.size());
      61            2 :     for (const auto &response : responses) {
      62              :         dgw::EntityPtr dynamicSrcEntity =
      63            1 :             dgw::EntityManager::Instance(index).GetSrcEntityByGlobalId(key, response.src.queueLogicId);
      64            1 :         if (dynamicSrcEntity == nullptr) {
      65            0 :             BQS_LOG_ERROR("Can't get entity by key[%u], globalId[%u]", key, response.src.queueLogicId);
      66            0 :             continue;
      67              :         }
      68              : 
      69            1 :         uint32_t updateCount = 0U;
      70            1 :         const auto &dataResults = response.groupResults;
      71            2 :         for (const auto groupResult : dataResults) {
      72              :             dgw::EntityPtr dynamicDstGrpEnity =
      73            1 :                 dgw::EntityManager::Instance(index).GetDstEntityByGlobalId(key, groupResult.logicGroupId);
      74            1 :             if (dynamicDstGrpEnity == nullptr) {
      75            0 :                 BQS_LOG_ERROR("Can't get entity by key[%u], globalId[%u]", key, groupResult.logicGroupId);
      76            0 :                 continue;
      77              :             }
      78              :             const std::vector<dgw::EntityPtr> &entitiesInGroup =
      79            1 :                 dgw::EntityManager::Instance(index).GetEntitiesInGroup(dynamicDstGrpEnity->GetId());
      80            1 :             if (entitiesInGroup.size() <= groupResult.index) {
      81            0 :                 BQS_LOG_ERROR("Dynamic response's index[%u] is larger than group size[%zu]",
      82              :                     groupResult.index, entitiesInGroup.size());
      83            0 :                 continue;
      84              :             }
      85            1 :             const dgw::EntityPtr dynamicDstInGroup = entitiesInGroup[groupResult.index];
      86            1 :             if (dynamicSrcEntity->UpdateSendObject(dynamicDstGrpEnity, dynamicDstInGroup)) {
      87            1 :                 ++updateCount;
      88              :             }
      89            1 :         }
      90            1 :         BQS_LOG_INFO("updateCount is %u", updateCount);
      91            1 :         if (updateCount > 0U) {
      92            1 :             BQS_LOG_INFO("%s processMessage", dynamicSrcEntity->ToString().c_str());
      93            1 :             dgw::DynamicSchedMgr::GetInstance(index).DynamicSchedDurationEnd(dynamicSrcEntity->GetDynamicReqTime());
      94            1 :             dgw::InnerMessage msg;
      95            1 :             msg.msgType = dgw::InnerMsgType::INNER_MSG_PUSH;
      96            1 :             (void) dynamicSrcEntity->ProcessMessage(msg);
      97              :         }
      98            1 :     }
      99            1 : }
     100              : thread_local static int32_t thread_groupId;
     101              : thread_local static int32_t thread_deviceId;
     102              : 
     103            0 : int32_t getGrpId(int32_t tag, int32_t *grpId, int32_t *deviceId)
     104              : {
     105              :     (void) tag;
     106            0 :     if ((grpId == nullptr) || (deviceId == nullptr)) {
     107            0 :         return -1;
     108              :     }
     109            0 :     *grpId = thread_groupId;
     110            0 :     *deviceId = thread_deviceId;
     111            0 :     return 0;
     112              : }
     113              : 
     114              : }  // namespace
     115              : 
     116           18 : BqsStatus QueueSchedule::StartQueueSchedule()
     117              : {
     118           18 :     auto ret = BqsServer::GetInstance().InitBqsServer(qsInitGroupName_, deviceId_);
     119           18 :     if (ret != BQS_STATUS_OK) {
     120            0 :         BQS_LOG_ERROR("BqsServer Init failed, ret=%d.", ret);
     121            0 :         return ret;
     122              :     }
     123           18 :     ret = RouterServer::GetInstance().InitRouterServer(initQsParams_);
     124           18 :     if (ret != BQS_STATUS_OK) {
     125            2 :         BQS_LOG_ERROR("RouterServer Init failed, ret=%d.", ret);
     126            2 :         return ret;
     127              :     }
     128              : 
     129           16 :     GlobalCfg::GetInstance().SetNumaFlag(initQsParams_.numaFlag);
     130           16 :     GlobalCfg::GetInstance().RecordDeviceId(deviceId_, 0U, enqueGroupId_);
     131           16 :     reschedInterval_ = (reschedInterval_ == 0U) ? DAEMON_WAIT_TIMEOUT : reschedInterval_;
     132           32 :     abnormalInterval_ = ((initQsParams_.abnormalInterVal > ABNORMAL_INTERVAL_MIN) &&
     133           16 :                          (initQsParams_.abnormalInterVal < ABNORMAL_INTERVAL_MAX)) ?
     134              :                             initQsParams_.abnormalInterVal : ABNORMAL_INTERVAL_DEFAULT;
     135           16 :     StatisticManager::GetInstance().StartStatisticManager(
     136           16 :         abnormalInterval_, initQsParams_.pid, initQsParams_.numaFlag, initQsParams_.deviceIdExtra,
     137              :         initQsParams_.enqueGroupIdExtra);
     138              : 
     139           16 :     char_t hostNameStr[HOST_NAME_MAX_LEN] = {};
     140           16 :     const int32_t getNameRet = gethostname(&hostNameStr[FIRST_ARRAY_INDEX], HOST_NAME_MAX_LEN);
     141           16 :     if (getNameRet < 0) {
     142            0 :         BQS_LOG_ERROR("gethostname failed, ret=%d.", getNameRet);
     143            0 :         return BQS_STATUS_INNER_ERROR;
     144              :     }
     145           16 :     const std::string nameStr(hostNameStr);
     146           16 :     uint32_t threadNum = 0U;
     147           16 :     if (nameStr == AOS_SD) {
     148            3 :         hasAICPU_ = false;
     149            3 :         threadNum = 1U;
     150              :     }
     151           16 :     BQS_LOG_INFO("StartQueueSchedule schedPolicy:[%lu].", initQsParams_.schedPolicy);
     152           16 :     if (hasAICPU_ && (bqs::RunContext::HOST != bqs::GetRunContext())) {
     153            3 :         uint32_t aicpuNum = QueueScheduleInterface::GetInstance().GetAiCpuNum();
     154            3 :         BQS_LOG_RUN_INFO("the number of AICPU cores: %d", aicpuNum);
     155            3 :         if (aicpuNum == 0U) {
     156            2 :             isZeroSizeAicpuNum_ = true;
     157            2 :             threadNum = 1U;
     158              :         } else {
     159            1 :             threadNum = aicpuNum;
     160              :         }
     161              :     }
     162           16 :     BQS_LOG_RUN_INFO("Has aicpu:%d, numaFlag:%d, deviceId_:%u.",
     163              :         static_cast<int32_t>(hasAICPU_), initQsParams_.numaFlag, deviceId_);
     164              : 
     165           16 :     aicpuFeatureDisableRecvRequestEvent_ = (bqs::GetRunContext() == bqs::RunContext::HOST) ? false : QSFeatureCtrl::ShouldDisableRecvRequestEvent(deviceId_);
     166           16 :     aicpuFeatureSetPidPriority_ = (bqs::GetRunContext() == bqs::RunContext::HOST) ? false : QSFeatureCtrl::ShouldSetPidPriority(deviceId_);
     167           16 :     ret = InitDrvSchedModule(deviceId_, enqueGroupId_, f2nfGroupId_);
     168           16 :     if (ret != BQS_STATUS_OK) {
     169            2 :         BQS_LOG_ERROR("InitDrvSchedModule failed, ret=%d.", ret);
     170            2 :         return ret;
     171              :     }
     172              : 
     173           14 :     ret = QueueManager::GetInstance().InitQueueManager(deviceId_, enqueGroupId_, hasAICPU_, qsInitGroupName_);
     174           14 :     if (ret != BQS_STATUS_OK) {
     175            1 :         BQS_LOG_ERROR("QueueManager Init failed, ret=%d.", ret);
     176            1 :         return ret;
     177              :     }
     178              : 
     179           13 :     std::set<uint32_t> resDevids(initQsParams_.devIdVec.begin(), initQsParams_.devIdVec.end());
     180           13 :     resDevids.insert(deviceId_);
     181           13 :     if (initQsParams_.numaFlag) {
     182            5 :         resDevids.insert(initQsParams_.deviceIdExtra);
     183              :     }
     184           13 :     Subscribers::GetInstance().InitSubscribeManagers(resDevids, deviceId_);
     185              : 
     186           13 :     ProfileManager::GetInstance(0U).InitProfileManager(deviceId_);
     187           13 :     dgw::EntityManager::Instance(0U).SetSubscriptionPausePolicy(
     188           13 :         (initQsParams_.schedPolicy & static_cast<uint64_t>(SchedPolicy::POLICY_UNSUB_F2NF)) == 0UL);
     189              : 
     190           13 :     running_ = true;
     191           13 :     if (BindCpuUtils::InitSem() != BQS_STATUS_OK) {
     192            0 :         BQS_LOG_ERROR("InitSem failed");
     193            0 :         return BQS_STATUS_INNER_ERROR;
     194              :     }
     195              : 
     196           13 :     auto threadRet = StartThreadGroup(threadNum, deviceId_, enqueGroupId_, 0U);
     197           13 :     if (threadRet != BQS_STATUS_OK) {
     198            0 :         BQS_LOG_ERROR("StartThreadGroup failed");
     199            0 :         BindCpuUtils::DestroySem();
     200            0 :         return threadRet;
     201              :     }
     202              : 
     203           13 :     if (initQsParams_.numaFlag) {
     204            5 :         const auto extraRet = InitExtraSchedule(resDevids, threadNum);
     205            5 :         if (extraRet != BQS_STATUS_OK) {
     206            3 :             BQS_LOG_ERROR("InitExtraSchedule failed, ret is %d.", static_cast<int32_t>(extraRet));
     207            3 :             BindCpuUtils::DestroySem();
     208            3 :             return extraRet;
     209              :         }
     210              :     }
     211              : 
     212           10 :     BindCpuUtils::DestroySem();
     213           10 :     RouterServer::GetInstance().NotifyInitSuccess();
     214           10 :     return BQS_STATUS_OK;
     215           16 : }
     216              : 
     217            5 : BqsStatus QueueSchedule::InitExtraSchedule(const std::set<uint32_t> &resDevids, uint32_t threadNum)
     218              : {
     219            5 :     BqsStatus ret = InitDrvSchedModule(initQsParams_.deviceIdExtra, initQsParams_.enqueGroupIdExtra,
     220              :         initQsParams_.f2nfGroupIdExtra);
     221            5 :     if (ret != BQS_STATUS_OK) {
     222            1 :         BQS_LOG_ERROR("InitDrvSchedModule failed, ret=%d.", static_cast<int32_t>(ret));
     223            1 :         return ret;
     224              :     }
     225            4 :     GlobalCfg::GetInstance().RecordDeviceId(initQsParams_.deviceIdExtra, 1U, initQsParams_.enqueGroupIdExtra);
     226              : 
     227            4 :     QueueManager::GetInstance().InitExtra(initQsParams_.deviceIdExtra, initQsParams_.enqueGroupIdExtra);
     228              : 
     229            4 :     Subscribers::GetInstance().InitSubscribeManagers(resDevids, initQsParams_.deviceIdExtra);
     230              : 
     231            4 :     ProfileManager::GetInstance(1U).InitProfileManager(initQsParams_.deviceIdExtra);
     232              : 
     233            4 :     dgw::EntityManager::Instance(1U).SetSubscriptionPausePolicy(
     234            4 :         (initQsParams_.schedPolicy & static_cast<uint64_t>(SchedPolicy::POLICY_UNSUB_F2NF)) == 0UL);
     235              : 
     236            4 :     if (hasAICPU_ && (bqs::RunContext::HOST != bqs::GetRunContext())) {
     237            1 :         uint32_t aicpuNum = QueueScheduleInterface::GetInstance().GetExtraAiCpuNum();
     238            1 :         BQS_LOG_RUN_INFO("the number of Extra AICPU cores: %d", aicpuNum);
     239            1 :         if (aicpuNum == 0U) {
     240            1 :             aicpuNum = 1U;
     241              :         }
     242            1 :         threadNum = aicpuNum;
     243              :     }
     244              : 
     245            4 :     BqsStatus threadRet = StartThreadGroup(threadNum, initQsParams_.deviceIdExtra, initQsParams_.enqueGroupIdExtra, 1U);
     246            4 :     if (threadRet != BQS_STATUS_OK) {
     247            1 :         BQS_LOG_ERROR("StartThreadGroup failed");
     248            1 :         return threadRet;
     249              :     }
     250              : 
     251            3 :     const auto setCallbackRes = HcclSetGrpIdCallback(getGrpId);
     252            3 :     if (setCallbackRes != HCCL_SUCCESS) {
     253            1 :         BQS_LOG_ERROR("SetCallback failed, res is %d", static_cast<int32_t>(setCallbackRes));
     254            1 :         return BQS_STATUS_HCCL_ERROR;
     255              :     }
     256            2 :     return BQS_STATUS_OK;
     257              : }
     258              : 
     259           15 : BqsStatus QueueSchedule::StartThreadGroup(const uint32_t threadNum, const uint32_t deviceId,
     260              :                                           const uint32_t enqueGroupId, const uint32_t index)
     261              : {
     262           15 :     const sighandler_t oldHandler = signal(SIGCHLD, static_cast<sighandler_t>(SIG_DFL));
     263           15 :     const uint32_t enqueueThreadNum = (bqs::RunContext::HOST == bqs::GetRunContext()) ? HOST_ENQUEUE_THREAD_NUM
     264           15 :                                                                                       : threadNum;
     265           15 :     uint32_t vDevNum = 0U;
     266           15 :     if ((FeatureCtrl::IsVfModeCheckedByDeviceId(deviceId)) && (&halGetVdevNum != nullptr)) {
     267            0 :         int32_t ret = halGetVdevNum(&vDevNum);
     268            0 :         if (ret != 0) {
     269            0 :             BQS_LOG_ERROR("halGetVdevNum, failed result[%d]", ret);
     270            0 :             return BQS_STATUS_DRIVER_ERROR;
     271              :         }
     272              :     }
     273           15 :     BQS_LOG_INFO("Get vdev num=[%u] success.", vDevNum);
     274          129 :     for (uint32_t thIndex = 0U; thIndex < enqueueThreadNum; ++thIndex) {
     275              :         // create enqueue event thread
     276          114 :         uint32_t aicpuIndex = 0U;
     277          114 :         if (bqs::RunContext::HOST != bqs::GetRunContext()) {
     278            4 :             if (vDevNum > 0U) {
     279            0 :                 aicpuIndex = (index == 0U) ?
     280            0 :                     QueueScheduleInterface::GetInstance().GetAicpuPhysIndexInVfMode(thIndex, deviceId) :
     281            0 :                     QueueScheduleInterface::GetInstance().GetExtraAicpuPhysIndexInVfMode(thIndex, deviceId);
     282              :             } else {
     283            8 :                 aicpuIndex = (index == 0U) ?
     284            4 :                     QueueScheduleInterface::GetInstance().GetAicpuPhysIndex(deviceId, thIndex) :
     285            0 :                     QueueScheduleInterface::GetInstance().GetExtraAicpuPhysIndex(deviceId, thIndex);
     286              :             }
     287              :         }
     288          114 :         (void) workThreads_.emplace_back(
     289          114 :             &QueueSchedule::EnqueueThreadTask, this, deviceId, thIndex, aicpuIndex, enqueGroupId, index);
     290              :     }
     291           15 :     if (bqs::RunContext::HOST != bqs::GetRunContext()) {
     292            4 :         (void)workThreads_.emplace_back(&QueueSchedule::DaemonThreadTask, this, index);
     293              :     }
     294              : 
     295           15 :     uint32_t f2nfThreadNum = (bqs::RunContext::HOST == bqs::GetRunContext()) ? HOST_F2NF_THREAD_NUM : threadNum;
     296           15 :     if (initQsParams_.numaFlag) {
     297              :         // these event will be processed by enque thread on condition numa, so we need not create f2nf threads
     298            7 :         f2nfThreadNum = 0U;
     299              :     }
     300           59 :     for (uint32_t thIndex = 0U; thIndex < f2nfThreadNum; ++thIndex) {
     301              :         // create f2nf event thread
     302           44 :         uint32_t aicpuIndex = 0U;
     303           44 :         if (bqs::RunContext::HOST != bqs::GetRunContext()) {
     304            4 :             if (vDevNum > 0U) {
     305            0 :                 aicpuIndex = QueueScheduleInterface::GetInstance().GetAicpuPhysIndexInVfMode(thIndex, deviceId);
     306              :             } else {
     307            4 :                 aicpuIndex = QueueScheduleInterface::GetInstance().GetAicpuPhysIndex(deviceId_, thIndex);
     308              :             }
     309              :         }
     310           44 :         (void) workThreads_.emplace_back(
     311           44 :             &QueueSchedule::F2NFThreadTask, this, thIndex, aicpuIndex, f2nfGroupId_);
     312              :     }
     313              : 
     314          173 :     for (uint32_t thIndex = 0U; thIndex < enqueueThreadNum + f2nfThreadNum; ++thIndex) {
     315              :         // EnqueueThreadTask thread
     316          158 :         if (BindCpuUtils::WaitSem() != BQS_STATUS_OK) {
     317            0 :             BQS_LOG_ERROR("WaitSem failed");
     318            0 :             return BQS_STATUS_INNER_ERROR;
     319              :         }
     320              :     }
     321           15 :     (void)signal(SIGCHLD, oldHandler);
     322           15 :     return BQS_STATUS_OK;
     323              : }
     324              : 
     325          308 : void QueueSchedule::StopQueueSchedule()
     326              : {
     327          308 :     running_ = false;
     328          308 :     const std::unique_lock<std::mutex> daemonWaitLock(daemonWaitMtx_);
     329          308 :     daemonWait_.notify_all();
     330          308 :     StatisticManager::GetInstance().DumpOutProcMemStatInfo();
     331          308 :     StatisticManager::GetInstance().StopStatisticManager();
     332          308 :     ProfileManager::GetInstance(0U).Uninit();
     333          308 :     if (initQsParams_.numaFlag) {
     334           10 :         ProfileManager::GetInstance(1U).Uninit();
     335              :     }
     336          308 : }
     337              : 
     338           55 : void QueueSchedule::Destroy() const
     339              : {
     340           55 :     QueueManager::GetInstance().Destroy();
     341           55 :     if (!SubModuleInterface::GetInstance().GetStartFlag()) {
     342           53 :         (void)halEschedDettachDevice(deviceId_);
     343           53 :         if (initQsParams_.numaFlag) {
     344            5 :             (void)halEschedDettachDevice(initQsParams_.deviceIdExtra);
     345              :         }
     346              :     } else {
     347            2 :         BQS_LOG_RUN_INFO("sub module no need process detach main module do it");
     348              :     }
     349           55 : }
     350              : 
     351          114 : void QueueSchedule::EnqueueThreadTask(const uint32_t deviceId, const uint32_t threadIndex, const uint32_t bindCpuIndex,
     352              :                                       const uint32_t groupId, const uint32_t index)
     353              : {
     354          114 :     BQS_LOG_INFO("QueueSchedule enqueue thread[%u] start.", threadIndex);
     355          114 :     BindAicpu(threadIndex, bindCpuIndex);
     356          114 :     const auto threadName = std::string(ENQUEUE_THREAD_NAME_PREFIX).append(std::to_string(threadIndex));
     357          114 :     (void)pthread_setname_np(pthread_self(), threadName.c_str());
     358          114 :     thread_groupId = groupId;
     359          114 :     thread_deviceId = deviceId;
     360              : 
     361          114 :     const uint64_t eventBitmap =
     362              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(EVENT_QUEUE_ENQUEUE)) |
     363              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(EVENT_QUEUE_FULL_TO_NOT_FULL)) |
     364              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_RECV_REQUEST_MSG)) |
     365              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_SEND_COMPLETION_MSG)) |
     366              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_RECV_COMPLETION_MSG)) |
     367              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_CONGESTION_RELIEF_MSG));
     368          114 :     BQS_LOG_INFO("Enque group[%u] subscribe event, eventBitmap[%lu] deviceId[%u]", groupId, eventBitmap, deviceId);
     369          114 :     const int32_t ret = halEschedSubscribeEvent(deviceId, groupId, threadIndex, eventBitmap);
     370          114 :     if (ret != DRV_ERROR_NONE) {
     371            0 :         BQS_LOG_ERROR("halEschedSubscribeEvent failed, groupId[%u] eventBitmap[%lu] result[%d].",
     372              :             groupId, eventBitmap, ret);
     373            0 :         StopQueueSchedule();
     374            0 :         return;
     375              :     }
     376              :     // set max num for hccl event
     377          114 :     event_sched_grp_qos qos = {};
     378              :     const std::vector<uint32_t> eventList = {dgw::EVENT_RECV_REQUEST_MSG, dgw::EVENT_SEND_COMPLETION_MSG,
     379          228 :         dgw::EVENT_RECV_COMPLETION_MSG, EVENT_QUEUE_FULL_TO_NOT_FULL};
     380          566 :     for (const uint32_t eventId : eventList) {
     381          452 :         qos.maxNum = (eventId == static_cast<uint32_t>(EVENT_QUEUE_FULL_TO_NOT_FULL)) ?
     382              :             MAX_QOS_NUM_FOR_F2NF_EVENT : MAX_QOS_NUM_FOR_HCCL_EVENT;
     383          452 :         const auto drvRet = halEschedSetGrpEventQos(deviceId, groupId, static_cast<EVENT_ID>(eventId), &qos);
     384          452 :         if (drvRet != DRV_ERROR_NONE) {
     385            0 :             BQS_LOG_ERROR("Failed to call halEschedSetGrpEventQos, groupId[%u], qos.maxNum[%u], ret[%d].",
     386              :                 groupId, qos.maxNum, static_cast<int32_t>(drvRet));
     387            0 :             StopQueueSchedule();
     388            0 :             return;
     389              :         }
     390              :     }
     391          112 :     LoopProcessEnqueueEvent(threadIndex, deviceId, groupId, index);
     392          114 : }
     393              : 
     394          159 : void QueueSchedule::BindAicpu(const uint32_t threadIndex, const uint32_t bindCpuIndex)
     395              : {
     396          159 :     if (bqs::RunContext::HOST != bqs::GetRunContext()) {
     397            8 :         if (!hasAICPU_) {
     398              :             struct sched_param param;
     399            4 :             param.sched_priority = sched_get_priority_max(SCHED_FIFO);
     400            4 :             if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
     401            4 :                 BQS_LOG_ERROR("QueueSchedule sched_setscheduler failed, errno:%d, thread exit.", errno);
     402            4 :                 StopQueueSchedule();
     403              :             }
     404              :         } else {
     405            4 :             if (!isZeroSizeAicpuNum_) {
     406            2 :                 const int32_t status = BindCpuUtils::BindAicpu(bindCpuIndex);
     407            2 :                 if (status != BQS_STATUS_OK) {
     408            2 :                     BQS_LOG_ERROR(
     409              :                         "QueueSchedule enqueue thread[%u] bind cpu[%u] failed, thread exit.",
     410              :                         threadIndex, bindCpuIndex);
     411            2 :                     StopQueueSchedule();
     412              :                 }
     413              :             }
     414              :         }
     415              :     }
     416              : 
     417          159 :     if (BindCpuUtils::PostSem() != BQS_STATUS_OK) {
     418            0 :         BQS_LOG_ERROR("WaitPost failed");
     419              :     }
     420          159 : }
     421              : 
     422          154 : void QueueSchedule::CheckIfRecover(uint32_t &errCount, const char_t * const identity, const uint32_t threadIndex,
     423              :                                    const uint32_t groupId) const
     424              : {
     425          154 :     if (errCount != 0U) {
     426            1 :         errCount = 0U;
     427            1 :         BQS_LOG_ERROR("halEschedWaitEvent %s event recover, threadIndex[%u] groupId[%u]",
     428              :                       identity, threadIndex, groupId);
     429              :     }
     430          154 : }
     431              : 
     432          114 : void QueueSchedule::LoopProcessEnqueueEvent(const uint32_t threadIndex, const uint32_t deviceId,
     433              :     const uint32_t groupId, const uint32_t index)
     434              : {
     435          114 :     QueueManager::GetInstance().NotifyInitSuccess(index);
     436          115 :     struct event_info event = {};
     437              :     // default wait timeout 2s
     438          115 :     constexpr int32_t waitTimeout = 2000;
     439          115 :     uint32_t errCount = 0U;
     440          243 :     while (running_) {
     441          129 :         StatisticManager::GetInstance().RefreshEnqueHeartBeat();
     442          129 :         const int32_t schedRet = halEschedWaitEvent(deviceId, groupId, threadIndex, waitTimeout, &event);
     443          129 :         if (schedRet == DRV_ERROR_NONE) {
     444          111 :             CheckIfRecover(errCount, "enqueue", threadIndex, groupId);
     445          111 :             StatisticManager::GetInstance().AwakenAdd();
     446          111 :             ProcessEvent(threadIndex, event, index);
     447           18 :         } else if (schedRet == DRV_ERROR_SCHED_WAIT_TIMEOUT) {
     448            3 :             CheckIfRecover(errCount, "enqueue", threadIndex, groupId);
     449            3 :             BQS_LOG_DEBUG("halEschedWaitEvent enqueue event timeout, groupId=%u, thread index:%u",
     450              :                 groupId, threadIndex);
     451            3 :             continue;
     452           15 :         } else if (schedRet == DRV_ERROR_PARA_ERROR) {
     453            1 :             BQS_LOG_ERROR(
     454              :                     "halEschedWaitEvent enqueue event failed, deviceId[%u] threadIndex[%u] groupId[%u] error[%d].",
     455              :                     deviceId, threadIndex, groupId, schedRet);
     456            1 :             break;
     457              :         } else {
     458           14 :             if (errCount++ == 0U) {
     459            1 :                 BQS_LOG_ERROR(
     460              :                     "halEschedWaitEvent enqueue event failed, deviceId[%u] threadIndex[%u] groupId[%u] error[%d].",
     461              :                     deviceId, threadIndex, groupId, schedRet);
     462              :             }
     463              :         }
     464              :     }
     465              : 
     466          115 :     BQS_LOG_INFO("QueueSchedule enqueue thread[%u] exit", threadIndex);
     467          115 : }
     468              : 
     469           45 : void QueueSchedule::F2NFThreadTask(const uint32_t threadIndex, const uint32_t bindCpuIndex, const uint32_t groupId)
     470              : {
     471           45 :     BQS_LOG_INFO("Queue Schedule f2nf thread[%u] start.", threadIndex);
     472           45 :     const auto threadName = std::string(F2NF_THREAD_NAME_PREFIX).append(std::to_string(threadIndex));
     473           45 :     (void)pthread_setname_np(pthread_self(), threadName.c_str());
     474           45 :     BindAicpu(threadIndex, bindCpuIndex);
     475           45 :     const uint64_t eventBitmap =
     476              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_RECV_REQUEST_MSG)) |
     477              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_SEND_COMPLETION_MSG)) |
     478              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_RECV_COMPLETION_MSG)) |
     479              :         static_cast<uint64_t>(1LU << static_cast<uint64_t>(dgw::EVENT_CONGESTION_RELIEF_MSG));
     480              : 
     481           45 :     BQS_LOG_INFO("F2NF group[%u] subscribe event, eventBitmap[%lu]", f2nfGroupId_, eventBitmap);
     482           45 :     const auto ret = halEschedSubscribeEvent(deviceId_, f2nfGroupId_, threadIndex, eventBitmap);
     483           45 :     if (ret != DRV_ERROR_NONE) {
     484            0 :         BQS_LOG_ERROR("halEschedSubscribeEvent failed, groupId[%u] eventBitmap[%lu] result[%d].",
     485              :             f2nfGroupId_, eventBitmap, static_cast<int32_t>(ret));
     486            0 :         StopQueueSchedule();
     487            0 :         return;
     488              :     }
     489              : 
     490              :     // set max num for hccl event
     491           45 :     event_sched_grp_qos qos = {};
     492              :     const std::vector<uint32_t> eventList = {dgw::EVENT_RECV_REQUEST_MSG, dgw::EVENT_SEND_COMPLETION_MSG,
     493           90 :         dgw::EVENT_RECV_COMPLETION_MSG};
     494          180 :     for (const uint32_t eventId : eventList) {
     495          135 :         qos.maxNum = MAX_QOS_NUM_FOR_HCCL_EVENT;
     496          135 :         const auto drvRet = halEschedSetGrpEventQos(deviceId_, f2nfGroupId_, static_cast<EVENT_ID>(eventId), &qos);
     497          135 :         if (drvRet != DRV_ERROR_NONE) {
     498            0 :             BQS_LOG_ERROR("Failed to call halEschedSetGrpEventQos, groupId[%u], qos.maxNum[%u], ret[%d].",
     499              :                 f2nfGroupId_, qos.maxNum, static_cast<int32_t>(drvRet));
     500            0 :             StopQueueSchedule();
     501            0 :             return;
     502              :         }
     503              :     }
     504              : 
     505           45 :     struct event_info event = {};
     506              :     // default wait timeout 2s
     507           45 :     constexpr int32_t waitTimeout = 2000;
     508           45 :     uint32_t errCount = 0U;
     509           99 :     while (running_) {
     510           55 :         const int32_t schedRet = halEschedWaitEvent(deviceId_, groupId, threadIndex, waitTimeout, &event);
     511           55 :         if (schedRet == DRV_ERROR_NONE) {
     512           40 :             CheckIfRecover(errCount, "f2nf", threadIndex, groupId);
     513           40 :             (void)ProcessEvent(threadIndex, event, 0U);
     514           15 :         } else if (schedRet == DRV_ERROR_SCHED_WAIT_TIMEOUT) {
     515            0 :             CheckIfRecover(errCount, "f2nf", threadIndex, groupId);
     516            0 :             BQS_LOG_DEBUG("halEschedWaitEvent f2nf event timeout,thread index:%u", threadIndex);
     517            0 :             continue;
     518           15 :         } else if (schedRet == DRV_ERROR_PARA_ERROR) {
     519            1 :             BQS_LOG_ERROR(
     520              :                 "halEschedWaitEvent f2nf event failed, deviceId[%u] threadIndex[%u] groupId[%u] error[%d].",
     521              :                 deviceId_, threadIndex, groupId, schedRet);
     522            1 :             break;
     523              :         } else {
     524           14 :             if (errCount++ == 0U) {
     525            1 :                 BQS_LOG_ERROR(
     526              :                     "halEschedWaitEvent f2nf event failed, deviceId[%u] threadIndex[%u] groupId[%u] error[%d].",
     527              :                     deviceId_, threadIndex, groupId, schedRet);
     528              :             }
     529              :         }
     530              :     }
     531           45 :     BQS_LOG_INFO("Queue Schedule f2nf thread[%u] exit", threadIndex);
     532           45 : }
     533              : 
     534          166 : BqsStatus QueueSchedule::ProcessEvent(const uint32_t threadIndex, event_info &event, const uint32_t index)
     535              : {
     536          166 :     auto ret = dgw::FsmStatus::FSM_SUCCESS;
     537          166 :     const uint32_t eventId = event.comm.event_id;
     538          166 :     const uint32_t deviceId = (index == 0) ? deviceId_ : initQsParams_.deviceIdExtra;
     539              : 
     540          166 :     switch (eventId) {
     541            0 :         case static_cast<uint32_t>(EVENT_QUEUE_ENQUEUE): {
     542            0 :             BQS_LOG_INFO("the [%u]th thread[%u] recv enqueEvent", index, threadIndex);
     543            0 :             ProcessEnqueueEvent(threadIndex, event, index, false);
     544            0 :             break;
     545              :         }
     546            1 :         case static_cast<uint32_t>(EVENT_QUEUE_FULL_TO_NOT_FULL): {
     547            1 :             BQS_LOG_INFO("the [%u]th thread[%u] recv f2nfEvent", index, threadIndex);
     548            1 :             ProcessEnqueueEvent(threadIndex, event, index, true);
     549            1 :             break;
     550              :         }
     551            3 :         case dgw::EVENT_RECV_REQUEST_MSG: {
     552            3 :             ret = dgw::HcclProcess::GetInstance().ProcessRecvRequestEvent(event, deviceId, index);
     553            3 :             break;
     554              :         }
     555            4 :         case dgw::EVENT_SEND_COMPLETION_MSG: {
     556            4 :             ret = dgw::HcclProcess::GetInstance().ProcessSendCompletionEvent(event, deviceId, index);
     557            4 :             break;
     558              :         }
     559            5 :         case dgw::EVENT_RECV_COMPLETION_MSG: {
     560            5 :             ret = dgw::HcclProcess::GetInstance().ProcessRecvCompletionEvent(event, deviceId, index);
     561            5 :             break;
     562              :         }
     563            1 :         case dgw::EVENT_CONGESTION_RELIEF_MSG: {
     564            1 :             ret = dgw::HcclProcess::GetInstance().ProcessCongestionReliefEvent(event, deviceId, index);
     565            1 :             break;
     566              :         }
     567          152 :         default: {
     568          152 :             BQS_LOG_WARN("Unsupported event[%u].", eventId);
     569          152 :             ret = dgw::FsmStatus::FSM_FAILED;
     570          152 :             break;
     571              :         }
     572              :     }
     573              : 
     574          166 :     if (ret != dgw::FsmStatus::FSM_SUCCESS) {
     575          152 :         return BqsStatus::BQS_STATUS_INNER_ERROR;
     576              :     }
     577           14 :     return BqsStatus::BQS_STATUS_OK;
     578              : }
     579              : 
     580            4 : void QueueSchedule::DaemonThreadTask(const uint32_t index)
     581              : {
     582            4 :     BQS_LOG_INFO("Queue Schedule Daemon thread start.");
     583            4 :     (void)pthread_setname_np(pthread_self(), DAEMON_THREAD_NAME_PREFIX);
     584            4 :     const uint32_t deviceId = (index == 0) ? deviceId_ : initQsParams_.deviceIdExtra;
     585            4 :     const uint32_t enqueGroupId = (index == 0) ? enqueGroupId_ : initQsParams_.enqueGroupIdExtra;
     586            4 :     BindCpuUtils::SetThreadFIFO(deviceId);
     587              : 
     588              :     // fixme: can run concurrancyly for different index
     589            4 :     std::unique_lock<std::mutex> daemonWaitLock(daemonWaitMtx_);
     590            4 :     uint64_t awakenTimes = 0UL;
     591              :     QueueSubscriber subscriber;
     592            4 :     subscriber.devId = deviceId;
     593            4 :     subscriber.spGrpId = 0;
     594            4 :     subscriber.pid = static_cast<int32_t>(getpid());
     595            4 :     subscriber.groupId = static_cast<int32_t>(enqueGroupId);
     596            4 :     while ((daemonWait_.wait_for(daemonWaitLock, std::chrono::milliseconds(reschedInterval_)) ==
     597            4 :             std::cv_status::timeout) && (running_)) {
     598            0 :         if (StatisticManager::GetInstance().GetEventScheduleStat() == 0U) {
     599              :             // no work to do
     600            0 :             continue;
     601              :         }
     602            0 :         const uint64_t newAwakenTimes = StatisticManager::GetInstance().GetAwakenTimes();
     603            0 :         if (awakenTimes == newAwakenTimes) {
     604            0 :             int32_t ret = halQueueCtrlEvent(&subscriber, QUE_PAUSE_EVENT);
     605            0 :             if (ret == DRV_ERROR_NONE) {
     606            0 :                 DaemonEnqueueEvent(index);
     607            0 :                 ret = halQueueCtrlEvent(&subscriber, QUE_RESUME_EVENT);
     608            0 :                 if (ret != DRV_ERROR_NONE) {
     609            0 :                     BQS_LOG_ERROR(
     610              :                         "halQueueCtrlEvent QUE_RESUME_EVENT failed, deviceId_[%u] enqueGroupId_[%u] ret[%d].",
     611              :                         deviceId, enqueGroupId, ret);
     612              :                 }
     613              :             } else {
     614            0 :                 BQS_LOG_RUN_WARN("halQueueCtrlEvent QUE_PAUSE_EVENT failed, deviceId_[%u] enqueGroupId_[%u] ret[%d].",
     615              :                     deviceId, enqueGroupId, ret);
     616              :             }
     617              :         } else {
     618            0 :             awakenTimes = newAwakenTimes;
     619              :         }
     620              :     }
     621            4 :     BQS_LOG_INFO("Queue Schedule Daemon thread exit");
     622            4 : }
     623              : 
     624            3 : void QueueSchedule::ProcessEnqueueEvent(const uint32_t threadIndex, const event_info &event, const uint32_t index,
     625              :     const bool procF2NF)
     626              : {
     627            3 :     auto &queueEventAtomicFlag = (index == 0U) ? queueEventAtomicFlag_ : queueEventAtomicFlagExtra_;
     628              :     // if other thread is working do nothing; if not set work flag.
     629            3 :     if (!queueEventAtomicFlag.test_and_set()) {
     630            1 :         ProfileManager &profileManager = ProfileManager::GetInstance(index);
     631            1 :         const uint64_t eventBegin = profileManager.GetCpuTick();
     632            1 :         const uint64_t schedDelay = static_cast<uint64_t>(event.comm.sched_timestamp - event.comm.submit_timestamp);
     633            1 :         const uint64_t schedTimes = StatisticManager::GetInstance().EventScheduleStat();
     634            1 :         profileManager.InitMaker(schedTimes, schedDelay);
     635              : 
     636              :         // handle relation queue
     637            1 :         const bool procRelation = QueueManager::GetInstance().HandleRelationEvent(index);
     638            1 :         const uint64_t f2NFBegin = profileManager.GetCpuTick();
     639            1 :         profileManager.SetRelationCost(f2NFBegin - eventBegin);
     640              : 
     641              :         // handle full to not full queue
     642            1 :         bool hasF2NF = QueueManager::GetInstance().HandleFullToNotFullEvent(index);
     643            1 :         profileManager.Setf2NFCost(profileManager.GetCpuTick() - f2NFBegin);
     644            1 :         hasF2NF |= procF2NF;
     645              : 
     646              :         // handle schedule data
     647            1 :         const bool procAsynMemBuff = QueueManager::GetInstance().HandleAsynMemBuffEvent(index);
     648            1 :         const uint64_t scheduleBegin = profileManager.GetCpuTick();
     649            1 :         ScheduleDataBuffAll(!(procRelation || hasF2NF || procAsynMemBuff), index);
     650            2 :         StatisticManager::GetInstance().UpdateScheuleStatistic(profileManager.GetTimeCost(schedDelay),
     651            1 :             profileManager.GetTimeCost(profileManager.GetCpuTick() - scheduleBegin));
     652            1 :         profileManager.TryMarker(eventBegin);
     653              :         // clear event work flag
     654              :         queueEventAtomicFlag.clear();
     655            1 :         return;
     656              :     }
     657              : 
     658            2 :     if (procF2NF) {
     659            1 :         ProcessFullToNotFullEvent(index);
     660            1 :         return;
     661              :     }
     662              : 
     663            1 :     bqs::StatisticManager::GetInstance().EnqueueEventFalseAwakenStat();
     664            1 :     BQS_LOG_DEBUG("Thread[%u] can't work as other thread is working.", threadIndex);
     665              : }
     666              : 
     667            1 : void QueueSchedule::ProcessFullToNotFullEvent(const uint32_t index)
     668              : {
     669            1 :     bqs::StatisticManager::GetInstance().F2nfEventStat();
     670            1 :     (void)QueueManager::GetInstance().EnqueueFullToNotFullEvent(index);
     671            1 : }
     672              : 
     673            1 : void QueueSchedule::DaemonEnqueueEvent(const uint32_t index)
     674              : {
     675            1 :     auto &queueEventAtomicFlag = (index == 0U) ? queueEventAtomicFlag_ : queueEventAtomicFlagExtra_;
     676              :     // if other thread is working do nothing; if not set work flag.
     677            1 :     if (!queueEventAtomicFlag.test_and_set()) {
     678            1 :         StatisticManager::GetInstance().DaemonEventScheduleStat();
     679              : 
     680              :         // handle relation queue
     681            1 :         const bool procRelation = QueueManager::GetInstance().HandleRelationEvent(index);
     682              : 
     683              :         // handle schedule data
     684            1 :         ScheduleDataBuffAll(!procRelation, index);
     685              : 
     686              :         // clear event work flag
     687              :         queueEventAtomicFlag.clear();
     688              :     } else {
     689            0 :         BQS_LOG_WARN("Daemon thread can't work as other thread is working, may event error.");
     690              :     }
     691            1 : }
     692              : 
     693           29 : void QueueSchedule::DynamicSchedule(const uint32_t index) const
     694              : {
     695           29 :     const auto &dynamicCfgKeys = dgw::ScheduleConfig::GetInstance().GetSchedKeys();
     696           29 :     BQS_LOG_DEBUG("dynamicCfgKeys size is %zu", dynamicCfgKeys.size());
     697           29 :     if (dynamicCfgKeys.empty()) {
     698           28 :         return;
     699              :     }
     700            1 :     uint32_t dynamicScheduleCount = 0U;
     701            2 :     for (const auto key: dynamicCfgKeys) {
     702            1 :         if (dgw::ScheduleConfig::GetInstance().IsStopped(key)) {
     703            0 :             BQS_LOG_INFO("key[%u] is stopped, then skip", key);
     704            0 :             continue;
     705              :         }
     706            2 :         while (dynamicScheduleCount++ < 100U) {
     707            2 :             std::vector<dgw::DynamicSchedMgr::ResponseInfo> responses;
     708            2 :             const auto getResponseRet = dgw::DynamicSchedMgr::GetInstance(index).GetResponse(key, responses);
     709            2 :             if ((getResponseRet != dgw::FsmStatus::FSM_SUCCESS) || (responses.size() == 0U)) {
     710            1 :                 BQS_LOG_DEBUG("Can't get response, ret is %d", static_cast<int32_t>(getResponseRet));
     711            1 :                 break;
     712              :             }
     713            1 :             DynamicScheduleByResponse(key, index, responses);
     714            2 :         }
     715              :     }
     716            1 :     BQS_LOG_DEBUG("finish DynamicSchedule, dynamicScheduleCount is %u", dynamicScheduleCount);
     717              : }
     718              : 
     719           28 : void QueueSchedule::ScheduleDataBuffAll(const bool dataEnqueue, const uint32_t index) const
     720              : {
     721           28 :     BQS_LOG_INFO("the [%u]th thread ScheduleDataBuffAll.", index);
     722           28 :     bool hasDequeueFlag = false;
     723           28 :     const auto &orderedSubscribeQueues = (index == 0U) ?
     724           28 :         BindRelation::GetInstance().GetOrderedSubscribeQueueId() :
     725            0 :         BindRelation::GetInstance().GetOrderedSubscribeQueueIdExtra();
     726              :     const auto &srcToDstRelation = (index == 0U) ?
     727           28 :         BindRelation::GetInstance().GetSrcToDstRelation() :
     728           28 :         BindRelation::GetInstance().GetSrcToDstExtraRelation();
     729              : 
     730           28 :     ProfileManager::GetInstance(index).SetSrcQueueNum(static_cast<uint32_t>(orderedSubscribeQueues.size()));
     731           28 :     dgw::InnerMessage msg;
     732           28 :     msg.msgType = dgw::InnerMsgType::INNER_MSG_PUSH;
     733           28 :     BindRelation::GetInstance().ClearAbnormalEntityInfo(index);
     734           32 :     if (dgw::EntityManager::Instance(index).IsExistFullEntity() ||
     735            4 :         dgw::EntityManager::Instance(index).IsExistAsyncMemEntity()) {
     736           47 :         for (const auto &src : orderedSubscribeQueues) {
     737           24 :             if (dgw::ScheduleConfig::GetInstance().IsStopped(src.GetSchedCfgKey())) {
     738            0 :                 BQS_LOG_INFO("Skip schedule src[%s] for it has been stopped.", src.ToString().c_str());
     739            1 :                 continue;
     740              :             }
     741           24 :             const auto iter = srcToDstRelation.find(src);
     742           24 :             if (iter == srcToDstRelation.end()) {
     743            1 :                 BQS_LOG_WARN("Can't find dst queues for queue[%u].", src.GetId());
     744            1 :                 continue;
     745              :             }
     746           46 :             for (auto &dst : iter->second) {
     747              :                 // process full state for dst entity
     748           23 :                 if (ProcessDstEntity(dst, index) == dgw::FsmStatus::FSM_ERROR) {
     749            0 :                     BQS_LOG_ERROR("Skip scheduler for routes maybe has been modified");
     750            0 :                     break;
     751              :                 };
     752              :             }
     753              : 
     754           23 :             const auto &srcEntity = src.GetEntity();
     755           23 :             if (srcEntity->ProcessMessage(msg) == dgw::FsmStatus::FSM_ERROR) {
     756            1 :                 BQS_LOG_ERROR("skip scheduler for routes maybe have been modified");
     757            1 :                 break;
     758              :             }
     759           22 :             hasDequeueFlag |= (srcEntity->GetScheduleCount() > 0UL);
     760              :         }
     761              :     } else {
     762            6 :         for (const auto &src : orderedSubscribeQueues) {
     763            3 :             if (dgw::ScheduleConfig::GetInstance().IsStopped(src.GetSchedCfgKey())) {
     764            0 :                 BQS_LOG_INFO("Skip schedule src[%s] for it has been stopped.", src.ToString().c_str());
     765            0 :                 continue;
     766              :             }
     767            3 :             const auto &srcEntity = src.GetEntity();
     768            3 :             if (srcEntity->ProcessMessage(msg) == dgw::FsmStatus::FSM_ERROR) {
     769            1 :                 BQS_LOG_ERROR("skip scheduler for routes maybe have been modified");
     770            1 :                 break;
     771              :             }
     772            2 :             hasDequeueFlag |= (srcEntity->GetScheduleCount() > 0UL);
     773              :         }
     774              :     }
     775              : 
     776           28 :     DynamicSchedule(index);
     777              : 
     778              :     // supply recv request event
     779           28 :     if (hasDequeueFlag && (!aicpuFeatureDisableRecvRequestEvent_)) {
     780           12 :         (void)dgw::EntityManager::Instance(index).SupplyRecvRequestEvent();
     781              :     }
     782              : 
     783           28 :     if ((!hasDequeueFlag) && dataEnqueue) {
     784           14 :         StatisticManager::GetInstance().AddScheduleEmpty();
     785              :     }
     786           28 :     BindRelation::GetInstance().UpdateRelation(index);
     787           28 : }
     788              : 
     789           23 : dgw::FsmStatus QueueSchedule::ProcessDstEntity(const EntityInfo &entity, const uint32_t index) const
     790              : {
     791           23 :     const auto dstEntity = entity.GetEntity();
     792           23 :     if (dstEntity == nullptr) {
     793            0 :         BQS_LOG_ERROR("Get entity ptr for entity[%s] failed.", entity.ToString().c_str());
     794            0 :         return dgw::FsmStatus::FSM_FAILED;
     795              :     }
     796              :     // process full for queue or tag
     797           23 :     if (entity.GetType() != dgw::EntityType::ENTITY_GROUP) {
     798           22 :         BQS_LOG_DEBUG("Process dst entity, id[%u], type[%s].",
     799              :             dstEntity->GetId(), dstEntity->GetTypeDesc().c_str());
     800           22 :         dgw::InnerMessage msg;
     801           22 :         msg.msgType = dstEntity->GetCurState() == dgw::FsmState::FSM_FULL_STATE ? dgw::InnerMsgType::INNER_MSG_F2NF :
     802              :             dgw::InnerMsgType::INNER_MSG_PUSH;
     803           22 :         return dstEntity->ProcessMessage(msg);
     804              :     }
     805              :     // process full for group
     806            1 :     auto &entitiesInGroup = dgw::EntityManager::Instance(index).GetEntitiesInGroup(entity.GetId());
     807            3 :     for (auto &entityInGroup : entitiesInGroup) {
     808            2 :         BQS_LOG_DEBUG("Process dst entity in group[%u], id[%u], type[%s].",
     809              :             dstEntity->GetId(), entityInGroup->GetId(), entityInGroup->GetTypeDesc().c_str());
     810            2 :         dgw::InnerMessage msg;
     811            2 :         msg.msgType = entityInGroup->GetCurState() == dgw::FsmState::FSM_FULL_STATE ?
     812              :             dgw::InnerMsgType::INNER_MSG_F2NF : dgw::InnerMsgType::INNER_MSG_PUSH;
     813            2 :         (void) entityInGroup->ProcessMessage(msg);
     814              :     }
     815            1 :     return dgw::FsmStatus::FSM_SUCCESS;
     816           23 : }
     817              : 
     818          108 : QueueSchedule::~QueueSchedule()
     819              : {
     820          108 :     running_ = false;
     821          108 :     daemonWait_.notify_all();
     822          270 :     for (auto &worker : workThreads_) {
     823          162 :         if (worker.joinable()) {
     824            0 :             worker.join();
     825              :         }
     826              :     }
     827          108 : }
     828              : 
     829          158 : void QueueSchedule::WaitForStop()
     830              : {
     831          158 :     BQS_LOG_RUN_INFO("WaitForStop begin");
     832          158 :     RouterServer::GetInstance().Destroy();
     833          158 :     StopQueueSchedule();
     834          482 :     for (auto &worker : workThreads_) {
     835          324 :         if (worker.joinable()) {
     836          162 :             worker.join();
     837              :         }
     838              :     }
     839          158 :     BQS_LOG_INFO("WaitForStop end");
     840          158 : }
     841              : 
     842              : /* *
     843              :  * init drv event scheduler.
     844              :  * @return BQS_STATUS_OK: success, other: error
     845              :  */
     846           19 : BqsStatus QueueSchedule::InitDrvSchedModule(const uint32_t deviceId, const uint32_t enqueGroupId,
     847              :                                             const uint32_t f2nfGroupId) const
     848              : {
     849           19 :     BQS_LOG_INFO("Attach device[%u] to drv scheduler", deviceId);
     850              :     (void)f2nfGroupId;
     851           19 :     int32_t ret = halEschedAttachDevice(deviceId);
     852           19 :     if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_PROCESS_REPEAT_ADD)) {
     853            1 :         BQS_LOG_ERROR("Failed to attach device[%u] for eSched, result[%d].", deviceId, ret);
     854            1 :         return BQS_STATUS_DRIVER_ERROR;
     855              :     }
     856              : 
     857           22 :     for (uint32_t idx = 0; idx < initQsParams_.devIdVec.size(); idx++) {
     858            4 :         uint32_t currDeviceId = initQsParams_.devIdVec[idx];
     859            4 :         ret = halEschedAttachDevice(currDeviceId);
     860            4 :         if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_PROCESS_REPEAT_ADD)) {
     861            0 :             BQS_LOG_ERROR("Failed to attach device[%u] for eSched, result[%d].", currDeviceId, ret);
     862            0 :             return BQS_STATUS_DRIVER_ERROR;
     863              :         }
     864              : 
     865            4 :         if (deviceId_ == currDeviceId) {
     866            0 :             continue;
     867              :         }
     868              :         QueueSetInputPara inPutParam;
     869            4 :         (void)halQueueSet(currDeviceId, QUEUE_ENABLE_LOCAL_QUEUE, &inPutParam);
     870              : 
     871            4 :         ret = halQueueInit(currDeviceId);
     872            4 :         if ((ret != DRV_ERROR_NONE) && (ret != DRV_ERROR_REPEATED_INIT)) {
     873            0 :             BQS_LOG_ERROR("host flow halQueueInit error, ret=[%d]", static_cast<int32_t>(ret));
     874            0 :             return BQS_STATUS_DRIVER_ERROR;
     875              :         }
     876              :     }
     877              : 
     878              :     // set pid priority
     879           24 :     const bool setPidPriorityFlag = (bqs::GetRunContext() == bqs::RunContext::HOST) ?
     880            6 :         true : aicpuFeatureSetPidPriority_;
     881           18 :     if (setPidPriorityFlag) {
     882           12 :         (void)halEschedSetPidPriority(deviceId, PRIORITY_LEVEL0);
     883              :     }
     884              : 
     885           18 :     GROUP_TYPE enqueGrpType = GRP_TYPE_BIND_CP_CPU;
     886           18 :     GROUP_TYPE f2nfGrpType = GRP_TYPE_BIND_CP_CPU;
     887           18 :     if (hasAICPU_ && !isZeroSizeAicpuNum_ && (bqs::RunContext::HOST != bqs::GetRunContext())) {
     888            1 :         enqueGrpType = GRP_TYPE_BIND_DP_CPU;
     889            1 :         f2nfGrpType = GRP_TYPE_BIND_DP_CPU;
     890              :     }
     891           18 :     BQS_LOG_INFO("Create enqueGroup[%u] type[%d] on device[%u].", enqueGroupId, enqueGrpType, deviceId);
     892           18 :     ret = halEschedCreateGrp(deviceId, enqueGroupId, enqueGrpType);
     893           18 :     if (ret != DRV_ERROR_NONE) {
     894            1 :         (void)halEschedDettachDevice(deviceId);
     895            1 :         BQS_LOG_ERROR("Failed to create enqueGroup, groupId[%u] result[%d].", enqueGroupId, ret);
     896            1 :         return BQS_STATUS_DRIVER_ERROR;
     897              :     }
     898              : 
     899           17 :     if (!initQsParams_.numaFlag) {
     900            9 :         BQS_LOG_INFO("Create f2nfGroup[%u], type[%d]", f2nfGroupId_, f2nfGrpType);
     901            9 :         ret = halEschedCreateGrp(deviceId_, f2nfGroupId_, f2nfGrpType);
     902            9 :         if (ret != DRV_ERROR_NONE) {
     903            0 :             (void)halEschedDettachDevice(deviceId_);
     904            0 :             BQS_LOG_ERROR("Failed to create f2nfGroup, groupId[%u] result[%d].", f2nfGroupId_, ret);
     905            0 :             return BQS_STATUS_DRIVER_ERROR;
     906              :         }
     907              :     }
     908           17 :     return BQS_STATUS_OK;
     909              : }
     910              : 
     911            1 : void QueueSchedule::ReportAbnormal() const
     912              : {
     913            1 :     BQS_LOG_ERROR("Enqueue thread has missed heartbeat for %u seconds", abnormalInterval_);
     914            1 :     if ((bqs::GetRunContext() != bqs::RunContext::HOST) &&
     915            2 :         (initQsParams_.starter != bqs::QsStartType::START_BY_DEPLOYER) &&
     916            1 :         (initQsParams_.runMode != QueueSchedulerRunMode::MULTI_THREAD)) {
     917            1 :         const int32_t ret = TsdDestroy(deviceId_, TSD_QS, initQsParams_.pid, initQsParams_.vfId);
     918            1 :         if (ret != 0) {
     919            0 :             BQS_LOG_ERROR("dev[%u] send abnormal msg to tsdaemon failed, ret[%d]", deviceId_, ret);
     920              :         }
     921              :     }
     922            1 : }
     923              : }  // namespace bqs
        

Generated by: LCOV version 2.0-1