LCOV - code coverage report
Current view: top level - aicpu_schedule/datadump - datadump_worker.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 81.4 % 183 149
Test Date: 2026-08-12 11:05:02 Functions: 92.9 % 14 13

            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 "aicpusd_worker.h"
      12              : 
      13              : #include <csignal>
      14              : #include <cstring>
      15              : #include <cerrno>
      16              : #include <sys/wait.h>
      17              : 
      18              : #include "aicpusd_status.h"
      19              : #include "aicpusd_util.h"
      20              : #include "aicpusd_drv_manager.h"
      21              : #include "aicpusd_monitor.h"
      22              : #include "aicpusd_event_manager.h"
      23              : #include "aicpusd_context.h"
      24              : #include "aicpu_context.h"
      25              : #include "aicpusd_proc_mgr_sys_operator_agent.h"
      26              : #include "aicpusd_hal_interface_ref.h"
      27              : #include "aicpusd_so_manager.h"
      28              : #include "aicpu_pulse.h"
      29              : #include "aicpusd_feature_ctrl.h"
      30              : 
      31              : namespace {
      32              : constexpr uint32_t CP_EVENT_MASK =
      33              :     static_cast<uint32_t>(static_cast<uint32_t>(1U) << static_cast<uint32_t>(EVENT_TS_CTRL_MSG));
      34              : }
      35              : 
      36              : namespace AicpuSchedule {
      37           22 : ThreadPool& ThreadPool::Instance()
      38              : {
      39           22 :     static ThreadPool threadPoolInstance;
      40           22 :     return threadPoolInstance;
      41              : }
      42              : 
      43            8 : ThreadPool::ThreadPool() : semInitedNum_(0UL) { aicpusd_run_info("ThreadPool"); }
      44              : 
      45            8 : ThreadPool::~ThreadPool() { Clear(); }
      46              : 
      47           14 : void ThreadPool::Clear()
      48              : {
      49           14 :     AicpuSchedule::AicpuEventManager::GetInstance().SetRunningFlag(false);
      50           14 :     WaitForStop();
      51           20 :     for (auto& sem : sems_) {
      52            6 :         (void)sem_destroy(&sem);
      53              :     }
      54           14 :     semInitedNum_ = 0UL;
      55           14 :     threadStatusList_.clear();
      56           14 :     threadIdLists_.clear();
      57           14 : }
      58              : 
      59            6 : int32_t ThreadPool::CreateWorker(const AicpuSchedMode schedMode)
      60              : {
      61            6 :     Clear();
      62            6 :     AicpuSchedule::AicpuEventManager::GetInstance().SetRunningFlag(true);
      63            6 :     schedMode_ = schedMode;
      64            6 :     const size_t aicpuNum = AicpuDrvManager::GetInstance().GetAicpuNum();
      65            6 :     const std::vector<uint32_t> deviceVec = AicpuDrvManager::GetInstance().GetDeviceList();
      66            6 :     if (aicpuNum == 0UL) {
      67            1 :         aicpusd_run_info("aicpu total num[0], need not create aicpu worker");
      68              :     } else {
      69              :         try {
      70            5 :             sems_ = std::move(std::vector<sem_t>(static_cast<size_t>(aicpuNum)));
      71            0 :         } catch (std::exception& threadException) {
      72            0 :             aicpusd_err("create sems failed, %s", threadException.what());
      73            0 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
      74            0 :         }
      75            9 :         for (size_t i = 0UL; i < aicpuNum; ++i) {
      76            5 :             const int32_t semInitRet = sem_init(&(sems_[i]), 0, 0U);
      77            5 :             if (semInitRet == -1) {
      78            1 :                 aicpusd_err("sem[%zu] init failed, %s", i, strerror(errno));
      79            1 :                 return AICPU_SCHEDULE_ERROR_INIT_FAILED;
      80              :             }
      81            4 :             semInitedNum_ = i + 1UL;
      82              :         }
      83              :         try {
      84              :             threadStatusList_ =
      85            4 :                 std::move(std::vector<ThreadStatus>(static_cast<size_t>(aicpuNum), ThreadStatus::THREAD_INIT));
      86            0 :         } catch (std::exception& threadException) {
      87            0 :             aicpusd_err("create ThreadStatus failed, %s", threadException.what());
      88            0 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
      89            0 :         }
      90            4 :         int32_t ret = AICPU_SCHEDULE_OK;
      91            4 :         const sighandler_t oldHandler = signal(SIGCHLD, SIG_DFL);
      92            4 :         aicpusd_info("set SIGCHLD to %d, old sighandler[%d]", SIG_DFL, oldHandler);
      93            4 :         const size_t aicpuNumPerDev = AicpuDrvManager::GetInstance().GetAicpuNumPerDevice();
      94            7 :         for (size_t i = 0UL; i < aicpuNum; ++i) {
      95              :             // aicpuNumPerDev is not 0
      96            4 :             const size_t deviceVecInx = i / aicpuNumPerDev;
      97            4 :             ret = CreateOneWorker(i, deviceVec[deviceVecInx]);
      98            4 :             if (ret != AICPU_SCHEDULE_OK) {
      99            1 :                 (void)signal(SIGCHLD, oldHandler);
     100            1 :                 return ret;
     101              :             }
     102              :         }
     103              : 
     104            3 :         for (size_t i = 0UL; i < aicpuNum; i++) {
     105            3 :             const int32_t semWaitRet = sem_wait(&(sems_[i]));
     106            3 :             if (semWaitRet == -1) {
     107            1 :                 (void)signal(SIGCHLD, oldHandler);
     108            1 :                 aicpusd_err("sem[%zu] wait failed, %s", i, strerror(errno));
     109            1 :                 return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     110              :             }
     111            2 :             if (threadStatusList_[i] != ThreadStatus::THREAD_RUNNING) {
     112            2 :                 (void)signal(SIGCHLD, oldHandler);
     113            2 :                 aicpusd_err("create thread[%zu] failed", i);
     114            2 :                 return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     115              :             }
     116              :         }
     117            0 :         aicpusd_info("set SIGCHLD to old sighandler[%d]", oldHandler);
     118            0 :         (void)signal(SIGCHLD, oldHandler);
     119              :     }
     120              : 
     121            1 :     return AICPU_SCHEDULE_OK;
     122            6 : }
     123              : 
     124            2 : int32_t ThreadPool::CreateOneWorker(const size_t threadIndex, const uint32_t deviceId)
     125              : {
     126              :     try {
     127            2 :         aicpusd_info("CreateOneWorker device[%u]:thread[%zu] started.", deviceId, threadIndex);
     128            2 :         std::thread th(&ThreadPool::Work, threadIndex, deviceId, schedMode_);
     129            2 :         pthread_setname_np(th.native_handle(), "aicpu_dump");
     130            2 :         workers_.emplace_back(std::move(th));
     131            2 :     } catch (std::exception& threadException) {
     132            0 :         aicpusd_err("create aicpu worker[%zu] failed, %s", threadIndex, threadException.what());
     133            0 :         return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     134            0 :     }
     135              : 
     136            2 :     return AICPU_SCHEDULE_OK;
     137              : }
     138              : 
     139           14 : void ThreadPool::WaitForStop()
     140              : {
     141           14 :     aicpusd_run_info("WaitForStop begin.");
     142           18 :     for (auto& worker : workers_) {
     143            4 :         if (worker.joinable()) {
     144            2 :             worker.join();
     145              :         }
     146              :     }
     147           14 :     aicpusd_run_info("WaitForStop end.");
     148           14 : }
     149              : 
     150            8 : void ThreadPool::Work(const size_t threadIndex, const uint32_t deviceId, const AicpuSchedMode schedMode)
     151              : {
     152              :     (void)schedMode;
     153            8 :     aicpusd_info("Aicpu device[%u]:thread[%zu] started.", deviceId, threadIndex);
     154              :     aicpu::aicpuContext_t context;
     155            8 :     context.tsId = 0U;
     156            8 :     context.hostPid = AicpuDrvManager::GetInstance().GetHostPid();
     157            8 :     context.vfId = AicpuDrvManager::GetInstance().GetVfId();
     158            8 :     context.deviceId = deviceId;
     159            8 :     if (aicpu::aicpuSetContext(&context) != aicpu::AICPU_ERROR_NONE) {
     160            1 :         aicpusd_err("Set aicpu context failed, deviceId[%u], thread[%zu].", deviceId, threadIndex);
     161            1 :         AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     162            5 :         return;
     163              :     }
     164            7 :     aicpusd_info(
     165              :         "halEschedSubscribeEvent success, deviceId[%u], groupId[%u], threadIndex[%zu] eventBitmap[%llu].", deviceId,
     166              :         CP_DEFAULT_GROUP_ID, threadIndex, CP_EVENT_MASK);
     167            7 :     DeployContext deployCtx = DeployContext::DEVICE;
     168            7 :     const StatusCode ctxRet = GetAicpuDeployContext(deployCtx);
     169            7 :     if (ctxRet != AICPU_SCHEDULE_OK) {
     170            1 :         aicpusd_err("Get current deploy ctx failed.");
     171            1 :         return;
     172              :     }
     173              : 
     174            6 :     if (deployCtx == DeployContext::DEVICE) {
     175            6 :         if (AicpuSchedule::ThreadPool::Instance().SetAffinity(threadIndex, deviceId) != AICPU_SCHEDULE_OK) {
     176            1 :             AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     177            1 :             return;
     178              :         }
     179              :     } else {
     180            0 :         AicpuSchedule::ThreadPool::Instance().SetThreadStatus(threadIndex, ThreadStatus::THREAD_RUNNING);
     181              :     }
     182              :     const int32_t ret =
     183            5 :         halEschedSubscribeEvent(deviceId, CP_DEFAULT_GROUP_ID, static_cast<uint32_t>(threadIndex), CP_EVENT_MASK);
     184            5 :     if (ret != DRV_ERROR_NONE) {
     185            2 :         aicpusd_err(
     186              :             "halEschedSubscribeEvent failed, deviceId[%u], groupId[%u], threadIndex[%zu] "
     187              :             "eventBitmap[%llu].",
     188              :             deviceId, CP_DEFAULT_GROUP_ID, threadIndex, CP_EVENT_MASK);
     189            2 :         AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     190            2 :         return;
     191              :     }
     192              : 
     193            3 :     AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     194              : 
     195            3 :     AicpuSchedule::AicpuEventManager::GetInstance().LoopProcess(static_cast<uint32_t>(threadIndex));
     196            3 :     aicpusd_info("Aicpu device[%u]:thread[%u] stopped.", deviceId, threadIndex);
     197              : }
     198              : 
     199            7 : int32_t ThreadPool::WriteTidForAffinity(const size_t threadIndex)
     200              : {
     201            7 :     if (threadIndex >= threadStatusList_.size()) {
     202            1 :         aicpusd_err("threadIndex[%zu], out of rank[0, %zu]", threadIndex, threadStatusList_.size());
     203            1 :         return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     204              :     }
     205              : 
     206           12 :     std::string command = "cd /var/ && sudo ./add_aicpu_tid_to_tasks.sh";
     207            6 :     std::string pathStr = "/var/add_aicpu_tid_to_tasks.sh";
     208            6 :     if (access(pathStr.c_str(), F_OK) != 0) {
     209            5 :         aicpusd_info("Not find add_aicpu_tid_to_tasks.sh.");
     210            5 :         return AICPU_SCHEDULE_OK;
     211              :     }
     212            1 :     command = command + " " + std::to_string(GetTid());
     213              : 
     214              :     // 使用system命令会对父进程进行拷贝,浪费了系统资源。在esl等环境中还会存在由于资源较少无法fork导致system卡住的问题.
     215              :     // 使用vfork替换system命令,由于与父进程共享资源,因此可解决资源浪费/卡住的问题.
     216            1 :     const int32_t ret = AicpuUtil::ExecuteCmd(command);
     217            1 :     if (ret != 0) {
     218            1 :         threadStatusList_[threadIndex] = ThreadStatus::THREAD_EXIT;
     219            1 :         aicpusd_err(
     220              :             "write tid[%llu] to /sys/fs/cgroup/cpuset/AICPU/tasks failed, ret[%d], strerror[%s]", GetTid(), ret,
     221              :             strerror(errno));
     222            1 :         return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     223              :     }
     224              : 
     225            0 :     return AICPU_SCHEDULE_OK;
     226            6 : }
     227              : 
     228            6 : int32_t ThreadPool::AddPidToTask(const size_t threadIndex)
     229              : {
     230            6 :     if (FeatureCtrl::IsBindPidByHal()) {
     231            2 :         if (&halBindCgroup != nullptr) {
     232            2 :             aicpusd_info("Bind pid by hal index:%zu.", threadIndex);
     233            2 :             const drvError_t drvRet = halBindCgroup(BIND_AICPU_CGROUP);
     234            2 :             if (drvRet != DRV_ERROR_NONE) {
     235            1 :                 aicpusd_err("halBindCgroup failed, ret[%d]", drvRet);
     236            1 :                 return AICPU_SCHEDULE_ERROR_FROM_DRV;
     237              :             }
     238            1 :             aicpusd_info("halBindCgroup success");
     239              :         }
     240              :     } else {
     241            4 :         aicpusd_run_info("AddPidToTask by WriteTidForAffinity");
     242            4 :         auto ret = WriteTidForAffinity(threadIndex);
     243            4 :         if (ret != static_cast<int32_t>(AICPU_SCHEDULE_OK)) {
     244            0 :             aicpusd_err("WriteTidForAffinity failed, ret[%d]", ret);
     245            0 :             return static_cast<int32_t>(AICPU_SCHEDULE_ERROR_INIT_FAILED);
     246              :         }
     247            4 :         aicpusd_info("WriteTidForAffinity success");
     248              :     }
     249            5 :     return AICPU_SCHEDULE_OK;
     250              : }
     251              : 
     252            4 : int32_t ThreadPool::SetAffinityBySelf(const size_t threadIndex, const uint32_t deviceId)
     253              : {
     254            4 :     if (AddPidToTask(threadIndex) != AICPU_SCHEDULE_OK) {
     255            0 :         aicpusd_err("AddPidToTask failed");
     256            0 :         return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     257              :     }
     258              :     cpu_set_t mask;
     259            4 :     CPU_ZERO(&mask);
     260            4 :     if (AicpuDrvManager::GetInstance().GetAicpuNumPerDevice() == 0) {
     261            0 :         return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     262              :     }
     263              :     const uint32_t aicpuLogIndex =
     264            4 :         static_cast<uint32_t>(threadIndex) % AicpuDrvManager::GetInstance().GetAicpuNumPerDevice();
     265              : 
     266            4 :     uint32_t physIndex = 0;
     267            4 :     uint32_t devNum = 0U;
     268            4 :     if ((FeatureCtrl::IsVfModeCheckedByDeviceId(deviceId)) && (&halGetVdevNum != nullptr)) {
     269            0 :         int32_t result = halGetVdevNum(&devNum);
     270            0 :         if (result != 0) {
     271            0 :             aicpusd_err("halGetVdevNum, failed result[%d]", result);
     272            0 :             return AICPU_SCHEDULE_ERROR_FROM_DRV;
     273              :         }
     274              :     }
     275            4 :     if (devNum > 0U) {
     276            0 :         physIndex = AicpuDrvManager::GetInstance().GetAicpuPhysIndexInVfMode(aicpuLogIndex, deviceId);
     277              :     } else {
     278            4 :         physIndex = AicpuDrvManager::GetInstance().GetAicpuPhysIndex(aicpuLogIndex, deviceId);
     279              :     }
     280            4 :     aicpusd_run_info("[hw]SetAffinityBySelf, physIndex[%u], devNum[%u]", physIndex, devNum);
     281            4 :     if (physIndex == INVALID_AICPU_ID) {
     282            0 :         threadStatusList_[threadIndex] = ThreadStatus::THREAD_RUNNING;
     283            0 :         return static_cast<int32_t>(AICPU_SCHEDULE_OK);
     284              :     }
     285              :     // cannot overflow, aicpu num < 65535, max [64=4*16]
     286            4 :     CPU_SET(static_cast<int32_t>(physIndex), &mask);
     287            4 :     const int32_t ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mask);
     288            4 :     if (ret != 0) {
     289            0 :         threadStatusList_[threadIndex] = ThreadStatus::THREAD_EXIT;
     290            0 :         aicpusd_err(
     291              :             "set affinity failed ret[%d], aicpu logical index[%zu], aicpu physical index[%u], "
     292              :             "device id[%u]",
     293              :             ret, threadIndex, physIndex, deviceId);
     294            0 :         return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     295              :     }
     296            4 :     threadStatusList_[threadIndex] = ThreadStatus::THREAD_RUNNING;
     297            4 :     aicpusd_info(
     298              :         "set affinity success, aicpu logical index[%zu], aicpu physical index[%u], device id[%u]", threadIndex,
     299              :         physIndex, deviceId);
     300            4 :     return AICPU_SCHEDULE_OK;
     301              : }
     302              : 
     303            4 : int32_t ThreadPool::SetAffinity(const size_t threadIndex, const uint32_t deviceId)
     304              : {
     305            4 :     int32_t res = static_cast<int32_t>(AICPU_SCHEDULE_OK);
     306            8 :     if (AicpuUtil::IsEnvValEqual(ENV_NAME_PROCMGR_AICPU_CPUSET, "1")) {
     307            0 :         aicpusd_err("aicpu bind tid by pm, index[%zu], deviceId[%u].", threadIndex, deviceId);
     308              :     } else {
     309            4 :         res = SetAffinityBySelf(threadIndex, deviceId);
     310            4 :         aicpusd_run_info("aicpu bind tid by self, index[%zu], deviceId[%u], res[%d].", threadIndex, deviceId, res);
     311              :     }
     312            4 :     return res;
     313              : }
     314              : 
     315            0 : void ThreadPool::SetThreadStatus(const size_t threadIndex, const ThreadStatus threadStat)
     316              : {
     317            0 :     threadStatusList_[threadIndex] = threadStat;
     318            0 : }
     319              : 
     320            3 : void ThreadPool::PostSem(const size_t threadIndex) { (void)sem_post(&(sems_[threadIndex])); }
     321              : } // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1