* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "qs_interface_process.h"
#include <securec.h>
#include <unistd.h>
#include "common/bqs_log.h"
#include "common/bqs_util.h"
#include "msprof_manager.h"
#include "queue_schedule_hal_interface_ref.h"
#include "common/bqs_feature_ctrl.h"
namespace bqs {
constexpr uint32_t QUERY_BIND_HOST_PID_INTERVBALE = 10000U;
#ifndef aicpusd_UT
constexpr uint32_t QUERY_BIND_HOST_PID_TIME = 120000000U;
#else
constexpr uint32_t QUERY_BIND_HOST_PID_TIME = 100000U;
#endif
constexpr uint32_t QUERY_BIND_HOST_PID_LOG_INTERVAL = 1000U;
QueueScheduleInterface &QueueScheduleInterface::GetInstance()
{
static QueueScheduleInterface instance;
return instance;
}
* @ingroup QueueScheduleInterface
* @brief it use to initialize aicpu schedule.
* @param [in] params InitQsParams
* @return BQS_STATUS_OK: success, other: error code
*/
int32_t QueueScheduleInterface::InitQueueScheduler(const InitQsParams ¶ms)
{
const std::unique_lock<std::mutex> lk(mutexForInit_);
BQS_LOG_INFO("Start up BqsInterface.numaFlag[%d]", params.numaFlag);
if (bqs::GetRunContext() != bqs::RunContext::HOST) {
const auto initCpuInfoRet = BindCpuUtils::GetDevCpuInfo(params.deviceId, aiCpuIds_, ctrlCpuIds_,
coreNumPerDev_, aicpuNum_, aicpuBaseId_);
if (initCpuInfoRet != BQS_STATUS_OK) {
return static_cast<int32_t>(initCpuInfoRet);
}
}
if (params.numaFlag) {
const auto initCpuInfoRet = BindCpuUtils::GetDevCpuInfo(params.deviceIdExtra, aiCpuIdsExtra_,
ctrlCpuIdsExtra_, coreNumPerDevExtra_, aicpuNumExtra_, aicpuBaseIdExtra_);
if (initCpuInfoRet != BQS_STATUS_OK) {
BQS_LOG_ERROR("GetDevCpuInfo error");
return static_cast<int32_t>(initCpuInfoRet);
}
}
queueSchedule_.reset(new (std::nothrow) QueueSchedule(params));
if (queueSchedule_ == nullptr) {
BQS_LOG_ERROR("Fail to allocate QueueSchedule");
return static_cast<int32_t>(BQS_STATUS_INNER_ERROR);
}
BQS_LOG_INFO("Prepare bind process with host process, deviceId[%u], RunContext is [%u]",
params.deviceId, static_cast<uint32_t>(bqs::GetRunContext()));
if ((bqs::GetRunContext() != bqs::RunContext::HOST) &&
(params.starter != bqs::QsStartType::START_BY_DEPLOYER) &&
(params.runMode != QueueSchedulerRunMode::MULTI_THREAD)) {
const auto bindRet = CheckBindHostPid(params.pid);
if (bindRet != bqs::BQS_STATUS_OK) {
BQS_LOG_ERROR("BindHostPid failed");
return static_cast<int32_t>(bindRet);
}
}
const bool profFlag = params.profFlag;
BqsMsprofManager::GetInstance().InitBqsMsprofManager(profFlag, params.profCfgData);
const bqs::BqsStatus bsqStatus = queueSchedule_->StartQueueSchedule();
if (bsqStatus != bqs::BQS_STATUS_OK) {
BQS_LOG_ERROR("QueueSchedule start failed, ret=%d", static_cast<int32_t>(bsqStatus));
return static_cast<int32_t>(bsqStatus);
}
return static_cast<int32_t>(BQS_STATUS_OK);
}
void QueueScheduleInterface::WaitForStop()
{
if (queueSchedule_ != nullptr) {
queueSchedule_->WaitForStop();
}
}
* @ingroup QueueScheduleInterface
* @brief it use to destroy all model.
*/
int32_t QueueScheduleInterface::Destroy() const
{
if (queueSchedule_ != nullptr) {
queueSchedule_->Destroy();
}
return static_cast<int32_t>(BQS_STATUS_OK);
}
uint32_t QueueScheduleInterface::GetAicpuPhysIndex(uint32_t deviceId, const uint32_t aicpuLogIndex) const
{
if (FeatureCtrl::IsAosCore()) {
return ((aicpuBaseId_ + aicpuNum_) * deviceId) + aicpuBaseId_ + aicpuLogIndex;
}
if (aicpuLogIndex >= aiCpuIds_.size()) {
BQS_LOG_INFO("Get aicpu index not success");
return 0U;
}
if (FeatureCtrl::BindCpuOnlyOneDevice()) {
return aiCpuIds_[aicpuLogIndex];
}
return (coreNumPerDev_ * deviceId) + aiCpuIds_[aicpuLogIndex];
}
uint32_t QueueScheduleInterface::GetExtraAicpuPhysIndex(uint32_t deviceId, const uint32_t aicpuLogIndex) const
{
#ifdef _AOSCORE_
return ((aicpuBaseIdExtra_ + aicpuNumExtra_) * deviceId) + aicpuBaseIdExtra_ + aicpuLogIndex;
#else
if (aicpuLogIndex >= aiCpuIdsExtra_.size()) {
BQS_LOG_ERROR("Get aicpu index error");
return 0U;
}
#ifdef BIND_CPU_ONLY_ONE_DEVICE
return aiCpuIdsExtra_[aicpuLogIndex];
#else
return (coreNumPerDevExtra_ * deviceId) + aiCpuIdsExtra_[aicpuLogIndex];
#endif
#endif
}
int32_t QueueScheduleInterface::CheckBindHostPid(const uint32_t selfHostPid) const
{
BQS_LOG_RUN_INFO("Start query process host pid");
if (&drvQueryProcessHostPid == nullptr) {
BQS_LOG_INFO("drvQueryProcessHostPid does not exist");
return bqs::BQS_STATUS_OK;
}
drvError_t ret = DRV_ERROR_NONE;
unsigned int hostpid = 0;
unsigned int cpType = DEVDRV_PROCESS_CPTYPE_MAX;
const int pid = static_cast<int>(getpid());
for (uint32_t i = 0; i < QUERY_BIND_HOST_PID_TIME/QUERY_BIND_HOST_PID_INTERVBALE; i++) {
ret = drvQueryProcessHostPid(pid, nullptr, nullptr, &hostpid, &cpType);
if ((i % QUERY_BIND_HOST_PID_LOG_INTERVAL) == 0U) {
BQS_LOG_RUN_INFO("Query process host pid end, ret=%d, hostpid=%u, expect=%u, cpType=%u",
static_cast<int32_t>(ret), hostpid, selfHostPid, cpType);
}
if (ret == DRV_ERROR_NO_PROCESS) {
BQS_LOG_INFO("call drvQueryProcessHostPid trg again");
(void)usleep(QUERY_BIND_HOST_PID_INTERVBALE);
continue;
}
if (ret != DRV_ERROR_NONE) {
BQS_LOG_ERROR("call drvQueryProcessHostPid failed, ret[%d]", static_cast<int32_t>(ret));
return bqs::BQS_STATUS_DRIVER_ERROR;
}
BQS_LOG_INFO("call drvQueryProcessHostPid result, hostpid[%d], cpType[%d]", hostpid, cpType);
if (selfHostPid == static_cast<uint32_t>(hostpid)) {
BQS_LOG_RUN_INFO("call drvQueryProcessHostPid success, hostpid[%d]", hostpid);
return bqs::BQS_STATUS_OK;
} else {
BQS_LOG_ERROR("CheckBindHostPid failed, hostpid not right. ret[%d], pid[%d], hostpid[%d], cpType[%d]",
static_cast<int32_t>(ret), pid, hostpid, cpType);
return bqs::BQS_STATUS_DRIVER_ERROR;
}
}
BQS_LOG_ERROR("CheckBindHostPid failed, try timeout. ret[%d], pid[%d], hostpid[%d], cpType[%d]",
static_cast<int32_t>(ret), pid, hostpid, cpType);
return bqs::BQS_STATUS_DRIVER_ERROR;
}
void QueueScheduleInterface::ReportAbnormal() const
{
if (queueSchedule_ != nullptr) {
queueSchedule_->ReportAbnormal();
}
}
}