* 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 <stdlib.h>
#ifndef EMU_ST
#include "svm_user_interface.h"
#endif
#include "queue.h"
#include "que_ub_msg.h"
#include "que_uma.h"
#include "que_compiler.h"
#include "queue_interface.h"
#include "que_comm_agent.h"
#ifndef EMU_ST
struct que_agent_interface_list que_agent_interface = {NULL};
struct que_agent_interface_list *que_get_agent_interface(void)
{
return &que_agent_interface;
}
struct que_ctx *que_ctx_get(unsigned int devid)
{
return que_agent_interface.que_ctx_get(devid);
}
void que_ctx_put(struct que_ctx *ctx)
{
que_agent_interface.que_ctx_put(ctx);
}
int que_ctx_add(struct que_ctx *ctx)
{
return que_agent_interface.que_ctx_add(ctx);
}
int que_ctx_del(struct que_ctx *ctx)
{
return que_agent_interface.que_ctx_del(ctx);
}
struct que_chan *que_chan_get(unsigned int devid, unsigned int qid)
{
return que_agent_interface.que_chan_get(devid, qid);
}
void que_chan_put(struct que_chan *chan)
{
que_agent_interface.que_chan_put(chan);
}
int que_chan_add(struct que_chan *chan)
{
return que_agent_interface.que_chan_add(chan);
}
int que_chan_del(struct que_chan *chan)
{
return que_agent_interface.que_chan_del(chan);
}
int que_ub_res_init(unsigned int devid)
{
return que_agent_interface.que_ub_res_init(devid);
}
void que_ub_res_uninit(unsigned int devid, bool uninit_flag)
{
return que_agent_interface.que_ub_res_uninit(devid, uninit_flag);
}
drvError_t que_mem_alloc(void **addr, unsigned long long size)
{
return que_agent_interface.que_mem_alloc(addr, size);
}
void que_mem_free(void *addr)
{
return que_agent_interface.que_mem_free(addr);
}
bool que_is_share_mem(unsigned long long addr)
{
#ifndef DRV_HOST
if ((addr >= QUE_SP_VA_START) && (addr < (QUE_SP_VA_START + QUE_SP_VA_SIZE))) {
return true;
} else {
return false;
}
#endif
return false;
}
void queue_agent_update_time(struct timeval start, struct timeval end, int *timeout)
{
if (*timeout > 0) {
#ifndef EMU_ST
long tmp = *timeout;
tmp -= (end.tv_sec - start.tv_sec) * MS_PER_SECOND + (end.tv_usec - start.tv_usec) / US_PER_MSECOND;
*timeout = tmp > 0 ? (int)tmp : 0;
#endif
}
}
int que_get_peer_que_info(unsigned int dev_id, unsigned int qid, unsigned int *remote_qid,
struct que_peer_que_attr *peer_que_attr)
{
struct queue_manages *que_manage = NULL;
if ((dev_id >= MAX_DEVICE) || (qid >= MAX_SURPORT_QUEUE_NUM)) {
QUEUE_LOG_ERR("para is error. (dev_id=%u, qid=%u)\n", dev_id, qid);
return DRV_ERROR_INVALID_VALUE;
}
if (!queue_get(qid)) {
QUEUE_LOG_ERR("queue get failed. (qid=%u)\n", qid);
return DRV_ERROR_NOT_EXIST;
}
que_manage = queue_get_local_mng(qid);
if (que_manage == NULL) {
queue_put(qid);
QUEUE_LOG_ERR("Queue local manage is null. (dev_id=%u, qid=%u)\n", dev_id, qid);
return DRV_ERROR_NOT_EXIST;
}
if (que_manage->valid != QUEUE_CREATED) {
queue_put(qid);
QUEUE_LOG_ERR(" queue(%u) is not created.\n", qid);
return DRV_ERROR_NOT_EXIST;
}
if ((que_manage->inter_dev_state != QUEUE_STATE_EXPORTED) &&
(que_manage->inter_dev_state != QUEUE_STATE_IMPORTED)) {
queue_put(qid);
return DRV_ERROR_PARA_ERROR;
}
*remote_qid = que_manage->remote_qid;
if (peer_que_attr != NULL) {
peer_que_attr->inter_dev_state = que_manage->inter_dev_state;
peer_que_attr->tjfr_id = que_manage->tjfr_id;
peer_que_attr->tjfr_valid_flag = que_manage->tjfr_valid_flag;
peer_que_attr->depth = queue_get_local_depth(qid);
peer_que_attr->peer_devid = que_manage->remote_devid;
peer_que_attr->token = que_manage->token;
}
if ((que_manage->remote_qid == QUEUE_INVALID_VALUE) || (*remote_qid == QUEUE_INVALID_VALUE)) {
queue_put(qid);
return DRV_ERROR_NO_RESOURCES;
}
queue_put(qid);
return DRV_ERROR_NONE;
}
int que_get_peer_proc_info(unsigned int dev_id, unsigned int qid, pid_t *remote_pid, unsigned int *remote_devid,
unsigned int *remote_grpid)
{
struct queue_manages *que_manage = NULL;
if ((dev_id >= MAX_DEVICE) || (qid >= MAX_SURPORT_QUEUE_NUM)) {
QUEUE_LOG_ERR("para is error. (dev_id=%u, qid=%u)\n", dev_id, qid);
return DRV_ERROR_INVALID_VALUE;
}
if (!queue_get(qid)) {
QUEUE_LOG_ERR("queue get failed. (qid=%u)\n", qid);
return DRV_ERROR_NOT_EXIST;
}
que_manage = queue_get_local_mng(qid);
if (que_manage == NULL) {
queue_put(qid);
QUEUE_LOG_ERR("Queue local manage is null. (dev_id=%u, qid=%u)\n", dev_id, qid);
return DRV_ERROR_NOT_EXIST;
}
if (que_manage->valid != QUEUE_CREATED) {
queue_put(qid);
QUEUE_LOG_ERR(" queue(%u) is not created.\n", qid);
return DRV_ERROR_NOT_EXIST;
}
*remote_pid = que_manage->remote_devpid;
*remote_devid = que_manage->remote_devid;
*remote_grpid = que_manage->remote_grpid;
queue_put(qid);
return DRV_ERROR_NONE;
}
int que_set_tjfr_id_and_token(unsigned int dev_id, unsigned int qid, urma_jfr_id_t *tjfr_id, urma_token_t *token)
{
struct queue_manages *que_manage = NULL;
if (!queue_get(qid)) {
QUEUE_LOG_ERR("queue get failed. (dev_id=%u; qid=%u)\n", dev_id, qid);
return DRV_ERROR_NOT_EXIST;
}
que_manage = queue_get_local_mng(qid);
if (que_manage == NULL) {
queue_put(qid);
QUEUE_LOG_ERR("Queue local manage is null. (dev_id=%u, qid=%u)\n", dev_id, qid);
return DRV_ERROR_NOT_EXIST;
}
if (que_manage->valid != QUEUE_CREATED) {
queue_put(qid);
QUEUE_LOG_ERR(" queue(%u) is not created.\n", qid);
return DRV_ERROR_NOT_EXIST;
}
if ((que_manage->inter_dev_state != QUEUE_STATE_EXPORTED) &&
(que_manage->inter_dev_state != QUEUE_STATE_IMPORTED)) {
queue_put(qid);
return DRV_ERROR_NOT_SUPPORT;
}
que_manage->tjfr_id = *tjfr_id;
que_manage->token = *token;
que_manage->tjfr_valid_flag = 1;
queue_put(qid);
return DRV_ERROR_NONE;
}
drvError_t que_inter_dev_send_f2nf(unsigned int dev_id, unsigned int qid)
{
struct queue_manages *que_manage = NULL;
if (!queue_get(qid)) {
QUEUE_LOG_ERR("queue get failed. (dev_id=%u; qid=%u)\n", dev_id, qid);
return DRV_ERROR_NOT_EXIST;
}
que_manage = queue_get_local_mng(qid);
if (que_manage == NULL) {
queue_put(qid);
QUEUE_LOG_ERR("Queue local manage is null. (dev_id=%u, qid=%u)\n", dev_id, qid);
return DRV_ERROR_NOT_EXIST;
}
if (que_manage->valid != QUEUE_CREATED) {
queue_put(qid);
QUEUE_LOG_ERR(" queue(%u) is not created.\n", qid);
return DRV_ERROR_NOT_EXIST;
}
send_f_to_nf_event(dev_id, que_manage);
queue_put(qid);
return DRV_ERROR_NONE;
}
static inline bool que_inter_export_queue_status(unsigned int dev_id, int pid, unsigned int qid, int *inter_dev_state)
{
struct queue_manages *que_manage = NULL;
if (!queue_get(qid)) {
return false;
}
que_manage = queue_get_local_mng(qid);
if (que_manage == NULL) {
queue_put(qid);
return false;
}
if ((que_manage->valid != QUEUE_CREATED)
|| (que_manage->dev_id != dev_id)
|| (que_manage->creator_pid != pid)) {
queue_put(qid);
return false;
}
*inter_dev_state = que_manage->inter_dev_state;
if ((que_manage->inter_dev_state != QUEUE_STATE_EXPORTED)
|| (que_manage->remote_qid == QUEUE_INVALID_VALUE)) {
queue_put(qid);
return false;
}
queue_put(qid);
return true;
}
void que_get_single_export_que_import_stat(unsigned int dev_id, unsigned int qid, unsigned int *status)
{
int is_imported, inter_dev_state;
int not_imported_num = 0;
int inter_export_queue_num = 0;
int pid = getpid();
inter_dev_state = QUEUE_STATE_DISABLED;
is_imported = que_inter_export_queue_status(dev_id, pid, qid, &inter_dev_state);
if (inter_dev_state == QUEUE_STATE_EXPORTED) {
if (is_imported == false) {
not_imported_num++;
}
inter_export_queue_num++;
}
if (inter_export_queue_num == 0) {
not_imported_num = QUEUE_INVALID_VALUE;
}
*status = not_imported_num;
return;
}
void que_get_all_export_que_import_stat(unsigned int dev_id, unsigned int *status)
{
int qid_idx, is_imported, inter_dev_state;
int not_imported_num = 0;
int inter_export_queue_num = 0;
int pid = getpid();
for (qid_idx = 0; qid_idx < MAX_SURPORT_QUEUE_NUM; qid_idx++) {
inter_dev_state = QUEUE_STATE_DISABLED;
is_imported = que_inter_export_queue_status(dev_id, pid, qid_idx, &inter_dev_state);
if (inter_dev_state == QUEUE_STATE_EXPORTED) {
if (is_imported == false) {
not_imported_num++;
}
inter_export_queue_num++;
}
}
if (inter_export_queue_num == 0) {
not_imported_num = QUEUE_INVALID_VALUE;
}
*status = not_imported_num;
return;
}
unsigned int que_get_chan_devid(unsigned int devid)
{
#ifdef DRV_HOST
return halGetHostDevid();
#endif
return devid;
}
unsigned int que_get_urma_devid(unsigned int devid, unsigned int peer_devid)
{
return (devid == halGetHostDevid()) ? peer_devid : devid;
}
uint64_t que_get_cur_time_ns(void)
{
struct timespec timestamp;
(void)clock_gettime(CLOCK_MONOTONIC, ×tamp);
return (uint64_t)((timestamp.tv_sec * NS_PER_SECOND) + timestamp.tv_nsec);
}
#else
void que_comm_agent_emu_test(void)
{
}
#endif