LCOV - code coverage report
Current view: top level - aicpu_schedule/core - aicpusd_worker.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.3 % 274 261
Test Date: 2026-07-28 10:54:05 Functions: 100.0 % 21 21

            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              : #include <algorithm>
      18              : 
      19              : #include "tsd.h"
      20              : #include "aicpusd_status.h"
      21              : #include "aicpusd_util.h"
      22              : #include "aicpusd_drv_manager.h"
      23              : #include "aicpusd_monitor.h"
      24              : #include "aicpusd_event_manager.h"
      25              : #include "aicpusd_context.h"
      26              : #include "aicpu_context.h"
      27              : #include "aicpusd_proc_mgr_sys_operator_agent.h"
      28              : #include "aicpusd_hal_interface_ref.h"
      29              : #include "aicpusd_so_manager.h"
      30              : #include "aicpu_pulse.h"
      31              : #include "aicpusd_feature_ctrl.h"
      32              : #include "aicpusd_message_queue.h"
      33              : 
      34              : namespace {
      35              :     // user event id starts from EVENT_USR_START(48) to EVENT_USR_END(63), we should make sure that eventIds in
      36              :     // one process should not conflict, considering the first 3 user_event_id has been used by qs, so here we start by
      37              :     // offset 8
      38              :     constexpr uint64_t EVENT_PROXY_MSG = static_cast<uint64_t>(EVENT_ID::EVENT_USR_START) + 8U;
      39              : 
      40              :     constexpr uint64_t CP_EVENT_MASK =
      41              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_RANDOM_KERNEL)) |
      42              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_DVPP_MSG)) |
      43              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_FR_MSG)) |
      44              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_TS_HWTS_KERNEL)) |
      45              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_TS_HWTS_KERNEL)) |
      46              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_AICPU_MSG)) |
      47              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_TS_CTRL_MSG)) |
      48              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_QUEUE_EMPTY_TO_NOT_EMPTY)) |
      49              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_QUEUE_FULL_TO_NOT_FULL)) |
      50              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_TDT_ENQUEUE)) |
      51              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_ACPU_MSG_TYPE1)) |
      52              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_DVPP_MPI_MSG)) |
      53              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_SPLIT_KERNEL)) |
      54              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_CDQ_MSG)) |
      55              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_QUEUE_ENQUEUE)) |
      56              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_QS_MSG)) |
      57              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_DRV_MSG)) |
      58              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << static_cast<uint64_t>(EVENT_FFTS_PLUS_MSG)) |
      59              :         static_cast<uint64_t>(static_cast<uint64_t>(1U) << EVENT_PROXY_MSG);
      60              :     constexpr const uint32_t SLEEP_USECS = 50000U;
      61              :     // When there is no AICPU core, the AICPU schedule starts this number of work threads
      62              :     // and binds them to the largest CTRLCPU cores.
      63              :     constexpr size_t NO_AICPU_WORKER_NUM = 2UL;
      64              : }
      65              : 
      66              : namespace AicpuSchedule {
      67          101 :     ThreadPool &ThreadPool::Instance()
      68              :     {
      69          101 :         static ThreadPool threadPoolInstance;
      70          101 :         return threadPoolInstance;
      71              :     }
      72              : 
      73           36 :     ThreadPool::ThreadPool() : semInitedNum_(0UL)
      74              :     {
      75           36 :         aicpusd_run_info("ThreadPool");
      76           36 :     }
      77              : 
      78           36 :     ThreadPool::~ThreadPool()
      79              :     {
      80           36 :         ClearPulseNotifyFunc();
      81           36 :         Clear();
      82           36 :     }
      83              : 
      84           48 :     void ThreadPool::Clear()
      85              :     {
      86           48 :         AicpuSchedule::AicpuEventManager::GetInstance().SetRunningFlag(false);
      87           48 :         WaitForStop();
      88           71 :         for (auto &sem : sems_) {
      89           23 :             (void)sem_destroy(&sem);
      90              :         }
      91           48 :         semInitedNum_ = 0UL;
      92           48 :         threadStatusList_.clear();
      93           48 :         threadIdLists_.clear();
      94           48 :     }
      95              : 
      96           38 :     size_t ThreadPool::GetWorkerNum()
      97              :     {
      98           38 :         const size_t aicpuNum = static_cast<size_t>(AicpuDrvManager::GetInstance().GetAicpuNum());
      99              :         // When there is no AICPU core, the AICPU schedule still starts NO_AICPU_WORKER_NUM work threads.
     100           38 :         return (aicpuNum == 0UL) ? NO_AICPU_WORKER_NUM : aicpuNum;
     101              :     }
     102              : 
     103           12 :     int32_t ThreadPool::CreateWorker(const AicpuSchedMode schedMode)
     104              :     {
     105           12 :         Clear();
     106           12 :         AicpuSchedule::AicpuEventManager::GetInstance().SetRunningFlag(true);
     107           12 :         schedMode_ = schedMode;
     108           12 :         size_t aicpuNum = GetWorkerNum();
     109           12 :         const std::vector<uint32_t> deviceVec = AicpuDrvManager::GetInstance().GetDeviceList();
     110           12 :         if (AicpuDrvManager::GetInstance().GetAicpuNum() == 0UL) {
     111            2 :             aicpusd_run_info("aicpu total num=[0], create [%zu] aicpu workers", aicpuNum);
     112            2 :             hasAicpu_ = false;
     113              :         }
     114           12 :         sems_ = std::vector<sem_t>(static_cast<size_t>(aicpuNum));
     115           34 :         for (size_t i = 0UL; i < aicpuNum; ++i) {
     116           23 :             const int32_t semInitRet = sem_init(&(sems_[i]), 0, 0U);
     117           23 :             if (semInitRet == -1) {
     118            1 :                 aicpusd_err("sem[%zu] init failed, %s", i, strerror(errno));
     119            1 :                 return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     120              :             }
     121           22 :             semInitedNum_ = i + 1UL;
     122              :         }
     123           11 :         threadStatusList_ = std::vector<ThreadStatus>(static_cast<size_t>(aicpuNum), ThreadStatus::THREAD_INIT);
     124           11 :         threadIdLists_ = std::vector<pid_t>(static_cast<size_t>(aicpuNum), 0);
     125              : 
     126           11 :         sighandler_t const oldHandler = signal(SIGCHLD, SIG_DFL);
     127           11 :         aicpusd_info("set SIGCHLD to %d, old sighandler[%d], errno[%d]", SIG_DFL, oldHandler, errno);
     128              : 
     129              :         // When there is no AICPU core, all work threads run on the same device (deviceVec[0]),
     130              :         // so use aicpuNum as the per-device count to keep deviceVecInx at 0 for every worker.
     131           11 :         const size_t aicpuNumPerDev = hasAicpu_ ? AicpuDrvManager::GetInstance().GetAicpuNumPerDevice() : aicpuNum;
     132           11 :         if (aicpuNumPerDev == 0) {
     133            1 :             aicpusd_err("aicpu Number error, %lu", aicpuNumPerDev);
     134            1 :             (void)signal(SIGCHLD, oldHandler);
     135            1 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     136              :         }
     137              : 
     138           10 :         int32_t ret = AICPU_SCHEDULE_OK;
     139           30 :         for (size_t i = 0UL; i < aicpuNum; ++i) {
     140              :             // aicpuNumPerDev is not 0
     141           21 :             const size_t deviceVecInx = i / aicpuNumPerDev;
     142           21 :             ret = CreateOneWorker(i, deviceVec[deviceVecInx]);
     143           21 :             if (ret != AICPU_SCHEDULE_OK) {
     144            1 :                 (void)signal(SIGCHLD, oldHandler);
     145            1 :                 return ret;
     146              :             }
     147              :         }
     148              : 
     149           21 :         for (size_t i = 0UL; i < aicpuNum; i++) {
     150           18 :             const int32_t semWaitRet = sem_wait(&(sems_[i]));
     151           18 :             if (semWaitRet == -1) {
     152            1 :                 (void)signal(SIGCHLD, oldHandler);
     153            1 :                 aicpusd_err("sem[%zu] wait failed, %s", i, strerror(errno));
     154            1 :                 return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     155              :             }
     156           17 :             if (threadStatusList_[i] != ThreadStatus::THREAD_RUNNING) {
     157            5 :                 (void)signal(SIGCHLD, oldHandler);
     158            5 :                 aicpusd_err("create thread[%zu] failed", i);
     159            5 :                 return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     160              :             }
     161              :         }
     162            3 :         aicpusd_info("set SIGCHLD to old sighandler[%d]", oldHandler);
     163            3 :         (void)signal(SIGCHLD, oldHandler);
     164              : 
     165            3 :         ret = AicpuSchedule::AicpuMonitor::GetInstance().Run();
     166            3 :         if (ret != AICPU_SCHEDULE_OK) {
     167            0 :             aicpusd_err("aicpu monitor run failed, ret[%d]", ret);
     168            0 :             return ret;
     169              :         }
     170              : 
     171            3 :         return AICPU_SCHEDULE_OK;
     172           12 :     }
     173              : 
     174           13 :     int32_t ThreadPool::CreateOneWorker(const size_t threadIndex,
     175              :                                         const uint32_t deviceId)
     176              :     {
     177              :         try {
     178           13 :             aicpusd_info("CreateOneWorker device[%u]:thread[%zu] started.", deviceId, threadIndex);
     179           13 :             std::thread th(&ThreadPool::Work, threadIndex, deviceId, schedMode_);
     180           13 :             workers_.emplace_back(std::move(th));
     181           13 :         } catch (std::exception &threadException) {
     182            0 :             aicpusd_err("create aicpu worker[%zu] failed, %s", threadIndex, threadException.what());
     183            0 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     184            0 :         }
     185              : 
     186           13 :         return AICPU_SCHEDULE_OK;
     187              :     }
     188              : 
     189           69 :     void ThreadPool::WaitForStop()
     190              :     {
     191           69 :         aicpusd_run_info("Wait for stop begin.");
     192           82 :         for (auto &worker : workers_) {
     193           13 :             if (worker.joinable()) {
     194           13 :                 worker.join();
     195              :             }
     196              :         }
     197           69 :         workers_.clear();
     198           69 :         aicpusd_run_info("Wait for stop end.");
     199           69 :     }
     200              : 
     201           17 :     void ThreadPool::Work(const size_t threadIndex, const uint32_t deviceId, const AicpuSchedMode schedMode)
     202              :     {
     203           17 :         aicpusd_info("Aicpu device[%u]:thread[%zu] started.", deviceId, threadIndex);
     204              :         aicpu::aicpuContext_t context;
     205           17 :         context.tsId = 0U;
     206           17 :         context.hostPid = AicpuDrvManager::GetInstance().GetHostPid();
     207           17 :         context.vfId = AicpuDrvManager::GetInstance().GetVfId();
     208           17 :         context.deviceId = deviceId;
     209           17 :         aicpu::SetUniqueVfId(AicpuDrvManager::GetInstance().GetUniqueVfId());
     210           17 :         if (aicpu::aicpuSetContext(&context) != aicpu::AICPU_ERROR_NONE) {
     211            0 :             aicpusd_err("Set aicpu context failed, deviceId[%u], thread[%zu].", deviceId, threadIndex);
     212            0 :             AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     213            3 :             return;
     214              :         }
     215              : 
     216           17 :         DeployContext deployCtx = DeployContext::DEVICE;
     217           17 :         const StatusCode ctxRet = GetAicpuDeployContext(deployCtx);
     218           17 :         if (ctxRet != AICPU_SCHEDULE_OK) {
     219            0 :             aicpusd_err("Get current deploy ctx failed.");
     220            0 :             return;
     221              :         }
     222              : 
     223           17 :         if (deployCtx == DeployContext::DEVICE) {
     224           17 :             if (AicpuSchedule::ThreadPool::Instance().SetAffinity(threadIndex, deviceId) != AICPU_SCHEDULE_OK) {
     225            2 :                 AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     226            2 :                 return;
     227              :             }
     228              :         } else {
     229            0 :             AicpuSchedule::ThreadPool::Instance().SetThreadStatus(threadIndex, ThreadStatus::THREAD_RUNNING);
     230              :         }
     231           15 :         AicpuSchedule::ThreadPool::Instance().SetThreadIdRelation(threadIndex, static_cast<pid_t>(GetTid()));
     232              : 
     233           15 :         const int32_t ret = (schedMode == SCHED_MODE_MSGQ) ? InitMessageQueueWorker(threadIndex) :
     234           13 :                                                              InitInterruptWorker(deviceId, threadIndex);
     235           15 :         if (ret != AICPU_SCHEDULE_OK) {
     236            1 :             aicpusd_err("Init work for sched mode failed, mode=%u", schedMode);
     237            1 :             AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     238            1 :             return;
     239              :         }
     240              : 
     241           14 :         (void)aicpu::SetAicpuThreadIndex(static_cast<uint32_t>(threadIndex));
     242              :         // virtual device:给dvpp传递deviceId
     243           14 :         if (FeatureCtrl::IsVfModeCheckedByDeviceId(deviceId)) {
     244            0 :             AicpuSoManager::GetInstance().SetDeviceIdToDvpp(deviceId);
     245              :         }
     246              : 
     247              :         // should not add any process between PostSem and LoopProcess
     248           14 :         AicpuSchedule::ThreadPool::Instance().PostSem(threadIndex);
     249           14 :         AicpuSchedule::AicpuEventManager::GetInstance().LoopProcess(static_cast<uint32_t>(threadIndex));
     250              : 
     251           14 :         aicpusd_info("Aicpu device[%u]:thread[%u] stopped.", deviceId, threadIndex);
     252              :     }
     253              : 
     254           14 :     int32_t ThreadPool::InitInterruptWorker(const uint32_t deviceId, const size_t threadIndex)
     255              :     {
     256           14 :         const int32_t ret = halEschedSubscribeEvent(deviceId, CP_DEFAULT_GROUP_ID,
     257           14 :                                                     static_cast<uint32_t>(threadIndex), CP_EVENT_MASK);
     258           14 :         if (ret != DRV_ERROR_NONE) {
     259            1 :             aicpusd_err("Subscribe event failed, deviceId[%u], groupId[%u], threadIndex[%zu] "
     260              :                         "eventBitmap[%llu].", deviceId, CP_DEFAULT_GROUP_ID, threadIndex, CP_EVENT_MASK);
     261            1 :             return ret;
     262              :         }
     263              : 
     264           13 :         aicpusd_info("halEschedSubscribeEvent success, deviceId[%u], groupId[%u], threadIndex[%zu] eventBitmap[%llu].",
     265              :                      deviceId, CP_DEFAULT_GROUP_ID, threadIndex, CP_EVENT_MASK);
     266              : 
     267              :         /**
     268              :          * In some multi-thread scenarios, the queue for esched may not be created before the RTS delivers
     269              :          * the AICPU task. As a result, the abnormal status will be send to RTS. Therefore, need to invoke
     270              :          * the halEschedWaitEvent in advance to create a waiting queue for esched.
     271              :          */
     272           13 :         (void)AicpuSchedule::AicpuEventManager::GetInstance().DoOnce(static_cast<uint32_t>(threadIndex), deviceId, 0);
     273              : 
     274           13 :         return AICPU_SCHEDULE_OK;
     275              :     }
     276              : 
     277            2 :     int32_t ThreadPool::InitMessageQueueWorker(const size_t threadIndex)
     278              :     {
     279            2 :         return MessageQueue::GetInstance().InitMessageQueueForThread(threadIndex);
     280              :     }
     281              : 
     282           19 :     int32_t ThreadPool::WriteTidForAffinity(const size_t threadIndex)
     283              :     {
     284           19 :         if (threadIndex >= threadStatusList_.size()) {
     285            2 :             aicpusd_err("threadIndex[%zu], out of rank[0, %zu]",
     286              :                 threadIndex, threadStatusList_.size());
     287            2 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     288              :         }
     289              : 
     290           34 :         std::string command = "sudo /var/add_aicpu_tid_to_tasks.sh";
     291           17 :         std::string pathStr = "/var/add_aicpu_tid_to_tasks.sh";
     292           17 :         if (access(pathStr.c_str(), F_OK) != 0) {
     293           15 :             aicpusd_info("Not find add_aicpu_tid_to_tasks.sh.");
     294           15 :             return AICPU_SCHEDULE_OK;
     295              :         }
     296            2 :         command = command + " " + std::to_string(GetTid());
     297              : 
     298              :         // 使用system命令会对父进程进行拷贝,浪费了系统资源。在esl等环境中还会存在由于资源较少无法fork导致system卡住的问题.
     299              :         // 使用vfork替换system命令,由于与父进程共享资源,因此可解决资源浪费/卡住的问题.
     300            2 :         const int32_t ret = AicpuUtil::ExecuteCmd(command);
     301            2 :         if (ret != 0) {
     302            1 :             threadStatusList_[threadIndex] = ThreadStatus::THREAD_EXIT;
     303            1 :             aicpusd_err("write tid[%llu] to /sys/fs/cgroup/cpuset/AICPU/tasks failed, ret[%d], strerror[%s]",
     304              :                 GetTid(), ret, strerror(errno));
     305            1 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     306              :         }
     307              : 
     308            1 :         return AICPU_SCHEDULE_OK;
     309           17 :     }
     310              : 
     311           20 :     int32_t ThreadPool::AddPidToTask(const size_t threadIndex)
     312              :     {
     313           20 :         if (FeatureCtrl::IsBindPidByHal()) {
     314            2 :             if (&halBindCgroup != nullptr) {
     315            2 :                aicpusd_info("Bind pid by hal index:%zu.", threadIndex);
     316            2 :                 const drvError_t drvRet = halBindCgroup(BIND_AICPU_CGROUP);
     317            2 :                 if (drvRet != DRV_ERROR_NONE) {
     318            1 :                     aicpusd_err("halBindCgroup failed, ret[%d]", drvRet);
     319            1 :                     return AICPU_SCHEDULE_ERROR_FROM_DRV;
     320              :                 }
     321            1 :                 aicpusd_info("halBindCgroup success");
     322              :             }
     323              :         } else {
     324           18 :             aicpusd_run_info("AddPidToTask by WriteTidForAffinity");
     325           18 :             const auto ret = WriteTidForAffinity(threadIndex);
     326           18 :             if (ret != static_cast<int32_t>(AICPU_SCHEDULE_OK)) {
     327            2 :                 aicpusd_err("WriteTidForAffinity failed, ret[%d]", ret);
     328            2 :                 return static_cast<int32_t>(AICPU_SCHEDULE_ERROR_INIT_FAILED);
     329              :             }
     330           16 :             aicpusd_info("WriteTidForAffinity success");
     331              :         }
     332           17 :         return AICPU_SCHEDULE_OK;
     333              :     }
     334              : 
     335           11 :     uint32_t ThreadPool::GetNoAicpuCcpuPhysIndex(const size_t threadIndex, const uint32_t deviceId) const
     336              :     {
     337           11 :         const uint32_t ccpuNum = AicpuDrvManager::GetInstance().GetCcpuNum();
     338           11 :         if (ccpuNum == 0U) {
     339            1 :             aicpusd_err("no ctrlcpu core available for no-aicpu worker[%zu]", threadIndex);
     340            1 :             return INVALID_AICPU_ID;
     341              :         }
     342              :         // No AICPU core: bind work threads to the largest CTRLCPU cores. ccpuIdVec_ is sorted in
     343              :         // ascending order, so the last element is the largest core. Worker 0 takes the largest core,
     344              :         // worker 1 the second largest, and so on. When there are fewer cores than workers, the extra
     345              :         // workers fall back to the smallest core.
     346           10 :         uint32_t ccpuLogIndex = 0U;
     347           10 :         if (static_cast<size_t>(ccpuNum) > threadIndex) {
     348            9 :             ccpuLogIndex = ccpuNum - 1U - static_cast<uint32_t>(threadIndex);
     349              :         }
     350           10 :         const uint32_t physIndex = AicpuDrvManager::GetInstance().GetCcpuPhysIndex(ccpuLogIndex, deviceId);
     351           10 :         aicpusd_info("no aicpu worker[%zu] bind to ctrlcpu logIndex[%u], physIndex[%u]",
     352              :                      threadIndex, ccpuLogIndex, physIndex);
     353           10 :         return physIndex;
     354              :     }
     355              : 
     356           22 :     int32_t ThreadPool::SetAffinityBySelf(const size_t threadIndex, const uint32_t deviceId)
     357              :     {
     358           22 :         if (hasAicpu_ && (AddPidToTask(threadIndex) != AICPU_SCHEDULE_OK)) {
     359            2 :             aicpusd_err("AddPidToTask failed");
     360            2 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     361              :         }
     362              :         cpu_set_t mask;
     363           20 :         CPU_ZERO(&mask);
     364           20 :         const uint32_t aicpuLogIndex = hasAicpu_?
     365           16 :             static_cast<uint32_t>(threadIndex) % AicpuDrvManager::GetInstance().GetAicpuNumPerDevice(): 0U;
     366              : 
     367           20 :         uint32_t physIndex = 0;
     368           20 :         uint32_t devNum = 0U;
     369           20 :         if ((FeatureCtrl::IsVfModeCheckedByDeviceId(deviceId)) && (&halGetVdevNum != nullptr)) {
     370            3 :             const int32_t result = halGetVdevNum(&devNum);
     371            3 :             if (result != 0) {
     372            1 :                 aicpusd_err("halGetVdevNum, failed result[%d]", result);
     373            1 :                 return AICPU_SCHEDULE_ERROR_FROM_DRV;
     374              :             }
     375              :         }
     376           19 :         if (!hasAicpu_) {
     377            4 :             physIndex = GetNoAicpuCcpuPhysIndex(threadIndex, deviceId);
     378           15 :         } else if (devNum > 0U) {
     379            1 :             physIndex = AicpuDrvManager::GetInstance().GetAicpuPhysIndexInVfMode(aicpuLogIndex, deviceId);
     380              :         } else {
     381           14 :             physIndex = AicpuDrvManager::GetInstance().GetAicpuPhysIndex(aicpuLogIndex, deviceId);
     382              :         }
     383           19 :         aicpusd_info("[hw]SetAffinityBySelf, physIndex[%u], devNum[%u]", physIndex, devNum);
     384           19 :         if (physIndex == INVALID_AICPU_ID) {
     385            0 :             threadStatusList_[threadIndex] = ThreadStatus::THREAD_RUNNING;
     386            0 :             return static_cast<int32_t>(AICPU_SCHEDULE_OK);
     387              :         }
     388              :         // cannot overflow, aicpu num < 65535, max [64=4*16]
     389           19 :         CPU_SET(static_cast<int32_t>(physIndex), &mask);
     390           19 :         const int32_t ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mask);
     391           19 :         if (ret != 0) {
     392            1 :             threadStatusList_[threadIndex] = ThreadStatus::THREAD_EXIT;
     393            1 :             aicpusd_err("set affinity failed ret[%d], aicpu logical index[%zu], aicpu physical index[%u], "
     394              :                 "device id[%u]", ret, threadIndex, physIndex, deviceId);
     395            1 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     396              :         }
     397           18 :         threadStatusList_[threadIndex] = ThreadStatus::THREAD_RUNNING;
     398           18 :         aicpusd_info("set affinity success, aicpu logical index[%zu], aicpu physical index[%u], device id[%u]",
     399              :             threadIndex, physIndex, deviceId);
     400           18 :         return AICPU_SCHEDULE_OK;
     401              :     }
     402              : 
     403            7 :     int32_t ThreadPool::SetAffinityByPm(const size_t threadIndex, const uint32_t deviceId)
     404              :     {
     405            7 :         const uint32_t aicpuLogIndex = hasAicpu_?
     406            3 :             static_cast<uint32_t>(threadIndex) % AicpuDrvManager::GetInstance().GetAicpuNumPerDevice(): 0U;
     407              :         uint32_t physIndex;
     408            7 :         if (FeatureCtrl::IsVfModeCheckedByDeviceId(deviceId)) {
     409            2 :             physIndex = AicpuDrvManager::GetInstance().GetAicpuPhysIndex(aicpuLogIndex,
     410              :                                                                          (deviceId - VDEVICE_MIN_CPU_NUM));
     411              :         } else {
     412           10 :             physIndex = hasAicpu_?
     413            2 :                         AicpuDrvManager::GetInstance().GetAicpuPhysIndex(aicpuLogIndex, deviceId):
     414            3 :                         GetNoAicpuCcpuPhysIndex(threadIndex, deviceId);
     415              :         }
     416            7 :         const pid_t tid = static_cast<pid_t>(GetTid());
     417              : 
     418            7 :         std::vector<uint32_t> coreAffinity;
     419            7 :         coreAffinity.push_back(physIndex);
     420            7 :         aicpusd_info("begin to ProcMgrBindThread, tid:%d, physIndex:%u, hasAicpu_:%d", tid, physIndex, hasAicpu_);
     421            7 :         auto ret = ProcMgrBindThread(tid, coreAffinity);
     422            7 :         aicpusd_info("end to ProcMgrBindThread, ret:%d", ret);
     423            7 :         uint32_t tryTimes = 0;
     424            9 :         while ((ret != 0U) && (tryTimes <= 1)) {
     425            2 :             aicpusd_warn("set affinity failed ret[%d], will try again", ret);
     426            2 :             (void)usleep(SLEEP_USECS);
     427            2 :             ret = ProcMgrBindThread(tid, coreAffinity);
     428            2 :             tryTimes++;
     429              :         }
     430            7 :         if (ret != 0U) {
     431            1 :             threadStatusList_[threadIndex] = ThreadStatus::THREAD_EXIT;
     432            1 :             aicpusd_err("set affinity failed ret[%d], aicpu logical index[%zu], "
     433              :                         "aicpu physical index[%u],tid[%u], device id[%u]",
     434              :                         ret, threadIndex, physIndex, tid, AicpuDrvManager::GetInstance().GetDeviceId());
     435            1 :             return AICPU_SCHEDULE_ERROR_INIT_FAILED;
     436              :         }
     437            6 :         threadStatusList_[threadIndex] = ThreadStatus::THREAD_RUNNING;
     438            6 :         aicpusd_info("set affinity success, aicpu logical index[%zu], aicpu physical index[%u], device id[%u]",
     439              :             threadIndex, physIndex, AicpuDrvManager::GetInstance().GetDeviceId());
     440            6 :         return AICPU_SCHEDULE_OK;
     441            7 :     }
     442              : 
     443           28 :     int32_t ThreadPool::SetAffinity(const size_t threadIndex, const uint32_t deviceId)
     444              :     {
     445           28 :         int32_t res = static_cast<int32_t>(AICPU_SCHEDULE_OK);
     446           56 :         if (AicpuUtil::IsEnvValEqual(ENV_NAME_PROCMGR_AICPU_CPUSET, "1")) {
     447            7 :             res = SetAffinityByPm(threadIndex, deviceId);
     448            7 :             aicpusd_run_info("aicpu bind tid by pm, index[%zu], deviceId[%u], res[%d].", threadIndex, deviceId, res);
     449              :         } else {
     450           21 :             res = SetAffinityBySelf(threadIndex, deviceId);
     451           21 :             aicpusd_info("aicpu bind tid by self, index[%zu], deviceId[%u], res[%d].", threadIndex, deviceId, res);
     452              :         }
     453           28 :         return res;
     454              :     }
     455              : 
     456            1 :     void ThreadPool::SetThreadStatus(const size_t threadIndex, const ThreadStatus threadStat)
     457              :     {
     458            1 :         threadStatusList_[threadIndex] = threadStat;
     459            1 :     }
     460              : 
     461           12 :     void ThreadPool::PostSem(const size_t threadIndex)
     462              :     {
     463           12 :         (void)sem_post(&(sems_[threadIndex]));
     464           12 :     }
     465              : 
     466           15 :     void ThreadPool::SetThreadIdRelation(const size_t threadIndex, const pid_t threadId)
     467              :     {
     468           15 :         threadIdLists_[threadIndex] = threadId;
     469           15 :         aicpusd_info("set thread index:%zu and tid:%d relation to List", threadIndex,
     470              :                       static_cast<int32_t>(threadIdLists_[threadIndex]));
     471           15 :     }
     472              : 
     473            9 :     void ThreadPool::SetThreadSchedModeByTsd()
     474              :     {
     475            9 :         const size_t relationSize = threadIdLists_.size();
     476            9 :         if (relationSize > MAX_THREAD_ID_CNT) {
     477            1 :             aicpusd_err("current list to long size:%zu", relationSize);
     478            3 :             return;
     479              :         }
     480            8 :         SubProcScheduleModeInfo curInfo = {};
     481            8 :         curInfo.totalNum = static_cast<uint32_t>(relationSize);
     482            8 :         (void)std::copy(threadIdLists_.begin(), threadIdLists_.end(), curInfo.threadIdList);
     483            8 :         const std::vector<uint32_t> deviceVec = AicpuDrvManager::GetInstance().GetDeviceList();
     484            8 :         if (deviceVec.empty()) {
     485            1 :             aicpusd_err("the device vector is empty");
     486            1 :             return;
     487              :         }
     488            7 :         if (SetSubProcScheduleMode(deviceVec[0],
     489              :                                    static_cast<uint32_t>(TsdWaitType::TSD_COMPUTE),
     490            7 :                                    static_cast<uint32_t>(AicpuDrvManager::GetInstance().GetHostPid()),
     491           14 :                                    AicpuDrvManager::GetInstance().GetVfId(), &curInfo) != 0) {
     492            1 :             aicpusd_err("send msg to tsd failed");
     493            1 :             return;
     494              :         }
     495            8 :     }
     496              : }  // namespace AicpuSchedule
        

Generated by: LCOV version 2.0-1