* 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 "event_sched.h"
#include <sys/ioctl.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/sysinfo.h>
#include <pthread.h>
#include <stdbool.h>
#include "securec.h"
#ifdef CFG_FEATURE_EXTERNAL_CDEV
#include "davinci_interface.h"
#endif
#include "dms_user_interface.h"
#include "pbl_uda_user.h"
#include "esched_ioctl.h"
#include "esched_user_interface.h"
#ifndef CFG_ENV_HOST
#define ESCHED_MAX_PHY_DEV_NUM 4
#endif
#define ESCHED_CLOSE_MAX_SLEEP 10000
static THREAD__ int32_t sched_dev_fd[ESCHED_DEV_NUM];
static esched_proc_grp_info sched_grp[ESCHED_DEV_NUM];
static pthread_key_t esched_thread_key;
static pthread_once_t esched_thread_key_init = PTHREAD_ONCE_INIT;
static bool esched_thread_key_flag = false;
pthread_mutex_t g_esched_init_mutex = PTHREAD_MUTEX_INITIALIZER;
THREAD__ void (*esched_finish_func[SCHED_MAX_GRP_NUM][EVENT_MAX_NUM])(unsigned int dev_id, unsigned int grp_id,
unsigned int event_id, unsigned int subevent_id) = {{NULL}};
THREAD__ void (*esched_finish_func_ex[SCHED_MAX_GRP_NUM][EVENT_MAX_NUM])(unsigned int dev_id, unsigned int grp_id,
esched_event_info event_info) = {{NULL}};
THREAD__ void (*esched_ack_func[SCHED_MAX_GRP_NUM][EVENT_MAX_NUM])(unsigned int dev_id, unsigned int subevent_id,
char *msg, unsigned int msgLen) = {{NULL}};
THREAD__ void (*esched_trace_record_func[SCHED_MAX_GRP_NUM][EVENT_MAX_NUM])(unsigned int grp_id, unsigned int event_id,
unsigned int subevent_id, sched_trace_time_info *sched_trace_time_info) = {{NULL}};
STATIC bool esched_is_host_virtual_dev(unsigned int dev_id)
{
#ifdef CFG_SOC_PLATFORM_CLOUD_V4
#ifdef CFG_ENV_HOST
uint32_t host_id;
drvError_t ret = halGetHostID(&host_id);
if (ret != DRV_ERROR_NONE) {
sched_err("drv update host_id failed. (ret=%d)\n", ret);
return false;
}
if (dev_id == host_id) {
return true;
}
#endif
#endif
(void)dev_id;
return false;
}
int esched_device_check(unsigned int dev_id)
{
if ((dev_id >= ESCHED_LOGIC_DEV_NUM) && (!esched_is_host_virtual_dev(dev_id))) {
return DRV_ERROR_INVALID_DEVICE;
}
return DRV_ERROR_NONE;
}
void esched_clear_grp_info(unsigned int dev_id)
{
(void)memset_s((void *)sched_grp[dev_id].info, sizeof(sched_grp[dev_id].info),
0, sizeof(sched_grp[dev_id].info));
}
STATIC void esched_init_global_fork(unsigned int dev_id, int fd)
{
(void)pthread_mutex_lock(&g_esched_init_mutex);
if (sched_dev_fd[dev_id] == fd) {
(void)memset_s((void *)&sched_dev_fd[dev_id], sizeof(int32_t), 0, sizeof(int32_t));
}
(void)pthread_mutex_unlock(&g_esched_init_mutex);
}
#ifndef EMU_ST
STATIC int esched_open(const char *char_dev_name)
{
return open(char_dev_name, O_RDWR | O_NONBLOCK | O_CLOEXEC);
}
STATIC int esched_close(int fd)
{
return close(fd);
}
STATIC int esched_ioctl(int fd, uint32_t cmd, void *para)
{
return ioctl(fd, cmd, para);
}
#endif
void esched_query_sync_msg_trace(uint32_t dev_id, struct event_summary *event, uint32_t grp_id, uint32_t thread_id)
{
drvError_t ret;
struct sched_ioctl_para_trace para;
if ((dev_id >= ESCHED_DEV_NUM) || (grp_id < SCHED_MAX_DEFAULT_GRP_NUM)) {
sched_err("input param is invalid. (dev_id=%u; grp_id=%u; thread_id=%u)\n", dev_id, grp_id, thread_id);
return;
}
para.input.dev_id = (unsigned int)dev_id;
para.input.dst_pid = (unsigned int)event->pid;
para.input.dst_gid = event->grp_id;
para.input.dst_engine = event->dst_engine;
para.input.event_id = event->event_id;
para.input.subevent_id = event->subevent_id;
para.input.msg = *((struct sync_msg_info *)event->msg);
ret = esched_dev_ioctl(dev_id, SCHED_QUERY_SYNC_MSG_TRACE, ¶);
if (ret != DRV_ERROR_NONE) {
sched_err("query trace fail. (ret=%d; dev_id=%u; grp_id=%u; thread_id=%u)\n", ret, dev_id, grp_id, thread_id);
return;
}
sched_run_info("trace event cfg. (dev_id=%u; grp_id=%u; thread_id=%u; event_id=%u; subevent_id=%u; pid=%d; dst_engine=%d).\n",
dev_id, grp_id, thread_id, event->event_id, event->subevent_id, event->pid, event->dst_engine);
sched_run_info("show trace info. (src_submit_user=%llu; src_submit_kernel=%llu; dst_publish=%llu; dst_wait_start=%llu; dst_wait_end=%llu;"
" dst_submit_usr=%llu; dst_rsp_submit_kernel=%llu; src_publish=%llu; src_wait_start=%llu; src_wait_end=%llu).\n",
para.trace.src_submit_user_timestamp, para.trace.src_submit_kernel_timestamp, para.trace.dst_publish_timestamp,
para.trace.dst_wait_start_timestamp, para.trace.dst_wait_end_timestamp, para.trace.dst_submit_user_timestamp,
para.trace.dst_submit_kernel_timestamp, para.trace.src_publish_timestamp, para.trace.src_wait_start_timestamp,
para.trace.src_wait_end_timestamp);
return;
}
drvError_t halEschedRegisterFinishFunc(unsigned int grpId, unsigned int event_id,
void (*finishFunc)(unsigned int devId, unsigned int grpId, unsigned int event_id, unsigned int subevent_id))
{
if ((grpId >= SCHED_MAX_GRP_NUM) || (event_id >= EVENT_MAX_NUM)) {
sched_err("The value of grpId or event_id is out of range. (grpId=%u; event_id=%u)\n", grpId, event_id);
return DRV_ERROR_SCHED_PARA_ERR;
}
esched_finish_func[grpId][event_id] = finishFunc;
return DRV_ERROR_NONE;
}
drvError_t esched_register_finish_func_ex(unsigned int grp_id, unsigned int event_id,
void (*finish_func)(unsigned int dev_id, unsigned int grp_id, esched_event_info event_info))
{
if ((grp_id >= SCHED_MAX_GRP_NUM) || (event_id >= EVENT_MAX_NUM)) {
sched_err("The value of grp_id or event_id is out of range. (grp_id=%u; event_id=%u)\n", grp_id, event_id);
return DRV_ERROR_SCHED_PARA_ERR;
}
esched_finish_func_ex[grp_id][event_id] = finish_func;
return DRV_ERROR_NONE;
}
static inline bool esched_thread_info_is_match(esched_thread_info *thread_info,
unsigned int dev_id, unsigned int grp_id, unsigned int thread_id)
{
return ((thread_info->dev_id == dev_id) &&
(thread_info->gid == grp_id) &&
(thread_info->tid == thread_id));
}
static inline void esched_save_thread_info(esched_thread_wait_info *thread_wait_info,
uint32_t dev_id, uint32_t grp_id, uint32_t thread_id)
{
thread_wait_info->thread_info.dev_id = dev_id;
thread_wait_info->thread_info.gid = grp_id;
thread_wait_info->thread_info.tid = thread_id;
}
static inline esched_thread_wait_info_head *esched_get_thread_wait_info_list_head(void)
{
if (esched_thread_key_flag == false) {
sched_err("No esched_thread_key was created!\n");
return NULL;
}
return (esched_thread_wait_info_head *)pthread_getspecific(esched_thread_key);
}
static inline void esched_update_cur_thread_info(uint32_t grp_id, uint32_t thread_id)
{
esched_thread_wait_info_head *wait_info_head = esched_get_thread_wait_info_list_head();
if (wait_info_head == NULL) {
return;
}
wait_info_head->cur_thread_info.gid = grp_id;
wait_info_head->cur_thread_info.tid = thread_id;
}
static inline unsigned int esched_get_cur_group_id(void)
{
esched_thread_wait_info_head *wait_info_head = esched_get_thread_wait_info_list_head();
if (wait_info_head == NULL) {
return SCHED_INVALID_GID;
}
return wait_info_head->cur_thread_info.gid;
}
static inline unsigned int esched_get_cur_thread_id(void)
{
esched_thread_wait_info_head *wait_info_head = esched_get_thread_wait_info_list_head();
if (wait_info_head == NULL) {
return SCHED_INVALID_TID;
}
return wait_info_head->cur_thread_info.tid;
}
static void esched_create_thread_wait_info_list_head(void)
{
esched_thread_wait_info_head *wait_info_head = NULL;
int ret;
if (esched_thread_key_flag == false) {
sched_err("No esched_thread_key was created!\n");
return;
}
wait_info_head = (esched_thread_wait_info_head *)malloc(sizeof(esched_thread_wait_info_head));
if (wait_info_head == NULL) {
sched_err("malloc list_head failed.\n");
return;
}
INIT_LIST_HEAD(&wait_info_head->list_head);
wait_info_head->cur_thread_info.gid = SCHED_INVALID_GID;
wait_info_head->cur_thread_info.tid = SCHED_INVALID_TID;
ret = pthread_setspecific(esched_thread_key, (void*)wait_info_head);
if (ret != 0) {
sched_err("set esched_thread_key specific failed.\n");
free(wait_info_head);
return;
}
}
static void esched_thread_destructor(void *key)
{
esched_thread_wait_info_head *wait_info_head = NULL;
struct list_head *pos = NULL, *n = NULL;
esched_thread_wait_info *thread_wait_info = NULL;
wait_info_head = (esched_thread_wait_info_head *)key;
if (wait_info_head == NULL) {
return;
}
list_for_each_safe(pos, n, &wait_info_head->list_head) {
thread_wait_info = list_entry(pos, esched_thread_wait_info, list);
drv_user_list_del(&thread_wait_info->list);
sched_debug("Free thread wait info node(dev_id=%u; gid=%u; tid=%u).\n",
thread_wait_info->thread_info.dev_id, thread_wait_info->thread_info.gid,
thread_wait_info->thread_info.tid);
free(thread_wait_info);
}
free(wait_info_head);
}
static void esched_create_thread_key_once(void)
{
int ret;
ret = pthread_key_create(&esched_thread_key, esched_thread_destructor);
if (ret != 0) {
sched_err("pthread_key_create failed. (ret=%d)\n", ret);
return;
}
esched_thread_key_flag = true;
}
STATIC esched_thread_wait_info* esched_find_wait_info(unsigned int dev_id, unsigned int grp_id, unsigned int thread_id)
{
esched_thread_wait_info_head *wait_info_head = NULL;
struct list_head *pos = NULL, *n = NULL;
esched_thread_wait_info *thread_wait_info = NULL;
wait_info_head = esched_get_thread_wait_info_list_head();
if (wait_info_head == NULL) {
return NULL;
}
list_for_each_safe(pos, n, &wait_info_head->list_head) {
thread_wait_info = list_entry(pos, esched_thread_wait_info, list);
if (esched_thread_info_is_match(&thread_wait_info->thread_info, dev_id, grp_id, thread_id) == true) {
return thread_wait_info;
}
}
return NULL;
}
STATIC esched_thread_wait_info* esched_create_wait_info(unsigned int dev_id, unsigned int grp_id, unsigned int thread_id)
{
esched_thread_wait_info_head *wait_info_head = NULL;
esched_thread_wait_info *thread_wait_info = NULL;
wait_info_head = esched_get_thread_wait_info_list_head();
if (wait_info_head == NULL) {
sched_err("No wait info list.\n");
return NULL;
}
thread_wait_info = (esched_thread_wait_info *)malloc(sizeof(esched_thread_wait_info));
if (thread_wait_info == NULL) {
sched_err("malloc esched_thread_wait_info failed.\n");
return NULL;
}
esched_save_thread_info(thread_wait_info, dev_id, grp_id, thread_id);
drv_user_list_add_head(&thread_wait_info->list, &wait_info_head->list_head);
sched_debug("Add thread wait info node(dev_id=%u; gid=%u; tid=%u).\n",
dev_id, grp_id, thread_id);
return thread_wait_info;
}
STATIC void esched_finish_call_back(unsigned int dev_id, unsigned int grp_id, unsigned int thread_id)
{
esched_thread_wait_info *thread_wait_info;
thread_wait_info = esched_find_wait_info(dev_id, grp_id, thread_id);
if (thread_wait_info == NULL) {
return;
}
if (thread_wait_info->event_valid == 0) {
return;
}
if (esched_finish_func[grp_id][thread_wait_info->event_info.event_id] != NULL) {
esched_finish_func[grp_id][thread_wait_info->event_info.event_id](dev_id,
grp_id, thread_wait_info->event_info.event_id, thread_wait_info->event_info.subevent_id);
}
if (esched_finish_func_ex[grp_id][thread_wait_info->event_info.event_id] != NULL) {
esched_finish_func_ex[grp_id][thread_wait_info->event_info.event_id](dev_id,
grp_id, thread_wait_info->event_info);
}
thread_wait_info->event_valid = 0;
sched_debug("Called the finish func.(dev_id=%u; gid=%u; tid=%u; event_id=%u; subevent_id=%u).\n", dev_id, grp_id,
thread_id, thread_wait_info->event_info.event_id, thread_wait_info->event_info.subevent_id);
}
static void esched_save_wait_info(uint32_t dev_id, uint32_t thread_id, struct sched_ioctl_para_wait para)
{
esched_thread_wait_info *thread_wait_info = NULL;
esched_update_cur_thread_info(para.event.gid, thread_id);
thread_wait_info = esched_find_wait_info(dev_id, para.event.gid, thread_id);
if (thread_wait_info == NULL) {
thread_wait_info = esched_create_wait_info(dev_id, para.event.gid, thread_id);
if (thread_wait_info == NULL) {
sched_err("Create new wait info failed. (dev_id=%u; grp_id=%u; tid=%u)\n", dev_id, para.event.gid, thread_id);
return;
}
}
thread_wait_info->event_info.event_id = para.event.event_id;
thread_wait_info->event_info.subevent_id = para.event.subevent_id;
thread_wait_info->event_info.msg_len = para.event.msg_len;
(void)memcpy_s(thread_wait_info->event_info.msg, EVENT_MAX_MSG_LEN, para.input.msg, para.event.msg_len);
thread_wait_info->event_valid = 1;
}
#if (!defined (USER_EVENT_SCHED_UT)) && (!defined (EMU_ST))
drvError_t register_esched_trace_record_func(unsigned int grp_id, unsigned int event_id,
void (*finish_func)(unsigned int grp_id, unsigned int event_id, unsigned int subevent_id,
sched_trace_time_info *sched_trace_time_info))
{
if ((grp_id >= SCHED_MAX_GRP_NUM) || (event_id >= EVENT_MAX_NUM)) {
sched_err("The value of grp_id or event_id is out of range. (grp_id=%u; event_id=%u)\n", grp_id, event_id);
return DRV_ERROR_SCHED_PARA_ERR;
}
esched_trace_record_func[grp_id][event_id] = finish_func;
return DRV_ERROR_NONE;
}
#endif
STATIC void esched_trace_record_call_back(unsigned int grp_id, struct sched_subscribed_event *event,
uint64_t wait_start_timestamp)
{
#if (!defined (USER_EVENT_SCHED_UT)) && (!defined (EMU_ST))
sched_trace_time_info sched_trace_time_info_ins;
unsigned int event_id = event->event_id;
unsigned int subevent_id = event->subevent_id;
if (event_id != EVENT_QUEUE_ENQUEUE) {
return;
}
if (grp_id >= SCHED_MAX_GRP_NUM) {
sched_err("Invalid param. (grp_id=%u)\n", grp_id);
return;
}
if (esched_trace_record_func[grp_id][event_id] == NULL) {
return;
}
sched_trace_time_info_ins.time_stamp[SCHED_TRACE_TIME_THREAD_WAIT] = wait_start_timestamp;
sched_trace_time_info_ins.time_stamp[SCHED_TRACE_TIME_EVENT_PUBLISH_USER] = event->publish_user_timestamp;
sched_trace_time_info_ins.time_stamp[SCHED_TRACE_TIME_EVENT_PUBLISH_KERNEL] = event->publish_kernel_timestamp;
sched_trace_time_info_ins.time_stamp[SCHED_TRACE_TIME_EVENT_PUBLISH_FINISH] = event->publish_finish_timestamp;
sched_trace_time_info_ins.time_stamp[SCHED_TRACE_TIME_PUBLISH_WAKEUP] = event->publish_wakeup_timestamp;
sched_trace_time_info_ins.time_stamp[SCHED_TRACE_TIME_THREAD_WAKED] = event->subscribe_timestamp;
esched_trace_record_func[grp_id][event_id](grp_id, event_id, subevent_id, &sched_trace_time_info_ins);
#endif
}
#ifdef CFG_FEATURE_EXTERNAL_CDEV
static int32_t esched_ex_dev_open(unsigned int dev_id, int fd)
{
struct davinci_intf_open_arg arg;
int32_t ret;
ret = uda_get_udevid_by_devid_ex(dev_id, (unsigned int *)&arg.device_id);
if (ret != DRV_ERROR_NONE) {
sched_err("Get phys failed. (devid=%u)\n", dev_id);
return DRV_ERROR_INVALID_DEVICE;
}
ret = strcpy_s(arg.module_name, DAVINIC_MODULE_NAME_MAX, DAVINCI_ESCHED_SUB_MODULE_NAME);
if (ret < 0) {
sched_err("Failed to invoke the strcpy_s. (ret=%d).\n", ret);
return ret;
}
ret = esched_ioctl(fd, DAVINCI_INTF_IOCTL_OPEN, &arg);
if (ret != 0) {
sched_err("Failed to invoke the INTF_IOCTL_OPEN. (ret=%d)\n", ret);
return ret;
}
return 0;
}
static void esched_ex_dev_close(unsigned int dev_id, int fd)
{
struct davinci_intf_open_arg arg;
int32_t ret;
ret = uda_get_udevid_by_devid_ex(dev_id, (unsigned int *)&arg.device_id);
if (ret != DRV_ERROR_NONE) {
sched_err("Get phys failed. (devid=%u)\n", dev_id);
return;
}
ret = strcpy_s(arg.module_name, DAVINIC_MODULE_NAME_MAX, DAVINCI_ESCHED_SUB_MODULE_NAME);
if (ret < 0) {
sched_err("Failed to invoke the strcpy_s. (ret=%d).\n", ret);
return;
}
ret = esched_ioctl(fd, DAVINCI_INTF_IOCTL_CLOSE, &arg);
if (ret != 0) {
sched_err("Failed to invoke the INTF_IOCTL_CLOSE. (ret=%d)\n", ret);
}
}
#else
void esched_init_all_fd(int fd)
{
int i;
for (i = 0; i < ESCHED_DEV_NUM; i++) {
sched_dev_fd[i] = fd;
}
}
void esched_uninit_all_fd(void)
{
int i;
for (i = 0; i < ESCHED_DEV_NUM; i++) {
sched_dev_fd[i] = SCHED_DEV_FD_CLOSED;
}
}
#endif
STATIC int32_t esched_dev_init(unsigned int dev_id)
{
int32_t ret = 0;
int fd;
if (esched_device_check(dev_id) != 0) {
sched_err("The dev_id is invalid. (dev_id=%u; max=%u)\n", dev_id, ESCHED_LOGIC_DEV_NUM);
return DRV_ERROR_INVALID_DEVICE;
}
(void)pthread_mutex_lock(&g_esched_init_mutex);
if (sched_dev_fd[dev_id] == SCHED_DEV_FD_CLOSED) {
(void)pthread_mutex_unlock(&g_esched_init_mutex);
return DRV_ERROR_SCHED_PROCESS_EXIT;
}
if (sched_dev_fd[dev_id] > 0) {
(void)pthread_mutex_unlock(&g_esched_init_mutex);
return 0;
}
fd = esched_open(SCHED_CHAR_DEV_FULL_NAME);
if (fd < 0) {
sched_err("Failed to open device. (ret=%d)\n", errno);
(void)pthread_mutex_unlock(&g_esched_init_mutex);
return DRV_ERROR_INVALID_DEVICE;
}
#ifdef CFG_FEATURE_EXTERNAL_CDEV
ret = esched_ex_dev_open(dev_id, fd);
if (ret != 0) {
(void)pthread_mutex_unlock(&g_esched_init_mutex);
esched_close(fd);
return ret;
}
#endif
ret = esched_init_sched_cpu_num(dev_id, fd);
if (ret != 0) {
sched_err("Failed to init sched cpu num.(dev_id=%u)\n", dev_id);
(void)pthread_mutex_unlock(&g_esched_init_mutex);
#ifdef CFG_FEATURE_EXTERNAL_CDEV
esched_ex_dev_close(dev_id, fd);
#endif
(void)esched_close(fd);
return ret;
}
#ifdef CFG_FEATURE_EXTERNAL_CDEV
sched_dev_fd[dev_id] = fd;
#else
esched_init_all_fd(fd);
#endif
(void)pthread_mutex_unlock(&g_esched_init_mutex);
return ret;
}
STATIC void esched_dev_close(unsigned int dev_id)
{
if (sched_dev_fd[dev_id] <= 0) {
return;
}
#ifdef CFG_FEATURE_EXTERNAL_CDEV
esched_ex_dev_close(dev_id, sched_dev_fd[dev_id]);
#endif
(void)esched_close(sched_dev_fd[dev_id]);
#ifdef CFG_FEATURE_EXTERNAL_CDEV
sched_dev_fd[dev_id] = SCHED_DEV_FD_CLOSED;
#else
esched_uninit_all_fd();
#endif
}
int esched_dev_ioctl(unsigned int dev_id, unsigned int cmd, void *para)
{
int ret;
int fd;
while (1) {
ret = esched_dev_init(dev_id);
if (ret != 0) {
return ret;
}
fd = sched_dev_fd[dev_id];
if (fd == 0) {
continue;
}
ret = esched_ioctl(fd, cmd, para);
if (ret == DRV_ERROR_FILE_OPS) {
esched_init_global_fork(dev_id, fd);
continue;
}
if (ret != 0) {
esched_share_log_read();
}
break;
}
return ret;
}
drvError_t halEschedAttachDevice(uint32_t devId)
{
struct sched_ioctl_para_attach para_attach;
int ret;
ret = esched_attach_device_inner(devId, ¶_attach);
if (ret == DRV_ERROR_NONE) {
(void)pthread_once(&esched_thread_key_init, esched_create_thread_key_once);
}
return ret;
}
drvError_t halEschedDettachDevice(uint32_t devId)
{
struct sched_ioctl_para_detach para_detach;
int ret;
ret = esched_dettach_device_inner(devId, ¶_detach);
return ret;
}
static drvError_t esched_wait_event_comm(esched_thread_info *wait_info, int32_t timeout, struct event_info *event,
esched_event_buffer *event_buffer)
{
drvError_t ret;
struct sched_ioctl_para_wait para;
uint64_t wait_start_timestamp = esched_get_cur_cpu_timestamp();
esched_thread_wait_info_head *wait_info_head = NULL;
wait_info_head = esched_get_thread_wait_info_list_head();
if (wait_info_head == NULL) {
esched_create_thread_wait_info_list_head();
}
esched_finish_call_back(wait_info->dev_id, wait_info->gid, wait_info->tid);
para.input.dev_id = wait_info->dev_id;
para.input.grp_id = wait_info->gid;
para.input.thread_id = wait_info->tid;
para.input.timeout = (timeout < 0) ? SCHED_WAIT_TIMEOUT_ALWAYS_WAIT : timeout;
para.input.msg_len = event_buffer->msg_len;
para.input.msg = event_buffer->msg;
do {
ret = esched_dev_ioctl(wait_info->dev_id, SCHED_WAIT_EVENT_ID, ¶);
} while (ret == DRV_ERROR_WAIT_INTERRUPT);
if (ret != DRV_ERROR_NONE) {
return ret;
}
event->comm.pid = para.event.pid;
event->comm.host_pid = para.event.host_pid;
event->comm.grp_id = para.event.gid;
event->comm.event_id = (EVENT_ID)para.event.event_id;
event->comm.subevent_id = para.event.subevent_id;
event->priv.msg_len = para.event.msg_len;
event->comm.submit_timestamp = para.event.publish_user_timestamp;
event->comm.sched_timestamp = para.event.subscribe_timestamp;
esched_save_wait_info(wait_info->dev_id, wait_info->tid, para);
esched_trace_record_call_back(wait_info->gid, ¶.event, wait_start_timestamp);
return DRV_ERROR_NONE;
}
drvError_t esched_wait_event_ex(uint32_t dev_id, uint32_t grp_id,
uint32_t thread_id, int32_t timeout, struct event_info *event)
{
esched_thread_info wait_info = {dev_id, grp_id, thread_id};
esched_event_buffer *event_buffer = NULL;
if (event == NULL) {
sched_err("Event is NULL. (dev_id=%u; grp_id=%u; thread_id=%u)\n", dev_id, grp_id, thread_id);
return DRV_ERROR_PARA_ERROR;
}
event_buffer = (esched_event_buffer *)event->priv.msg;
return esched_wait_event_comm(&wait_info, timeout, event, event_buffer);
}
drvError_t halEschedWaitEvent(uint32_t devId, uint32_t grpId,
uint32_t threadId, int32_t timeout, struct event_info *event)
{
esched_thread_info wait_info = {devId, grpId, threadId};
esched_event_buffer event_buffer;
if (event == NULL) {
sched_err("Event is NULL. (devId=%u; grpId=%u; threadId=%u)\n", devId, grpId, threadId);
return DRV_ERROR_PARA_ERROR;
}
event_buffer.msg_len = EVENT_MAX_MSG_LEN;
event_buffer.msg = event->priv.msg;
return esched_wait_event_comm(&wait_info, timeout, event, &event_buffer);
}
static drvError_t esched_thread_swapout_common(unsigned int dev_id, unsigned int grp_id, unsigned int thread_id, int timeout)
{
struct sched_ioctl_para_wait para = {0};
drvError_t ret;
unsigned int grp_id_ = grp_id;
unsigned int thread_id_ = thread_id;
GROUP_TYPE type;
if (esched_need_judge_thread_id()) {
if (esched_get_cur_thread_id() == SCHED_INVALID_TID) {
return DRV_ERROR_NONE;
}
}
if ((grp_id_ == SCHED_INVALID_GID) && (thread_id_ == SCHED_INVALID_TID)) {
grp_id_ = esched_get_cur_group_id();
thread_id_ = esched_get_cur_thread_id();
}
para.input.dev_id = dev_id;
para.input.grp_id = grp_id_;
para.input.thread_id = thread_id_;
para.input.timeout = timeout;
esched_finish_call_back(dev_id, grp_id_, thread_id_);
ret = esched_query_grp_type(dev_id, grp_id_, &type);
if (ret != 0) {
sched_err("Query grp type failed. (dev_id=%u; grp_id=%u; thread_id=%u)\n", dev_id, grp_id_, thread_id_);
return DRV_ERROR_PARA_ERROR;
}
if (type == GRP_TYPE_BIND_CP_CPU) {
esched_update_cur_thread_info(SCHED_INVALID_GID, SCHED_INVALID_TID);
return DRV_ERROR_NONE;
}
ret = esched_dev_ioctl(dev_id, SCHED_WAIT_EVENT_ID, ¶);
ret = (ret == DRV_ERROR_NO_EVENT) ? 0 : ret;
if (ret == 0) {
esched_update_cur_thread_info(SCHED_INVALID_GID, SCHED_INVALID_TID);
}
return ret;
}
drvError_t halEschedThreadSwapout(unsigned int devId, unsigned int grpId, unsigned int threadId)
{
drvError_t ret;
if (esched_support_thread_swap_out()) {
ret = esched_thread_swapout_common(devId, grpId, threadId, SCHED_WAIT_TIMEOUT_SWAPOUT);
return ret;
} else {
return DRV_ERROR_NOT_SUPPORT;
}
}
drvError_t halEschedThreadGiveup(unsigned int devId, unsigned int grpId, unsigned int threadId)
{
drvError_t ret;
if (esched_support_thread_giveup()) {
ret = esched_thread_swapout_common(devId, grpId, threadId, SCHED_WAIT_TIMEOUT_GIVEUP);
return ret;
} else {
return DRV_ERROR_NOT_SUPPORT;
}
}
drvError_t halEschedGetEvent(uint32_t devId, uint32_t grpId, uint32_t threadId,
EVENT_ID eventId, struct event_info *event)
{
drvError_t ret;
struct sched_ioctl_para_get_event para;
if (event == NULL) {
sched_err("The variable event is NULL. (devId=%u; grpId=%u; threadId=%u)\n", devId, grpId, threadId);
return DRV_ERROR_PARA_ERROR;
}
para.input.dev_id = devId;
para.input.grp_id = grpId;
para.input.thread_id = threadId;
para.input.event_id = (uint32_t)eventId;
para.input.msg_len = EVENT_MAX_MSG_LEN;
para.input.msg = event->priv.msg;
ret = esched_dev_ioctl(devId, SCHED_GET_EXACT_EVENT_ID, ¶);
if (ret != 0) {
return ret;
}
event->comm.pid = para.event.pid;
event->comm.host_pid = -1;
event->comm.grp_id = para.event.gid;
event->comm.event_id = (EVENT_ID)para.event.event_id;
event->comm.subevent_id = para.event.subevent_id;
event->priv.msg_len = para.event.msg_len;
event->comm.submit_timestamp = para.event.publish_user_timestamp;
event->comm.sched_timestamp = esched_get_cur_cpu_timestamp();
return DRV_ERROR_NONE;
}
STATIC drvError_t esched_submit_event_comm(uint32_t dev_id, struct event_summary *event,
unsigned int tid, unsigned int dst_dev_id, unsigned int *event_num)
{
struct sched_ioctl_para_submit para;
struct timespec publish_timestamp;
int ret;
para.dev_id = dev_id;
para.event_info.dst_engine = event->dst_engine;
para.event_info.policy = (uint32_t)event->policy;
para.event_info.pid = event->pid;
para.event_info.gid = event->grp_id;
para.event_info.tid = tid;
para.event_info.event_id = (uint32_t)event->event_id;
para.event_info.subevent_id = event->subevent_id;
para.event_info.dst_devid = dst_dev_id;
para.event_info.msg_len = event->msg_len;
para.event_info.msg = event->msg;
para.event_info.event_num = *event_num;
para.event_info.publish_timestamp = esched_get_cur_cpu_timestamp();
(void)clock_gettime(CLOCK_MONOTONIC, &publish_timestamp);
para.event_info.publish_timestamp_of_day = (uint64_t)((publish_timestamp.tv_sec * USEC_PER_SEC) +
(publish_timestamp.tv_nsec / NSEC_PER_USEC));
ret = esched_dev_ioctl(dev_id, SCHED_SUBMIT_EVENT_ID, ¶);
*event_num = para.event_info.event_num;
return ret;
}
drvError_t halEschedSubmitEvent(uint32_t devId, struct event_summary *event)
{
unsigned int event_num = 1;
if (event == NULL) {
sched_err("The variable event is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
return esched_submit_event_comm(devId, event, SCHED_INVALID_TID, SCHED_INVALID_DEVID, &event_num);
}
static int esched_check_rsv_data(int *rsv_data, unsigned int len)
{
unsigned int i;
for (i = 0; i < len; i++) {
if (rsv_data[i] != 0) {
sched_err("The rsv data is invalid. (rsvIdx=%u)\n", i);
return DRV_ERROR_PARA_ERROR;
}
}
return DRV_ERROR_NONE;
}
static int esched_check_event_rsv_data(struct event_summary *events, unsigned int event_num)
{
unsigned int i;
int ret;
for (i = 0; i < event_num; i++) {
ret = esched_check_rsv_data(events[i].rsv, EVENT_SUMMARY_RSV);
if (ret != DRV_ERROR_NONE) {
sched_err("The rsv data is invalid. (event_idx=%u)\n", i);
return ret;
}
}
return DRV_ERROR_NONE;
}
DLLEXPORT drvError_t halEschedSubmitEventBatch(unsigned int devId, SUBMIT_FLAG flag,
struct event_summary *events, unsigned int event_num, unsigned int *succ_event_num)
{
int ret;
if (!esched_support_extern_interface()) {
sched_info("Not support yet.\n");
return DRV_ERROR_NOT_SUPPORT;
}
if (events == NULL) {
sched_err("The variable events is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
if (succ_event_num == NULL) {
sched_err("The variable success_event_num is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
if (flag != SHARED_EVENT_ENTRY) {
#ifndef EMU_ST
sched_warn("The flag is not support. (flag=%d)\n", flag);
#endif
return DRV_ERROR_NOT_SUPPORT;
}
if (flag == SHARED_EVENT_ENTRY) {
ret = esched_check_event_rsv_data(events, 1);
} else {
ret = esched_check_event_rsv_data(events, event_num);
}
if (ret != 0) {
sched_err("Failed to invoke the esched_check_event_rsv_data. (ret=%d)\n", ret);
return ret;
}
*succ_event_num = event_num;
return esched_submit_event_comm(devId, events, SCHED_INVALID_TID, SCHED_INVALID_DEVID, succ_event_num);
}
drvError_t halEschedSubmitEventToThread(uint32_t devId, struct event_summary *event)
{
unsigned int event_num = 1;
if (!esched_support_extern_interface()) {
return DRV_ERROR_NOT_SUPPORT;
}
if (event == NULL) {
sched_err("The variable event is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
if (event->tid == SCHED_INVALID_TID) {
sched_err("User specific tid not support. (tid=%u)\n", SCHED_INVALID_TID);
return DRV_ERROR_PARA_ERROR;
}
return esched_submit_event_comm(devId, event, event->tid, SCHED_INVALID_DEVID, &event_num);
}
drvError_t halEschedSubmitEventEx(uint32_t devId, uint32_t dstDevId, struct event_summary *event)
{
unsigned int event_num = 1;
if (event == NULL) {
sched_err("The variable event is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
return esched_submit_event_comm(devId, event, event->tid, dstDevId, &event_num);
}
drvError_t halEschedRegisterAckFunc(unsigned int grpId, EVENT_ID eventId,
void (*ackFunc)(unsigned int devId, unsigned int subevent_id, char *msg, unsigned int msgLen))
{
if (!esched_support_extern_interface()) {
sched_info("Not support yet.\n");
return DRV_ERROR_NOT_SUPPORT;
}
if ((grpId >= SCHED_MAX_GRP_NUM) || (eventId >= EVENT_MAX_NUM)) {
sched_err("The value of grpId or event_id is out of range. (grpId=%u; event_id=%u)\n",
grpId, (unsigned int)eventId);
return DRV_ERROR_SCHED_PARA_ERR;
}
esched_ack_func[grpId][eventId] = ackFunc;
return DRV_ERROR_NONE;
}
drvError_t halEschedAckEvent(uint32_t devId, EVENT_ID eventId, uint32_t subeventId,
char *msg, uint32_t msgLen)
{
struct sched_ioctl_para_ack para;
unsigned int cur_grp_id = esched_get_cur_group_id();
if (eventId >= EVENT_MAX_NUM) {
return DRV_ERROR_PARA_ERROR;
}
if ((cur_grp_id != SCHED_INVALID_GID) && (esched_ack_func[cur_grp_id][eventId] != NULL)) {
esched_ack_func[cur_grp_id][eventId](devId, subeventId, msg, msgLen);
return DRV_ERROR_NONE;
}
para.dev_id = devId;
para.event_id = (uint32_t)eventId;
para.subevent_id = subeventId;
para.msg_len = msgLen;
para.msg = msg;
return esched_dev_ioctl(devId, SCHED_ACK_EVENT_ID, ¶);
}
drvError_t halEschedSubscribeEvent(uint32_t devId, uint32_t grpId,
uint32_t threadId, u64 eventBitmap)
{
struct sched_ioctl_para_subscribe para;
para.dev_id = devId;
para.gid = grpId;
para.tid = threadId;
para.event_bitmap = eventBitmap;
return esched_dev_ioctl(devId, SCHED_THREAD_SUBSCRIBE_EVENT_ID, ¶);
}
drvError_t halEschedSetGrpEventQos(unsigned int devId, unsigned int grpId,
EVENT_ID eventId, struct event_sched_grp_qos *qos)
{
struct sched_ioctl_para_set_event_max_num para;
if (qos == NULL) {
sched_err("The variable qos is NULL. (devId=%u; grpId=%u; eventId=%u)\n", devId, grpId, (unsigned int)eventId);
return DRV_ERROR_PARA_ERROR;
}
para.dev_id = devId;
para.gid = grpId;
para.event_id = (uint32_t)eventId;
para.max_num = qos->maxNum;
return esched_dev_ioctl(devId, SCHED_GRP_SET_EVENT_MAX_NUM, ¶);
}
static int esched_create_grp(uint32_t dev_id, unsigned int grp_id, struct esched_grp_para *grp_para)
{
struct sched_ioctl_para_add_grp para;
int ret;
para.dev_id = dev_id;
para.gid = grp_id;
para.sched_mode = (uint32_t)grp_para->type;
para.thread_num = grp_para->threadNum;
ret = strcpy_s(para.grp_name, EVENT_MAX_GRP_NAME_LEN, grp_para->grp_name);
if (ret != 0) {
sched_err("Failed to invoke strcpy_s. (dev_id=%u)\n", dev_id);
return DRV_ERROR_INNER_ERR;
}
ret = esched_dev_ioctl(dev_id, SCHED_PROC_ADD_GRP_ID, ¶);
if (ret != DRV_ERROR_NONE) {
return ret;
}
sched_grp[dev_id].info[grp_id].gid = grp_id;
sched_grp[dev_id].info[grp_id].type = grp_para->type;
sched_info("Esched create grp success. (dev_id=%u; gid=%u; sched_mode=%u; grpName=%s)\n",
dev_id, grp_id, para.sched_mode, para.grp_name);
return ret;
}
drvError_t esched_create_extend_grp(uint32_t dev_id, unsigned int grp_id, struct esched_grp_para *grp_para)
{
if (grp_id >= SCHED_MAX_DEFAULT_GRP_NUM) {
return DRV_ERROR_NOT_SUPPORT;
}
(void)memset_s(grp_para->grp_name, EVENT_MAX_GRP_NAME_LEN, 0, EVENT_MAX_GRP_NAME_LEN);
return esched_create_grp(dev_id, grp_id, grp_para);
}
static void esched_grp_name_print(uint32_t dev_id)
{
unsigned int i;
for (i = SCHED_MAX_DEFAULT_GRP_NUM; i < SCHED_MAX_GRP_NUM; i++) {
if (sched_grp[dev_id].info[i].type == GRP_TYPE_UNINIT) {
break;
}
sched_info("Show detail. (gid=%u; grpName=%s)\n", sched_grp[dev_id].info[i].gid,
sched_grp[dev_id].info[i].grp_name);
}
}
static int esched_check_grp_name(uint32_t dev_id, const char *name)
{
unsigned int i;
for (i = SCHED_MAX_DEFAULT_GRP_NUM; i < SCHED_MAX_GRP_NUM; i++) {
if (sched_grp[dev_id].info[i].type == GRP_TYPE_UNINIT) {
break;
}
if (strcmp(name, sched_grp[dev_id].info[i].grp_name) == 0) {
sched_err("Grp name reused. (grp_name=%s; i=%u)\n", name, i);
esched_grp_name_print(dev_id);
return DRV_ERROR_REPEATED_USERD;
}
}
return 0;
}
static int esched_alloc_grp_id(uint32_t dev_id, uint32_t *gid)
{
unsigned int i;
for (i = SCHED_MAX_DEFAULT_GRP_NUM; i < SCHED_MAX_GRP_NUM; i++) {
if (sched_grp[dev_id].info[i].type == GRP_TYPE_UNINIT) {
*gid = i;
return 0;
}
}
return DRV_ERROR_NO_GROUP;
}
drvError_t halEschedCreateGrp(uint32_t devId, uint32_t grpId, GROUP_TYPE type)
{
struct esched_grp_para grp_para;
if ((esched_device_check(devId) != 0) || (grpId >= SCHED_MAX_DEFAULT_GRP_NUM)) {
sched_err("The devId or grpId is invalid. (devId=%u; max=%u; grpId=%u; max=%u)\n",
devId, ESCHED_LOGIC_DEV_NUM, grpId, SCHED_MAX_DEFAULT_GRP_NUM);
return DRV_ERROR_PARA_ERROR;
}
grp_para.type = type;
grp_para.threadNum = SCHED_DEFAULT_THREAD_NUM_IN_GRP;
(void)memset_s(grp_para.grp_name, EVENT_MAX_GRP_NAME_LEN, 0, EVENT_MAX_GRP_NAME_LEN);
return esched_create_grp(devId, grpId, &grp_para);
}
drvError_t halEschedCreateGrpEx(uint32_t devId, struct esched_grp_para *grpPara, unsigned int *grpId)
{
int ret;
unsigned int alloc_grp_id;
if ((esched_device_check(devId) != 0) || (grpPara == NULL) || (grpId == NULL)) {
sched_err("Invalid para. (devId=%u; grpPara=%u; grpId=%u)\n", devId, grpPara == NULL ? 1 : 0,
grpId == NULL ? 1 : 0);
return DRV_ERROR_PARA_ERROR;
}
if ((strnlen(grpPara->grp_name, EVENT_MAX_GRP_NAME_LEN) == 0) ||
(strnlen(grpPara->grp_name, EVENT_MAX_GRP_NAME_LEN) >= EVENT_MAX_GRP_NAME_LEN)) {
sched_err("Invalid grp name. (grp_name_len=%u)\n",
(unsigned int)strnlen(grpPara->grp_name, EVENT_MAX_GRP_NAME_LEN));
return DRV_ERROR_PARA_ERROR;
}
if (esched_check_rsv_data(grpPara->rsv, ESCHED_GRP_PARA_RSV) != 0) {
sched_err("The rsv data is invalid. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
(void)pthread_mutex_lock(&(sched_grp[devId].mutex));
ret = esched_check_grp_name(devId, grpPara->grp_name);
if (ret) {
(void)pthread_mutex_unlock(&(sched_grp[devId].mutex));
return ret;
}
ret = esched_alloc_grp_id(devId, &alloc_grp_id);
if (ret) {
(void)pthread_mutex_unlock(&(sched_grp[devId].mutex));
return ret;
}
ret = strcpy_s(sched_grp[devId].info[alloc_grp_id].grp_name, EVENT_MAX_GRP_NAME_LEN, grpPara->grp_name);
if (ret != 0) {
sched_err("Failed to invoke strcpy_s. (devId=%u)\n", devId);
(void)pthread_mutex_unlock(&(sched_grp[devId].mutex));
return DRV_ERROR_INNER_ERR;
}
ret = esched_create_grp(devId, alloc_grp_id, grpPara);
if (ret == 0) {
*grpId = alloc_grp_id;
}
(void)pthread_mutex_unlock(&(sched_grp[devId].mutex));
return ret;
}
drvError_t halEschedQueryInfo(unsigned int devId, ESCHED_QUERY_TYPE type,
struct esched_input_info *inPut, struct esched_output_info *outPut)
{
struct sched_ioctl_para_query_info para;
if ((esched_device_check(devId) != 0) || (type >= QUERY_TYPE_MAX) || (inPut == NULL) || (outPut == NULL)) {
sched_err("Invalid para. (devId=%u; type=%u; inPut=%u; outPut=%u)\n",
devId, type, inPut == NULL ? 1 : 0, outPut == NULL ? 1 : 0);
return DRV_ERROR_PARA_ERROR;
}
para.dev_id = devId;
para.type = type;
para.dst_devid = SCHED_INVALID_DEVID;
para.input.inBuff = inPut->inBuff;
para.input.inLen = inPut->inLen;
para.output.outBuff = outPut->outBuff;
para.output.outLen = outPut->outLen;
return esched_dev_ioctl(devId, SCHED_QUERY_INFO, ¶);
}
drvError_t halEschedQueryInfoEx(unsigned int devId, unsigned int dstDevId, ESCHED_QUERY_TYPE type,
struct esched_input_info *inPut, struct esched_output_info *outPut)
{
struct sched_ioctl_para_query_info para;
if ((esched_device_check(devId) != 0) || (type >= QUERY_TYPE_MAX) || (inPut == NULL) || (outPut == NULL)) {
sched_err("Invalid para. (devId=%u; type=%u; inPut=%u; outPut=%u)\n",
devId, type, inPut == NULL ? 1 : 0, outPut == NULL ? 1 : 0);
return DRV_ERROR_PARA_ERROR;
}
para.dev_id = devId;
para.dst_devid = dstDevId;
para.type = type;
para.input.inBuff = inPut->inBuff;
para.input.inLen = inPut->inLen;
para.output.outBuff = outPut->outBuff;
para.output.outLen = outPut->outLen;
return esched_dev_ioctl(devId, SCHED_QUERY_INFO, ¶);
}
drvError_t esched_query_grp_type(uint32_t dev_id, uint32_t grp_id, GROUP_TYPE *type)
{
if ((esched_device_check(dev_id) != 0) || (grp_id >= SCHED_MAX_GRP_NUM)) {
sched_err("The dev_id or grp_id is invalid. (dev_id=%u; max=%u; grp_id=%u; max=%u)\n",
dev_id, ESCHED_LOGIC_DEV_NUM, grp_id, SCHED_MAX_GRP_NUM);
return DRV_ERROR_PARA_ERROR;
}
if (sched_grp[dev_id].info[grp_id].type == GRP_TYPE_UNINIT) {
sched_err("The group not created yet. (dev_id=%u; grp_id=%u)\n", dev_id, grp_id);
return DRV_ERROR_UNINIT;
}
*type = sched_grp[dev_id].info[grp_id].type;
return DRV_ERROR_NONE;
}
drvError_t halEschedSetPidPriority(uint32_t devId, SCHEDULE_PRIORITY priority)
{
struct sched_ioctl_para_set_proc_pri para;
para.dev_id = devId;
para.pri = (uint32_t)priority;
return esched_dev_ioctl(devId, SCHED_SET_PROCESS_PRIORITY_ID, ¶);
}
drvError_t halEschedSetEventPriority(uint32_t devId, EVENT_ID eventId, SCHEDULE_PRIORITY priority)
{
struct sched_ioctl_para_set_event_pri para;
para.dev_id = devId;
para.event_id = (uint32_t)eventId;
para.pri = (uint32_t)priority;
return esched_dev_ioctl(devId, SCHED_SET_EVENT_PRIORITY_ID, ¶);
}
#ifndef CFG_ENV_HOST
STATIC void esched_init_cpu_mask(struct sched_sched_cpu_mask *cpu_mask)
{
unsigned int i;
for (i = 0; i < SCHED_MASK_NUM; i++) {
cpu_mask->mask[i] = 0;
}
}
STATIC int32_t esched_set_sched_cpu_mask(unsigned long long *mask, unsigned int sched_cpu_start, unsigned int sched_cpu_num)
{
unsigned int i;
if ((sched_cpu_start + sched_cpu_num) > SCHED_MASK_BIT_NUM) {
sched_err("Invalid para. (sched_cpu_start=%u; sched_cpu_num=%u)\n", sched_cpu_start, sched_cpu_num);
return DRV_ERROR_INVALID_VALUE;
}
for (i = 0; i < sched_cpu_num; i++) {
*mask |= (0x1ULL << (i + sched_cpu_start));
}
return 0;
}
int32_t esched_init_device_sched_cpu_num(unsigned int dev_id, int fd)
{
struct sched_ioctl_para_cpu_info cpu_para;
drvCpuInfo_t cpu_info = {0};
uint32_t i, sched_cpu_start, sched_cpu_num;
drvError_t ret;
if (dev_id >= ESCHED_MAX_PHY_DEV_NUM) {
return DRV_ERROR_NONE;
}
sched_cpu_start = 0;
for (i = 0; i <= dev_id; i++) {
ret = drvGetCpuInfo(i, &cpu_info);
if (ret != DRV_ERROR_NONE) {
sched_err("Failed to invoke the drvGetCpuInfo. (dev=%u; ret=%d)\n", dev_id, (int)ret);
return (int)DRV_ERROR_SCHED_INNER_ERR;
}
if (cpu_info.ccpu_os_sched != 0) {
sched_cpu_start += cpu_info.ccpu_num;
}
if (cpu_info.dcpu_os_sched != 0) {
sched_cpu_start += cpu_info.dcpu_num;
}
if (i < dev_id) {
sched_cpu_start += cpu_info.aicpu_num;
sched_cpu_start += cpu_info.comcpu_num;
} else {
sched_cpu_num = cpu_info.aicpu_num + cpu_info.comcpu_num;
}
}
cpu_para.dev_id = dev_id;
esched_init_cpu_mask(&cpu_para.cpu_mask);
ret = esched_set_sched_cpu_mask(&cpu_para.cpu_mask.mask[0], sched_cpu_start, sched_cpu_num);
if (ret != DRV_ERROR_NONE) {
return ret;
}
ret = esched_ioctl(fd, SCHED_SET_SCHED_CPU_ID, &cpu_para);
if (ret != DRV_ERROR_NONE) {
sched_err("Failed to invoke the esched_dev_ioctl. (ret=%d)\n", (int)ret);
return (int)ret;
}
return 0;
}
#endif
drvError_t halEschedDumpEventTrace(uint32_t devId, char *buff, uint32_t buffLen, uint32_t *dataLen)
{
struct sched_ioctl_para_get_event_trace para;
drvError_t ret;
if (buff == NULL || dataLen == NULL) {
sched_err("The variable buff or dataLen is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
para.dev_id = devId;
para.buff = buff;
para.buff_len = buffLen;
para.data_len = 0;
ret = esched_dev_ioctl(devId, SCHED_GET_NODE_EVENT_TRACE, ¶);
if (ret != DRV_ERROR_NONE) {
sched_err("Ioctl return error. (ret=%d)\n", (int32_t)ret);
return ret;
}
*dataLen = para.data_len;
return DRV_ERROR_NONE;
}
drvError_t halEschedTraceRecord(uint32_t devId, const char *recordReason, const char *key)
{
struct sched_ioctl_para_trigger_sched_trace_record para;
size_t len;
int32_t ret;
if (recordReason == NULL || key == NULL) {
sched_err("The variable recordReason or key is NULL. (devId=%u)\n", devId);
return DRV_ERROR_PARA_ERROR;
}
para.dev_id = devId;
len = ((strnlen(recordReason, SCHED_STR_MAX_LEN) >= SCHED_STR_MAX_LEN) ?
SCHED_STR_MAX_LEN - 1 : strnlen(recordReason, SCHED_STR_MAX_LEN));
ret = strncpy_s(para.record_reason, SCHED_STR_MAX_LEN, recordReason, len);
if (ret != 0) {
#ifndef EMU_ST
sched_warn("Unable to invoke the strncpy_s to copy recordReason. (ret=%d)\n", ret);
#endif
}
len = ((strnlen(key, SCHED_STR_MAX_LEN) >= SCHED_STR_MAX_LEN) ?
SCHED_STR_MAX_LEN - 1 : strnlen(key, SCHED_STR_MAX_LEN));
ret = strncpy_s(para.key, SCHED_STR_MAX_LEN, key, len);
if (ret != 0) {
#ifndef EMU_ST
sched_warn("Unable to invoke the strncpy_s to copy key. (ret=%d)\n", ret);
#endif
}
para.record_reason[SCHED_STR_MAX_LEN - 1] = '\0';
para.key[SCHED_STR_MAX_LEN - 1] = '\0';
return esched_dev_ioctl(devId, SCHED_TRIGGER_SCHED_TRACE_RECORD_VALUE, ¶);
}
drvError_t esched_query_curr_sched_mode(unsigned int dev_id, unsigned int *sched_mode)
{
drvError_t ret;
struct sched_ioctl_para_query_sched_mode para;
if ((esched_device_check(dev_id) != 0) || (sched_mode == NULL)) {
sched_err("Invalid para. (dev_id=%u; sched_mode_ptr=%u)\n",
dev_id, sched_mode == NULL ? 1 : 0);
return DRV_ERROR_PARA_ERROR;
}
para.dev_id = dev_id;
ret = esched_dev_ioctl(dev_id, SCHED_QUERY_SCHED_MODE, ¶);
if (ret == 0) {
*sched_mode = para.sched_mode;
}
return DRV_ERROR_NONE;
}
#ifndef DRV_HOST
static __thread unsigned int g_sched_mode[ESCHED_DEV_NUM] = {[0 ... (ESCHED_DEV_NUM - 1)] = 0xff};
#endif
unsigned int esched_get_cpu_mode(uint32_t devid)
{
#ifdef DRV_HOST
(void)devid;
return 0;
#else
if (g_sched_mode[devid] != 0xff) {
return g_sched_mode[devid];
}
drvError_t ret;
unsigned int cpu_mode = 0;
ret = esched_query_curr_sched_mode(devid, &cpu_mode);
if (ret != DRV_ERROR_NONE) {
return 0;
}
g_sched_mode[devid] = cpu_mode;
return g_sched_mode[devid];
#endif
}
drvError_t esched_device_close_user(uint32_t devid, halDevCloseIn *in)
{
(void)in;
if (!esched_support_extern_interface()) {
return 0;
}
if (esched_device_check(devid) != 0) {
sched_err("The dev_id is invalid. (dev_id=%u; max=%u)\n", devid, ESCHED_LOGIC_DEV_NUM);
return DRV_ERROR_PARA_ERROR;
}
esched_clear_attach_refcnt(devid);
(void)pthread_mutex_lock(&(sched_grp[devid].mutex));
(void)memset_s((void *)sched_grp[devid].info, sizeof(sched_grp[devid].info), 0, sizeof(sched_grp[devid].info));
(void)pthread_mutex_unlock(&(sched_grp[devid].mutex));
esched_sync_res_reset(devid);
sched_dev_fd[devid] = 0;
#ifndef DRV_HOST
g_sched_mode[devid] = 0xff;
#endif
sched_run_info("Close user success. (dev_id=%u)\n", devid);
return DRV_ERROR_NONE;
}
drvError_t esched_device_close(uint32_t devid, halDevCloseIn *in)
{
(void)in;
struct sched_ioctl_para_detach para_detach;
if (!esched_support_extern_interface()) {
return 0;
}
if (esched_device_check(devid) != 0) {
sched_err("The dev_id is invalid. (dev_id=%u; max=%u)\n", devid, ESCHED_LOGIC_DEV_NUM);
return DRV_ERROR_PARA_ERROR;
}
esched_detach_device(devid, ¶_detach);
(void)usleep(ESCHED_CLOSE_MAX_SLEEP);
esched_dev_close(devid);
esched_clear_attach_refcnt(devid);
(void)pthread_mutex_lock(&(sched_grp[devid].mutex));
(void)memset_s((void *)sched_grp[devid].info, sizeof(sched_grp[devid].info), 0, sizeof(sched_grp[devid].info));
(void)pthread_mutex_unlock(&(sched_grp[devid].mutex));
esched_sync_res_reset(devid);
sched_dev_fd[devid] = 0;
#ifndef DRV_HOST
g_sched_mode[devid] = 0xff;
#endif
sched_run_info("Close success. (dev_id=%u)\n", devid);
return DRV_ERROR_NONE;
}
drvError_t esched_device_open(uint32_t devid, halDevOpenIn *in, halDevOpenOut *out)
{
(void)in;
(void)out;
if (!esched_support_extern_interface()) {
return 0;
}
if (esched_device_check(devid) != 0) {
sched_err("The dev_id is invalid. (dev_id=%u; max=%u)\n", devid, ESCHED_LOGIC_DEV_NUM);
return DRV_ERROR_PARA_ERROR;
}
if (sched_dev_fd[devid] >= 0) {
sched_run_info("The dev_id has opened. (dev_id=%u)\n", devid);
return DRV_ERROR_NONE;
}
sched_dev_fd[devid] = 0;
#ifndef DRV_HOST
g_sched_mode[devid] = 0xff;
#endif
sched_run_info("The dev_id open success. (dev_id=%u)\n", devid);
return DRV_ERROR_NONE;
}
STATIC int32_t __attribute__((constructor)) esched_init(void)
{
unsigned int i;
esched_share_log_create();
for (i = 0; i < ESCHED_DEV_NUM; i++) {
sched_dev_fd[i] = 0;
pthread_mutex_init(&(sched_grp[i].mutex), NULL);
}
return 0;
}
STATIC void __attribute__((destructor)) esched_exit(void)
{
unsigned int i;
for (i = 0; i < ESCHED_DEV_NUM; i++) {
if (sched_dev_fd[i] > 0) {
esched_dev_close(i);
}
(void)pthread_mutex_destroy(&(sched_grp[i].mutex));
}
esched_share_log_destroy();
}
#if defined(CFG_ENV_HOST) && !defined(CFG_SOC_PLATFORM_CLOUD_V4)
on the host side.Therefore, symbol halEventProc,halDrvEventThreadInit,halDrvEventThreadUninit are provided on the
host side for stubging. */
#ifndef EMU_ST
drvError_t halEventProc(unsigned int devId, struct event_info *event)
{
(void)devId;
(void)event;
return DRV_ERROR_NOT_SUPPORT;
}
drvError_t halDrvEventThreadInit(unsigned int devId)
{
(void)devId;
return DRV_ERROR_NOT_SUPPORT;
}
drvError_t halDrvEventThreadUninit(unsigned int devId)
{
(void)devId;
return DRV_ERROR_NOT_SUPPORT;
}
#endif
#endif