LCOV - code coverage report
Current view: top level - server - main.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.5 % 179 162
Test Date: 2026-07-28 10:54:05 Functions: 90.0 % 10 9

            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 <cstdint>
      12              : #include <string>
      13              : #include <sstream>
      14              : #include <unistd.h>
      15              : #include <csignal>
      16              : #include <dlfcn.h>
      17              : #include <fstream>
      18              : #include "driver/ascend_hal.h"
      19              : #include "common/bqs_status.h"
      20              : #include "common/bqs_log.h"
      21              : #include "common/bqs_util.h"
      22              : #include "qs_interface_process.h"
      23              : #include "server/bind_cpu_utils.h"
      24              : #include "tsd.h"
      25              : #include "securec.h"
      26              : #include "queue_schedule/qs_client.h"
      27              : #include "bqs_weak_log.h"
      28              : #include "server/qs_args_parser.h"
      29              : #include "queue_schedule_sub_module_interface.h"
      30              : #include "bqs_feature_ctrl.h"
      31              : 
      32              : namespace bqs {
      33              : namespace {
      34              : void *g_aicpuSdlibHandle = nullptr;
      35              : const std::string AICPU_SCHEDULER_SO_NAME = "libaicpu_scheduler.so";
      36              : // mutex for condition variable
      37              : std::mutex g_kMtx;
      38              : // condition variable
      39              : std::condition_variable g_kCv;
      40              : // exit flag
      41              : #ifndef aicpusd_UT
      42              : std::atomic<bool> g_kExitFlag{false};
      43              : #else
      44              : std::atomic<bool> g_kExitFlag{true};
      45              : #endif
      46              : 
      47              : /**
      48              :  * wait for shutdown.
      49              :  * @return  void
      50              :  */
      51            6 : static void WaitShutdown()
      52              : {
      53            6 :     std::unique_lock<std::mutex> lk(bqs::g_kMtx);
      54            6 :     while (!bqs::g_kExitFlag.load()) {
      55            0 :         bqs::g_kCv.wait(lk);
      56              :     }
      57            6 :     BQS_LOG_INFO("Exit WaitShutdown");
      58            6 : }
      59              : 
      60              : /**
      61              :  * handle SIGTERM sig.
      62              :  * @return  void
      63              :  */
      64            0 : static void HandleSignal(const int32_t sig)
      65              : {
      66              :     (void) sig;
      67            0 :     bqs::g_kExitFlag = true;
      68            0 :     bqs::g_kCv.notify_one();
      69            0 : }
      70              : }
      71              : 
      72            8 : void ReportErrorMsg(const int32_t errCode, const uint32_t deviceId, const pid_t hostPid, const uint32_t vfId)
      73              : {
      74            8 :     BQS_LOG_RUN_WARN("ReportErrorMsg errcode is %d.", errCode);
      75            8 :     std::string errStr;
      76            8 :     switch (errCode) {
      77            0 :         case BQS_STATUS_ATTACH_GROUP_FALED: {
      78            0 :             errStr = ERROR_MSG_ATTACH_GROUP_FAILED;
      79            0 :             break;
      80              :         }
      81            8 :         default: {
      82            8 :             errStr = ERROR_MSG_QS_INIT_FAILED;
      83            8 :             break;
      84              :         }
      85              :     }
      86            8 :     BQS_LOG_RUN_INFO("ReportErrorMsg msg is %s.", errStr.c_str());
      87            8 :     (void) TsdReportStartOrStopErrCode(deviceId, TSD_QS, static_cast<uint32_t>(hostPid), vfId, errStr.c_str(),
      88            8 :                                        static_cast<uint32_t>(errStr.size()));
      89            8 : }
      90              : 
      91           20 : void RegAicpuSchedulerModuleCallBack()
      92              : {
      93           20 :     g_aicpuSdlibHandle = dlopen(AICPU_SCHEDULER_SO_NAME.c_str(), RTLD_LAZY);
      94           20 :     if (g_aicpuSdlibHandle == nullptr) {
      95           14 :         BQS_LOG_WARN("cannot open so %s", AICPU_SCHEDULER_SO_NAME.c_str());
      96           14 :         return;
      97              :     }
      98              : 
      99              :     const SubProcEventCallBackFuncInfo startAicpuSdFunc =
     100            6 :         reinterpret_cast<SubProcEventCallBackFuncInfo>(dlsym(g_aicpuSdlibHandle, "StartAicpuSchedulerModule"));
     101            6 :     if (startAicpuSdFunc == nullptr) {
     102            1 :         BQS_LOG_ERROR("cannot find StartAicpuSchedulerModule");
     103            1 :         (void)dlclose(g_aicpuSdlibHandle);
     104            1 :         g_aicpuSdlibHandle = nullptr;
     105            1 :         return;
     106              :     }
     107              : 
     108              :     SubProcEventCallBackInfo startCallBackInfo;
     109            5 :     startCallBackInfo.callBackFunc = startAicpuSdFunc;
     110            5 :     startCallBackInfo.eventType = TSD_EVENT_START_AICPU_SD_MODULE;
     111            5 :     int32_t ret = RegEventMsgCallBackFunc(&startCallBackInfo);
     112            5 :     if (ret != 0) {
     113            1 :         BQS_LOG_ERROR("reg StartAicpuSchedulerModule failed");
     114            1 :         (void)dlclose(g_aicpuSdlibHandle);
     115            1 :         g_aicpuSdlibHandle = nullptr;
     116            1 :         return;
     117              :     }
     118              : 
     119              :     const SubProcEventCallBackFuncInfo stopAicpuSdFunc =
     120            4 :         reinterpret_cast<SubProcEventCallBackFuncInfo>(dlsym(g_aicpuSdlibHandle, "StopAicpuSchedulerModule"));
     121            4 :     if (stopAicpuSdFunc == nullptr) {
     122            1 :         UnRegEventMsgCallBackFunc(TSD_EVENT_START_AICPU_SD_MODULE);
     123            1 :         BQS_LOG_ERROR("cannot find StopAicpuSchedulerModule");
     124            1 :         (void)dlclose(g_aicpuSdlibHandle);
     125            1 :         g_aicpuSdlibHandle = nullptr;
     126            1 :         return;
     127              :     }
     128              : 
     129              :     SubProcEventCallBackInfo stopCallBackInfo;
     130            3 :     stopCallBackInfo.callBackFunc = stopAicpuSdFunc;
     131            3 :     stopCallBackInfo.eventType = TSD_EVENT_STOP_AICPU_SD_MODULE;
     132              : 
     133            3 :     ret = RegEventMsgCallBackFunc(&stopCallBackInfo);
     134            3 :     if (ret != 0) {
     135            1 :         UnRegEventMsgCallBackFunc(TSD_EVENT_START_AICPU_SD_MODULE);
     136            1 :         BQS_LOG_ERROR("reg StopAicpuSchedulerModule failed");
     137            1 :         (void)dlclose(g_aicpuSdlibHandle);
     138            1 :         g_aicpuSdlibHandle = nullptr;
     139            1 :         return;
     140              :     }
     141            2 :     BQS_LOG_RUN_INFO("RegAicpuSchedulerModuleCallBack success");
     142            2 :     return;
     143              : }
     144           12 : void StopAiCpuSubModuleInQs(const uint32_t deviceId, const uint32_t hostPid, const uint32_t vfId)
     145              : {
     146           12 :     if (g_aicpuSdlibHandle == nullptr) {
     147           11 :         BQS_LOG_WARN("cannot open so %s .", AICPU_SCHEDULER_SO_NAME.c_str());
     148           11 :         return;
     149              :     }
     150            1 :     TsdSubEventInfo eventInfo = {};
     151            1 :     eventInfo.deviceId = deviceId;
     152            1 :     eventInfo.hostPid = hostPid;
     153            1 :     eventInfo.vfId = vfId;
     154              :     const SubProcEventCallBackFuncInfo stopAicpuSdFunc =
     155            1 :         reinterpret_cast<SubProcEventCallBackFuncInfo>(dlsym(g_aicpuSdlibHandle, "StopAicpuSchedulerModule"));
     156            1 :     if (stopAicpuSdFunc == nullptr) {
     157            0 :         BQS_LOG_ERROR("cannot find StopAicpuSchedulerModule");
     158            0 :         (void)dlclose(g_aicpuSdlibHandle);
     159            0 :         g_aicpuSdlibHandle = nullptr;
     160            0 :         return;
     161              :     }
     162            1 :     const int32_t ret = stopAicpuSdFunc(&eventInfo);
     163            1 :     if (ret != 0) {
     164            0 :         BQS_LOG_ERROR("StopAicpuSchedulerModule fail");
     165              :     }
     166            1 :     (void)dlclose(g_aicpuSdlibHandle);
     167            1 :     g_aicpuSdlibHandle = nullptr;
     168              : }
     169              : 
     170            8 : void CloseAicpuSdlibHandle()
     171              : {
     172            8 :     if (g_aicpuSdlibHandle != nullptr) {
     173            1 :         (void)dlclose(g_aicpuSdlibHandle);
     174            1 :         g_aicpuSdlibHandle = nullptr;
     175            1 :         return;
     176              :     }
     177              : }
     178              : 
     179           38 : void GetEnv(const char_t * const envName, std::string &envValue)
     180              : {
     181           38 :     const size_t envValueMaxLen = 1024UL * 1024UL;
     182           38 :     const char_t * const envTemp = std::getenv(envName);
     183           38 :     if ((envTemp == nullptr) || (strnlen(envTemp, envValueMaxLen) >= envValueMaxLen)) {
     184           20 :         BQS_LOG_WARN("Get env[%s] failed.", envName);
     185           20 :         return;
     186              :     }
     187           18 :     envValue = envTemp;
     188              : }
     189              : 
     190           19 : void SetLogLevelWithEnv(bqs::ArgsParser &startParams)
     191              : {
     192           19 :     std::string envLogLevel;
     193           19 :     std::string envEventLevel;
     194           19 :     GetEnv("ASCEND_GLOBAL_LOG_LEVEL", envLogLevel);
     195           19 :     GetEnv("ASCEND_GLOBAL_EVENT_ENABLE", envEventLevel);
     196           19 :     BQS_LOG_RUN_INFO("Set log with env, envLogLevel[%s], envEventLevel[%s]",
     197              :                      envLogLevel.c_str(), envEventLevel.c_str());
     198              :     int32_t logLevel;
     199              :     int32_t eventLevel;
     200           19 :     if (!TransStrToInt(envLogLevel, logLevel)) {
     201            1 :         logLevel = ERROR_LOG;
     202              :     }
     203           19 :     if (!TransStrToInt(envEventLevel, eventLevel)) {
     204           19 :         eventLevel = EVENT_LOG;
     205              :     }
     206           19 :     startParams.SetLogLevel(logLevel, eventLevel);
     207           19 : }
     208              : 
     209           20 : void InitQsInitParams(bqs::InitQsParams &initQsParams, const uint32_t deviceId,
     210              :                       const uint32_t hostPid, const uint32_t vfId,
     211              :                       const std::vector<uint32_t> resVec, const bqs::ArgsParser &startParams)
     212              : {
     213           20 :     initQsParams.deviceId = deviceId;
     214           20 :     initQsParams.enqueGroupId = static_cast<uint32_t>(bqs::EventGroupId::ENQUEUE_GROUP_ID);
     215           20 :     initQsParams.f2nfGroupId = static_cast<uint32_t>(bqs::EventGroupId::F2NF_GROUP_ID);
     216           20 :     initQsParams.reschedInterval = static_cast<uint32_t>(startParams.GetReschedInterval());
     217           20 :     initQsParams.runMode = startParams.GetDeployMode();
     218           20 :     initQsParams.pid = hostPid;
     219           20 :     initQsParams.vfId = vfId;
     220           20 :     initQsParams.pidSign = startParams.GetPidSign();
     221           20 :     initQsParams.qsInitGrpName = startParams.GetGroupName();
     222           20 :     initQsParams.schedPolicy = startParams.GetSchedPolicy();
     223           20 :     initQsParams.starter = startParams.GetStarter();
     224           20 :     initQsParams.profCfgData = startParams.GetProfCfgData();
     225           20 :     initQsParams.abnormalInterVal = static_cast<uint32_t>(startParams.GetAbnormalInterval());
     226           20 :     initQsParams.profFlag = startParams.GetProfFlag();
     227           20 :     initQsParams.enqueGroupIdExtra = bqs::EventGroupId::ENQUEUE_GROUP_ID_EXTRA;
     228           20 :     initQsParams.f2nfGroupIdExtra = bqs::EventGroupId::F2NF_GROUP_ID_EXTRA;
     229           20 :     uint32_t extraDevceId = 0U;
     230           20 :     if (resVec.size() > 1U) {
     231            5 :         extraDevceId = (resVec[0U] == deviceId) ? resVec[1U] : resVec[0U];
     232              :     }
     233           20 :     initQsParams.deviceIdExtra = extraDevceId;
     234           20 :     initQsParams.numaFlag = (resVec.size() > 1U);
     235           20 :     initQsParams.devIdVec = startParams.GetDevIdVec();
     236           20 :     initQsParams.needAttachGroup = true;
     237           20 : }
     238              : }
     239              : 
     240              : /**
     241              :  * main of queue schedule
     242              :  * @param  argc argv length
     243              :  * @param  argv arg values
     244              :  * @return 0:success, other:failed
     245              :  */
     246              : #ifndef aicpusd_UT
     247              : int32_t main(int32_t argc, char_t *argv[])
     248              : #else
     249           32 : int32_t QueueScheduleMain(int32_t argc, char_t *argv[])
     250              : #endif
     251              : {
     252              :     try {
     253           32 :         BQS_LOG_RUN_INFO("QueueSchedule begin");
     254           32 :         bqs::ArgsParser startParams;
     255           32 :         if (!startParams.ParseArgs(argc, argv)) {
     256           12 :             BQS_LOG_ERROR("Parse args failed");
     257           12 :             return -1;
     258              :         }
     259              : 
     260           20 :         BQS_LOG_RUN_INFO("Start parameter. %s", startParams.GetParaParsedStr().c_str());
     261              : 
     262           20 :         if (!startParams.GetWithLogLevel()) {
     263           19 :             bqs::SetLogLevelWithEnv(startParams);
     264              :         }
     265              : 
     266           20 :         const uint32_t vfId = startParams.GetVfId();
     267           20 :         const uint32_t hostPid = startParams.GetHostPid();
     268           20 :         uint32_t deviceId = startParams.GetDeviceId();
     269           20 :         const std::vector<uint32_t> resVec = startParams.GetResvec();
     270           20 :         BQS_LOG_RUN_INFO("resVec size is %zu", resVec.size());
     271           20 :         if (resVec.size() >= 1) {
     272            5 :             deviceId = resVec[0];
     273              :         }
     274           20 :         if ((bqs::GetRunContext() == bqs::RunContext::DEVICE) && (!bqs::BindCpuUtils::AddToCgroup(deviceId, vfId))) {
     275            0 :             return -1;
     276              :         }
     277              : 
     278           20 :         bqs::RegAicpuSchedulerModuleCallBack();
     279              : 
     280           20 :         auto& qsInterface = bqs::QueueScheduleInterface::GetInstance();
     281              : 
     282           20 :         bqs::InitQsParams initQsParams = {};
     283           20 :         bqs::InitQsInitParams(initQsParams, deviceId, hostPid, vfId, resVec, startParams);
     284           20 :         const auto bsqStatus = qsInterface.InitQueueScheduler(initQsParams);
     285           20 :         if (bsqStatus != bqs::BQS_STATUS_OK) {
     286            8 :             BQS_LOG_ERROR("QueueSchedule start failed, ret=%d .", bsqStatus);
     287            8 :             bqs::ReportErrorMsg(bsqStatus, deviceId, hostPid, vfId);
     288            8 :             bqs::CloseAicpuSdlibHandle();
     289            8 :             return -1;
     290              :         }
     291           12 :         BQS_LOG_RUN_INFO("QueueSchedule start success");
     292              :         // wait for shutdown
     293           12 :         int32_t waitRet = 0;
     294           21 :         if ((startParams.GetStarter() == bqs::QsStartType::START_BY_TSD) &&
     295            9 :             (bqs::GetRunContext() != bqs::RunContext::HOST)) {
     296            6 :             waitRet = TsdWaitForShutdown(deviceId, TSD_QS, hostPid, vfId);
     297              :         } else {
     298              :             // register a signal handler
     299            6 :             (void) std::signal(SIGTERM, static_cast<sighandler_t>(&bqs::HandleSignal));
     300            6 :             bqs::WaitShutdown();
     301              :         }
     302           12 :         int32_t ret = 0;
     303           12 :         if (waitRet != 0) {
     304            1 :             BQS_LOG_ERROR("Tsd wait for shut down return not ok, error code[%d].", waitRet);
     305            1 :             ret = -1;
     306              :         } else {
     307           11 :             BQS_LOG_INFO("Tsd wait for shut down success");
     308           11 :             ret = 0;
     309              :         }
     310              : 
     311           12 :         bqs::StopAiCpuSubModuleInQs(deviceId, hostPid, vfId);
     312           12 :         qsInterface.WaitForStop();
     313           12 :         (void)qsInterface.Destroy();
     314           12 :         BQS_LOG_RUN_INFO("QueueSchedule exit");
     315           12 :         return ret;
     316           32 :     } catch(...) {
     317            0 :         BQS_LOG_ERROR("QueueSchedule run exception.");
     318            0 :         return -1;
     319            0 :     }
     320              : }
        

Generated by: LCOV version 2.0-1