* Copyright (c) 2026 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 "api_impl_esched.hpp"
#include <new>
#include <string>
#include "api_impl_creator.hpp"
#include "context.hpp"
#include "error_message_manage.hpp"
#include "heterogenous.h"
#include "npu_driver.hpp"
#include "runtime.hpp"
namespace cce {
namespace runtime {
namespace {
inline bool IsHostCpuDevId(const int32_t devId) { return devId == DEFAULT_HOSTCPU_USER_DEVICE_ID; }
}
bool IsImplEschedSupported() { return true; }
ApiEsched* CreateImplEschedAndGet()
{
ApiEsched* const apiImplEsched = new (std::nothrow) ApiImplEsched();
if (apiImplEsched == nullptr) {
RT_LOG_OUTER_MSG_IMPL(ErrorCode::EE1013, sizeof(ApiImplEsched), "new");
RT_LOG(RT_LOG_ERROR, "create ApiImplEsched failed.");
return nullptr;
}
RT_LOG(RT_LOG_INFO, "ApiImplEsched:Runtime_alloc_size %zu", sizeof(ApiImplEsched));
return apiImplEsched;
}
void DestroyImplEsched(ApiEsched*& apiImplEsched)
{
delete apiImplEsched;
apiImplEsched = nullptr;
}
namespace {
rtError_t ConvertUserDevIdToRealDevId(const int32_t devId, int32_t& realDeviceId)
{
if (IsHostCpuDevId(devId)) {
realDeviceId = DEFAULT_HOSTCPU_LOGIC_DEVICE_ID;
return RT_ERROR_NONE;
}
const rtError_t error =
Runtime::Instance()->ChgUserDevIdToDeviceId(static_cast<uint32_t>(devId), RtPtrToPtr<uint32_t*>(&realDeviceId));
COND_RETURN_ERROR(
error != RT_ERROR_NONE, error, "Failed to convert the user device ID %d to driver device ID.", devId);
return RT_ERROR_NONE;
}
rtError_t ConvertUserDevIdToRealDevId(const uint32_t devId, uint32_t& realDeviceId)
{
if (IsHostCpuDevId(static_cast<int32_t>(devId))) {
realDeviceId = static_cast<uint32_t>(DEFAULT_HOSTCPU_LOGIC_DEVICE_ID);
return RT_ERROR_NONE;
}
const rtError_t error = Runtime::Instance()->ChgUserDevIdToDeviceId(devId, &realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, error, "Failed to convert the user device ID %u to driver device ID.", devId);
return RT_ERROR_NONE;
}
}
rtError_t ApiImplEsched::EschedSubmitEventSync(
const int32_t devId, rtEschedEventSummary_t* const evt, rtEschedEventReply_t* const ack)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(evt, RT_ERROR_INVALID_VALUE, "Synchronous event submission");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(ack, RT_ERROR_INVALID_VALUE, "Synchronous event submission");
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_AND_FUNC_DESC(
((evt->eventId != RT_MQ_SCHED_EVENT_QS_MSG) && (evt->eventId != RT_MQ_SCHED_EVENT_DRV_CUSTOM_MSG)),
RT_ERROR_FEATURE_NOT_SUPPORT, "Synchronous event submission", evt->eventId,
std::to_string(RT_MQ_SCHED_EVENT_QS_MSG) + " or " + std::to_string(RT_MQ_SCHED_EVENT_DRV_CUSTOM_MSG));
int32_t realDeviceId = 0;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
RT_LOG(RT_LOG_INFO, "Start to submit event on drv devId %d.", realDeviceId);
error = Runtime::Instance()->CheckCurCtxValid(realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%d].", realDeviceId);
return NpuDriver::EschedSubmitEventSync(realDeviceId, evt, ack);
}
rtError_t ApiImplEsched::EschedAttachDevice(const uint32_t devId)
{
uint32_t realDeviceId = 0U;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(static_cast<int32_t>(realDeviceId));
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%u].", realDeviceId);
return NpuDriver::EschedAttachDevice(realDeviceId);
}
rtError_t ApiImplEsched::EschedDettachDevice(const uint32_t devId)
{
uint32_t realDeviceId = 0U;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(static_cast<int32_t>(realDeviceId));
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%u].", realDeviceId);
return NpuDriver::EschedDettachDevice(realDeviceId);
}
rtError_t ApiImplEsched::EschedWaitEvent(
const int32_t devId, const uint32_t grpId, const uint32_t threadId, const int32_t timeout,
rtEschedEventSummary_t* const evt)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(evt, RT_ERROR_INVALID_VALUE, "Waiting for an event");
int32_t realDeviceId = 0;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%d].", realDeviceId);
return NpuDriver::EschedWaitEvent(realDeviceId, grpId, threadId, timeout, evt);
}
rtError_t ApiImplEsched::EschedCreateGrp(const int32_t devId, const uint32_t grpId, const rtGroupType_t type)
{
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
(type < RT_GRP_TYPE_BIND_DP_CPU) || (type > RT_GRP_TYPE_BIND_DP_CPU_EXCLUSIVE), RT_ERROR_INVALID_VALUE,
"Creating an event scheduling group", RtFmtMsg("UNKNOWN(%d)", static_cast<int32_t>(type)), "type",
"[" + std::to_string(RT_GRP_TYPE_BIND_DP_CPU) + ", " + std::to_string(RT_GRP_TYPE_BIND_DP_CPU_EXCLUSIVE) + "]");
int32_t realDeviceId = 0;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%d].", realDeviceId);
return NpuDriver::EschedCreateGrp(realDeviceId, grpId, type);
}
rtError_t ApiImplEsched::EschedSubmitEvent(const int32_t devId, rtEschedEventSummary_t* const evt)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(evt, RT_ERROR_INVALID_VALUE, "Event submission");
int32_t realDeviceId = 0;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%d].", realDeviceId);
return NpuDriver::EschedSubmitEvent(realDeviceId, evt);
}
rtError_t ApiImplEsched::EschedSubscribeEvent(
const int32_t devId, const uint32_t grpId, const uint32_t threadId, const uint64_t eventBitmap)
{
int32_t realDeviceId = 0;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%d].", realDeviceId);
return NpuDriver::EschedSubscribeEvent(realDeviceId, grpId, threadId, eventBitmap);
}
rtError_t ApiImplEsched::EschedAckEvent(
const int32_t devId, const rtEventIdType_t evtId, const uint32_t subEvtId, char_t* const msg, const uint32_t len)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(msg, RT_ERROR_INVALID_VALUE, "Event confirmation");
int32_t realDeviceId = 0;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
error = Runtime::Instance()->CheckCurCtxValid(realDeviceId);
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%d].", realDeviceId);
return NpuDriver::EschedAckEvent(realDeviceId, evtId, subEvtId, msg, len);
}
rtError_t ApiImplEsched::EschedQueryInfo(
const uint32_t devId, const rtEschedQueryType type, rtEschedInputInfo* const inPut,
rtEschedOutputInfo* const outPut)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(inPut, RT_ERROR_INVALID_VALUE, "Information query");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(outPut, RT_ERROR_INVALID_VALUE, "Information query");
uint32_t realDeviceId = 0U;
rtError_t error = ConvertUserDevIdToRealDevId(devId, realDeviceId);
COND_RETURN_WITH_NOLOG(error != RT_ERROR_NONE, error);
RT_LOG(RT_LOG_INFO, "Start to Query Esched Info");
error = Runtime::Instance()->CheckCurCtxValid(static_cast<int32_t>(realDeviceId));
COND_RETURN_ERROR(
error != RT_ERROR_NONE, RT_ERROR_CONTEXT_NULL, "Current Context is null, drv devId[%u].", realDeviceId);
return NpuDriver::EschedQueryInfo(realDeviceId, type, inPut, outPut);
}
}
}