* 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 <cinttypes>
#include <cstring>
#include <new>
#include "api_impl_kernel_args.hpp"
#include "api_impl_creator.hpp"
#include "args_handle_allocator.hpp"
#include "context.hpp"
#include "device.hpp"
#include "error_message_manage.hpp"
#include "profiler_struct.hpp"
#include "program.hpp"
#include "runtime.hpp"
#include "runtime_handle_guard.h"
namespace {
void ResetKernelArgsParamHandles(RtArgsHandle* argsHandle, uint32_t paramCount)
{
if (argsHandle == nullptr) {
return;
}
for (uint32_t i = 0U; i < paramCount; ++i) {
ResetEmbeddedInnerHandle<ParaDetail>(&(argsHandle->para[i]));
}
}
void ReinitKernelArgsEmbeddedHandle(RtArgsHandle* argsHandle, uint32_t paramCount)
{
if (argsHandle == nullptr) {
return;
}
ResetKernelArgsParamHandles(argsHandle, paramCount);
ResetEmbeddedInnerHandle<RtArgsHandle>(argsHandle);
InitEmbeddedInnerHandle<RtArgsHandle>(argsHandle);
}
}
namespace cce {
namespace runtime {
bool IsImplKernelArgsSupported() { return true; }
ApiKernelArgs* CreateImplKernelArgsAndGet()
{
ApiKernelArgs* const apiImplKernelArgs = new (std::nothrow) ApiImplKernelArgs();
if (apiImplKernelArgs == nullptr) {
RT_LOG_OUTER_MSG_IMPL(ErrorCode::EE1013, sizeof(ApiImplKernelArgs), "new");
RT_LOG(RT_LOG_ERROR, "create ApiImplKernelArgs failed.");
return nullptr;
}
RT_LOG(RT_LOG_INFO, "ApiImplKernelArgs:Runtime_alloc_size %zu", sizeof(ApiImplKernelArgs));
return apiImplKernelArgs;
}
void DestroyImplKernelArgs(ApiKernelArgs*& apiImplKernelArgs)
{
delete apiImplKernelArgs;
apiImplKernelArgs = nullptr;
}
uint16_t ApiImplKernelArgs::GetToBeCalSystemParaNum(const Kernel* const kernel) const
{
const uint16_t sysParaNum = kernel->GetSystemParaNum();
if (sysParaNum == 0U) {
return 0U;
}
uint16_t toBeCalSysParaNum = kernel->IsSupportOverFlow() ? (sysParaNum - 1U) : sysParaNum;
Runtime* rtInstance = Runtime::Instance();
const rtChipType_t chipType = rtInstance->GetChipType();
toBeCalSysParaNum =
(!IS_SUPPORT_CHIP_FEATURE(chipType, RtOptionalFeatureType::RT_FEATURE_KERNEL_INTER_CORE_SYNC_ADDR)) &&
(kernel->IsNeedSetFftsAddrInArg() && (toBeCalSysParaNum > 1U)) ?
toBeCalSysParaNum - 1U :
toBeCalSysParaNum;
RT_LOG(
RT_LOG_DEBUG, "sysParaNum=%u,toBeCalSysParaNum=%u,isSupportOverFlow=%u,IsNeedSetFftsAddrInArg=%u,chipType=%u.",
sysParaNum, toBeCalSysParaNum, static_cast<uint8_t>(kernel->IsSupportOverFlow()),
static_cast<uint8_t>(kernel->IsNeedSetFftsAddrInArg()), chipType);
return toBeCalSysParaNum;
}
rtError_t ApiImplKernelArgs::ProcessOverFlowArgs(RtArgsHandle* argsHandle)
{
Kernel* kernel = RtPtrToPtr<Kernel*>(argsHandle->funcHandle);
COND_RETURN_WITH_NOLOG(kernel->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU, RT_ERROR_NONE);
COND_RETURN_WITH_NOLOG(argsHandle->isProcessedOverflow, RT_ERROR_NONE);
COND_RETURN_WITH_NOLOG(kernel->GetSystemParaNum() == 0U, RT_ERROR_NONE);
COND_RETURN_WITH_NOLOG(!kernel->IsSupportOverFlow(), RT_ERROR_NONE);
const size_t alignSize = (kernel->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU) ?
CPU_KERNEL_ARGS_ALIGN_SIZE :
NON_CPU_KERNEL_ARGS_ALIGN_SIZE;
const size_t padding =
((argsHandle->argsSize % alignSize) == 0U) ? 0U : (alignSize - (argsHandle->argsSize % alignSize));
const size_t realParaOffset = argsHandle->argsSize + padding;
const size_t needOccupyOffset = realParaOffset + sizeof(uint64_t);
COND_PROC(
needOccupyOffset > argsHandle->bufferSize,
RT_LOG(
RT_LOG_ERROR, "process overflow args failed, para size overflow, needOccupyOffset=%zu,total=%zu",
needOccupyOffset, argsHandle->bufferSize));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
(needOccupyOffset > argsHandle->bufferSize), RT_ERROR_INVALID_VALUE,
"Processing overflow parameters in the kernel parameter handle", needOccupyOffset, "required buffer size",
RtFmtMsg("[0, %zu]", argsHandle->bufferSize));
Context* const curCtx = Runtime::Instance()->CurrentContext(true, DEFAULT_DEVICE_ID);
CHECK_CONTEXT_VALID_WITH_RETURN(curCtx, RT_ERROR_CONTEXT_NULL);
const uint64_t overflowAddr = RtPtrToValue(curCtx->CtxGetOverflowAddr());
uint64_t* overflowParaAddr = RtPtrToPtr<uint64_t*>(RtPtrToPtr<uint8_t*>(argsHandle->buffer) + realParaOffset);
*overflowParaAddr = overflowAddr;
argsHandle->argsSize = needOccupyOffset;
argsHandle->isProcessedOverflow = true;
return RT_ERROR_NONE;
}
rtError_t ApiImplKernelArgs::KernelArgsGetHandleMemSize(Kernel* const funcHandle, size_t* memSize)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
funcHandle, RT_ERROR_INVALID_VALUE, "Obtaining the memory size occupied by the parameter list handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
memSize, RT_ERROR_INVALID_VALUE, "Obtaining the memory size occupied by the parameter list handle");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_GET_HANDLE_MEM_SIZE);
const rtError_t error = [&]() -> rtError_t {
const uint32_t maxUserParamNum = (funcHandle->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU) ?
MAX_PARAM_CNT :
static_cast<uint32_t>(funcHandle->GetUserParaNum());
*memSize = sizeof(RtArgsHandle) + (maxUserParamNum * sizeof(ParaDetail));
RT_LOG(
RT_LOG_DEBUG, "memSize=%zu,maxUserParamNum=%u,RtArgsHandle=%zu,rtParaDetail=%zu", *memSize, maxUserParamNum,
sizeof(RtArgsHandle), sizeof(ParaDetail));
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args get handle mem size failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsFinalize(RtArgsHandle* argsHandle)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle, RT_ERROR_INVALID_VALUE, "Marking the completion of kernel parameter assembly");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle->funcHandle, RT_ERROR_INVALID_VALUE, "Marking the completion of kernel parameter assembly");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_FINALIZE);
const rtError_t error = [&]() -> rtError_t {
rtError_t error = ProcessOverFlowArgs(argsHandle);
ERROR_RETURN(error, "process overflow args failed,retCode=%#x.", error);
Kernel* kernel = RtPtrToPtr<Kernel*>(argsHandle->funcHandle);
const KernelRegisterType regType = kernel->GetKernelRegisterType();
Runtime* rtInstance = Runtime::Instance();
NULL_PTR_RETURN_MSG(rtInstance, RT_ERROR_INSTANCE_NULL);
Context* const curCtx = rtInstance->CurrentContext(true, DEFAULT_DEVICE_ID);
CHECK_CONTEXT_VALID_WITH_RETURN(curCtx, RT_ERROR_CONTEXT_NULL);
if ((regType == RT_KERNEL_REG_TYPE_CPU) ||
(!curCtx->Device_()->IsSupportFeature(RtOptionalFeatureType::RT_FEATURE_KERNEL_INTER_CORE_SYNC_ADDR)) ||
!kernel->IsNeedSetFftsAddrInArg()) {
argsHandle->isFinalized = 1U;
argsHandle->isParamUpdating = 0U;
return RT_ERROR_NONE;
}
uint64_t interCoreAddr = 0ULL;
uint32_t len = 0U;
error = curCtx->Device_()->QueryC2cCtrlAddr(&interCoreAddr, &len);
ERROR_RETURN(error, "get inter core addr failed, retCode=%#x", static_cast<uint32_t>(error));
uint64_t* interCoreSyncAddr = RtPtrToPtr<uint64_t*>(argsHandle->buffer);
*interCoreSyncAddr = interCoreAddr;
argsHandle->isFinalized = 1U;
argsHandle->isParamUpdating = 0U;
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args finalize failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsInitByUserMem(
Kernel* const funcHandle, RtArgsHandle* argsHandle, void* userHostMem, size_t actualArgsSize)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
funcHandle, RT_ERROR_INVALID_VALUE, "Initializing the parameter list based on the kernel function handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle, RT_ERROR_INVALID_VALUE, "Initializing the parameter list based on the kernel function handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
userHostMem, RT_ERROR_INVALID_VALUE, "Initializing the parameter list based on the kernel function handle");
ZERO_RETURN_AND_MSG_OUTER_WITH_FUNC_DESC(
actualArgsSize, "Initializing the parameter list based on the kernel function handle");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_INIT_BY_USER_MEM);
const rtError_t error = [&]() -> rtError_t {
const uint32_t maxUserParamNum = (funcHandle->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU) ?
MAX_PARAM_CNT :
static_cast<uint32_t>(funcHandle->GetUserParaNum());
new (argsHandle) RtArgsHandle{};
for (uint32_t i = 0U; i < maxUserParamNum; ++i) {
new (&(argsHandle->para[i])) ParaDetail{};
}
ReinitKernelArgsEmbeddedHandle(argsHandle, maxUserParamNum);
argsHandle->buffer = userHostMem;
argsHandle->bufferSize = actualArgsSize;
argsHandle->realUserParamNum = 0U;
argsHandle->maxUserParamNum = static_cast<uint8_t>(maxUserParamNum);
argsHandle->placeHolderNum = 0U;
argsHandle->funcHandle = funcHandle;
argsHandle->argsSize = 0U;
argsHandle->isProcessedOverflow = false;
argsHandle->isGotPhBuff = false;
argsHandle->isFinalized = 0U;
argsHandle->isParamUpdating = 0U;
(void)memset_s(
&argsHandle->cpuKernelSysArgsInfo, sizeof(CpuKernelSysArgsInfo), 0, sizeof(CpuKernelSysArgsInfo));
if (funcHandle->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_NON_CPU) {
const uint16_t toBeCalSysParaNum = GetToBeCalSystemParaNum(funcHandle);
argsHandle->sysParamSize = toBeCalSysParaNum * sizeof(uint64_t);
argsHandle->argsSize += argsHandle->sysParamSize;
} else {
argsHandle->maxUserParamNum = MAX_PARAM_CNT;
}
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args init by user mem failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsGetMemSize(Kernel* const funcHandle, size_t userArgsSize, size_t* actualArgsSize)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
funcHandle, RT_ERROR_INVALID_VALUE,
"Obtaining the memory size required by the parameter list during kernel launch");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
actualArgsSize, RT_ERROR_INVALID_VALUE,
"Obtaining the memory size required by the parameter list during kernel launch");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_GET_MEM_SIZE);
const rtError_t error = [&]() -> rtError_t {
if (funcHandle->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_NON_CPU) {
const uint16_t userParaNum = funcHandle->GetUserParaNum();
*actualArgsSize = userArgsSize + (MAX_SYSTEM_PARAM_CNT * SINGLE_NON_CPU_SYS_PARAM_SIZE) +
(userParaNum * NON_CPU_KERNEL_ARGS_ALIGN_SIZE);
RT_LOG(
RT_LOG_DEBUG, "actualArgsSize=%zu,userArgsSize=%zu,userParaNum=%u", *actualArgsSize, userArgsSize,
userParaNum);
return RT_ERROR_NONE;
}
*actualArgsSize = userArgsSize;
RT_LOG(RT_LOG_DEBUG, "actualArgsSize=%zu,userArgsSize=%zu", *actualArgsSize, userArgsSize);
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args get mem size failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsInit(Kernel* const funcHandle, RtArgsHandle** argsHandle)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
funcHandle, RT_ERROR_INVALID_VALUE, "Initializing the parameter list based on the kernel function handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle, RT_ERROR_INVALID_VALUE, "Initializing the parameter list based on the kernel function handle");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_INIT);
const rtError_t error = [&]() -> rtError_t {
static thread_local ArgsHandleAllocator threadArgsHandle;
COND_RETURN_ERROR(
threadArgsHandle.localArgsHandle_ == nullptr, RT_ERROR_MEMORY_ALLOCATION,
"Check param failed, threadArgsHandle.localArgsHandle_ can not be null.");
RtArgsHandle* localArgsHandle = threadArgsHandle.localArgsHandle_;
ReinitKernelArgsEmbeddedHandle(localArgsHandle, MAX_PARAM_CNT);
localArgsHandle->argsSize = 0U;
localArgsHandle->realUserParamNum = 0U;
localArgsHandle->placeHolderNum = 0U;
localArgsHandle->sysParamSize = 0U;
localArgsHandle->funcHandle = funcHandle;
localArgsHandle->isProcessedOverflow = false;
localArgsHandle->isGotPhBuff = false;
localArgsHandle->bufferSize = MAX_ARGS_BUFF_SIZE;
localArgsHandle->maxUserParamNum = MAX_PARAM_CNT;
localArgsHandle->isFinalized = 0U;
localArgsHandle->isParamUpdating = 0U;
(void)memset_s(
&localArgsHandle->cpuKernelSysArgsInfo, sizeof(CpuKernelSysArgsInfo), 0, sizeof(CpuKernelSysArgsInfo));
if (funcHandle->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_NON_CPU) {
RT_LOG(RT_LOG_DEBUG, "non cpu kernel branch");
const uint16_t toBeCalSysParaNum = GetToBeCalSystemParaNum(funcHandle);
localArgsHandle->sysParamSize = toBeCalSysParaNum * sizeof(uint64_t);
localArgsHandle->argsSize += localArgsHandle->sysParamSize;
}
*argsHandle = localArgsHandle;
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args init failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsAppendPlaceHolder(RtArgsHandle* argsHandle, ParaDetail** paraHandle)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle, RT_ERROR_INVALID_VALUE, "Adding placeholder parameters to the kernel parameter handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle->funcHandle, RT_ERROR_INVALID_VALUE, "Adding placeholder parameters to the kernel parameter handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
paraHandle, RT_ERROR_INVALID_VALUE, "Adding placeholder parameters to the kernel parameter handle");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_APEND_PLACE_HOLDER);
const rtError_t error = [&]() -> rtError_t {
RT_LOG(RT_LOG_DEBUG, "enter append place holder");
COND_RETURN_AND_MSG_OUTER(
argsHandle->isGotPhBuff, RT_ERROR_FEATURE_NOT_SUPPORT, ErrorCode::EE1016,
"Adding placeholder parameters to the kernel parameter handle",
"Appending placeholder or common parameter after getting placeholder buffer is not supported");
COND_RETURN_AND_MSG_OUTER(
argsHandle->isFinalized == 1U, RT_ERROR_FEATURE_NOT_SUPPORT, ErrorCode::EE1016,
"Adding placeholder parameters to the kernel parameter handle",
"Appending and getting placeholder buffer after finalization is not supported");
COND_PROC(
(argsHandle->realUserParamNum + 1U) > argsHandle->maxUserParamNum,
RT_LOG(
RT_LOG_ERROR, "para num exceed max num,current real user para num is %u,max user para num is %u",
argsHandle->realUserParamNum, argsHandle->maxUserParamNum));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
((argsHandle->realUserParamNum + 1U) > argsHandle->maxUserParamNum), RT_ERROR_INVALID_VALUE,
"Adding placeholder parameters to the kernel parameter handle", argsHandle->realUserParamNum + 1U,
"user parameter count", RtFmtMsg("[0, %u]", static_cast<uint32_t>(argsHandle->maxUserParamNum)));
const uint32_t idx = argsHandle->realUserParamNum;
argsHandle->para[idx].type = 1U;
const Kernel* const kernel = RtPtrToPtr<Kernel*>(argsHandle->funcHandle);
const size_t alignSize = (kernel->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU) ?
CPU_KERNEL_ARGS_ALIGN_SIZE :
NON_CPU_KERNEL_ARGS_ALIGN_SIZE;
const size_t padding =
((argsHandle->argsSize % alignSize) == 0U) ? 0U : (alignSize - (argsHandle->argsSize % alignSize));
const size_t realParaOffset = argsHandle->argsSize + padding;
constexpr size_t phParamSize = sizeof(uint64_t);
const size_t needOccupyOffset = realParaOffset + phParamSize;
COND_PROC(
needOccupyOffset > argsHandle->bufferSize,
RT_LOG(
RT_LOG_ERROR, "args append failed,para size overflow,needOccupyOffset=%zu,total=%zu", needOccupyOffset,
argsHandle->bufferSize));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
(needOccupyOffset > argsHandle->bufferSize), RT_ERROR_INVALID_VALUE,
"Adding placeholder parameters to the kernel parameter handle", needOccupyOffset, "required buffer size",
RtFmtMsg("[0, %zu]", argsHandle->bufferSize));
argsHandle->para[idx].paraOffset = realParaOffset;
argsHandle->para[idx].paraSize = static_cast<uint32_t>(sizeof(uint64_t));
argsHandle->para[idx].dataOffset = 0U;
*paraHandle = ((argsHandle->para) + idx);
InitEmbeddedInnerHandle<ParaDetail>(*paraHandle);
argsHandle->argsSize = needOccupyOffset;
argsHandle->realUserParamNum++;
argsHandle->placeHolderNum++;
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args append ph failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsGetPlaceHolderBuffer(
RtArgsHandle* argsHandle, ParaDetail* paraHandle, size_t dataSize, void** bufferAddr)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle, RT_ERROR_INVALID_VALUE, "Obtaining the memory address pointed to by the paramHandle placeholder");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle->funcHandle, RT_ERROR_INVALID_VALUE,
"Obtaining the memory address pointed to by the paramHandle placeholder");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
paraHandle, RT_ERROR_INVALID_VALUE, "Obtaining the memory address pointed to by the paramHandle placeholder");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
bufferAddr, RT_ERROR_INVALID_VALUE, "Obtaining the memory address pointed to by the paramHandle placeholder");
ZERO_RETURN_AND_MSG_OUTER_WITH_FUNC_DESC(
dataSize, "Obtaining the memory address pointed to by the paramHandle placeholder");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_GET_PLACE_HOLDER_BUFF);
const rtError_t error = [&]() -> rtError_t {
RT_LOG(RT_LOG_DEBUG, "get placeholder start, dataSize=%zu", dataSize);
COND_PROC(
paraHandle->type == 0U,
RT_LOG(RT_LOG_ERROR, "param type=0 does not support getting the placeholder buffer"));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
paraHandle->type == 0U, RT_ERROR_INVALID_VALUE,
"Obtaining the memory address pointed to by the paramHandle placeholder",
"a common parameter handle returned by aclrtKernelArgsAppend", "paramHandle",
"a placeholder parameter handle returned by aclrtKernelArgsAppendPlaceHolder");
COND_RETURN_AND_MSG_OUTER(
argsHandle->isFinalized == 1U, RT_ERROR_FEATURE_NOT_SUPPORT, ErrorCode::EE1016,
"Obtaining the memory address pointed to by the paramHandle placeholder",
"Appending and getting placeholder buffer after finalization is not supported");
const rtError_t error = ProcessOverFlowArgs(argsHandle);
ERROR_RETURN(error, "process overflow args failed,retCode=%#x.", error);
const Kernel* const kernel = RtPtrToPtr<Kernel*>(argsHandle->funcHandle);
const size_t alignSize = (kernel->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU) ?
CPU_KERNEL_ARGS_ALIGN_SIZE :
NON_CPU_KERNEL_ARGS_ALIGN_SIZE;
const size_t argsSize = argsHandle->argsSize;
const size_t padding = ((argsSize % alignSize) == 0U) ? 0U : (alignSize - (argsSize % alignSize));
const size_t realParaOffset = argsSize + padding;
const size_t needOccupyOffset = realParaOffset + dataSize;
COND_PROC(
needOccupyOffset > argsHandle->bufferSize,
RT_LOG(
RT_LOG_ERROR, "get placeholder buffer failed, size overflow, needOccupyOffset=%zu, total=%zu",
needOccupyOffset, argsHandle->bufferSize));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
(needOccupyOffset > argsHandle->bufferSize), RT_ERROR_INVALID_VALUE,
"Obtaining the memory address pointed to by the paramHandle placeholder", needOccupyOffset,
"required buffer size", RtFmtMsg("[0, %zu]", argsHandle->bufferSize));
argsHandle->isGotPhBuff = true;
paraHandle->dataOffset = realParaOffset;
*bufferAddr = RtPtrToPtr<void*>(RtPtrToPtr<uint8_t*>(argsHandle->buffer) + paraHandle->dataOffset);
argsHandle->argsSize = needOccupyOffset;
RT_LOG(
RT_LOG_DEBUG, "get placeholder end, dataSize=%zu, dataOffset=%zu, needOccupyOffset=%zu", dataSize,
realParaOffset, needOccupyOffset);
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args get ph buffer failed.");
return error;
}
rtError_t ApiImplKernelArgs::KernelArgsAppend(
RtArgsHandle* argsHandle, void* para, size_t paraSize, ParaDetail** paraHandle)
{
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
argsHandle, RT_ERROR_INVALID_VALUE, "Adding parameters to the kernel parameter handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
para, RT_ERROR_INVALID_VALUE, "Adding parameters to the kernel parameter handle");
ZERO_RETURN_AND_MSG_OUTER_WITH_FUNC_DESC(paraSize, "Adding parameters to the kernel parameter handle");
NULL_PTR_RETURN_MSG_OUTER_WITH_FUNC_DESC(
paraHandle, RT_ERROR_INVALID_VALUE, "Adding parameters to the kernel parameter handle");
Runtime::Instance()->CallApiBegin(RT_PROF_API_KERNEL_ARGS_APEND);
const rtError_t error = [&]() -> rtError_t {
RT_LOG(RT_LOG_DEBUG, "args append start, paraSize=%zu", paraSize);
COND_RETURN_AND_MSG_OUTER(
argsHandle->isFinalized == 1U, RT_ERROR_FEATURE_NOT_SUPPORT, ErrorCode::EE1016,
"Adding parameters to the kernel parameter handle",
"Appending and getting placeholder buffer after finalization is not supported");
COND_RETURN_AND_MSG_OUTER(
argsHandle->isGotPhBuff, RT_ERROR_FEATURE_NOT_SUPPORT, ErrorCode::EE1016,
"Adding parameters to the kernel parameter handle",
"Appending placeholder or common parameter after getting placeholder buffer is not supported");
COND_PROC(
(argsHandle->realUserParamNum + 1U) > argsHandle->maxUserParamNum,
RT_LOG(
RT_LOG_ERROR, "para num exceed max num,current real user para num is %u,max user para num is %u",
argsHandle->realUserParamNum, argsHandle->maxUserParamNum));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
((argsHandle->realUserParamNum + 1U) > argsHandle->maxUserParamNum), RT_ERROR_INVALID_VALUE,
"Adding parameters to the kernel parameter handle", argsHandle->realUserParamNum + 1U,
"user parameter count", RtFmtMsg("[0, %u]", static_cast<uint32_t>(argsHandle->maxUserParamNum)));
const Kernel* const kernel = RtPtrToPtr<Kernel*>(argsHandle->funcHandle);
const size_t alignSize = (kernel->GetKernelRegisterType() == RT_KERNEL_REG_TYPE_CPU) ?
CPU_KERNEL_ARGS_ALIGN_SIZE :
NON_CPU_KERNEL_ARGS_ALIGN_SIZE;
const size_t padding =
((argsHandle->argsSize % alignSize) == 0U) ? 0U : (alignSize - (argsHandle->argsSize % alignSize));
const size_t realParaOffset = argsHandle->argsSize + padding;
const size_t needOccupyOffset = realParaOffset + paraSize;
COND_PROC(
needOccupyOffset > argsHandle->bufferSize,
RT_LOG(
RT_LOG_ERROR, "args append failed, para size overflow, needOccupyOffset=%zu,total=%zu",
needOccupyOffset, argsHandle->bufferSize));
COND_RETURN_AND_MSG_OUTER_WITH_PARAM_NAME_AND_FUNC_DESC(
(needOccupyOffset > argsHandle->bufferSize), RT_ERROR_INVALID_VALUE,
"Adding parameters to the kernel parameter handle", needOccupyOffset, "required buffer size",
RtFmtMsg("[0, %zu]", argsHandle->bufferSize));
const uint8_t index = argsHandle->realUserParamNum;
*paraHandle = &(argsHandle->para[index]);
argsHandle->para[index].type = 0U;
argsHandle->para[index].paraOffset = realParaOffset;
argsHandle->para[index].paraSize = paraSize;
argsHandle->para[index].dataOffset = 0U;
const uintptr_t offset = RtPtrToValue(argsHandle->buffer) + static_cast<uint64_t>(realParaOffset);
const errno_t ret = memcpy_s(RtPtrToPtr<void*>(offset), paraSize, para, paraSize);
COND_RETURN_AND_MSG_OUTER(
ret != EOK, RT_ERROR_INVALID_VALUE, ErrorCode::EE1020, "Adding parameters to the kernel parameter handle",
"memcpy_s", RtFmtMsg("%d", ret), strerror(ret),
RtFmtMsg(
"dest=0x%" PRIx64 ", para=0x%" PRIx64 ", destMax=%zu, paraSize=%zu.", static_cast<uint64_t>(offset),
RtPtrToValue(para), paraSize, paraSize));
InitEmbeddedInnerHandle<ParaDetail>(*paraHandle);
argsHandle->argsSize = needOccupyOffset;
argsHandle->realUserParamNum++;
return RT_ERROR_NONE;
}();
Runtime::Instance()->CallApiEnd(error);
ERROR_RETURN(error, "kernel args append failed.");
return error;
}
}
}