* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "ka_fs_pub.h"
#include "ka_driver_pub.h"
#include "ka_barrier_pub.h"
#include "ka_errno_pub.h"
#include "ka_memory_pub.h"
#include "securec.h"
#include "esched.h"
#include "esched_sysfs.h"
#define SCHED_FILE_PATH "/var/log/esched_trace"
#define SCHED_FILE_MODE 0640
#define SCHED_SYSFS_EVENT_NUM 1000
#define SCHED_SYSFS_CPU_USAGE_NUM 100
STATIC u32 g_node_id = 0;
u32 cpuid_in_node;
u32 cur_pid;
u32 cur_gid;
#ifdef CFG_FEATURE_VFIO
u32 g_cur_vf = 0;
#endif
STATIC void sched_fs_set_node_id(u32 id)
{
g_node_id = id;
}
typedef void (*pid_handle)(char *buf, ssize_t *offset, struct sched_proc_ctx *proc_ctx);
STATIC void pid_list_for_each_handle(char *buf, ssize_t *offset, pid_handle handle)
{
struct sched_proc_ctx *proc_ctx = NULL;
struct pid_entry *entry = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return;
}
ka_task_mutex_lock(&node->pid_list_mutex);
ka_list_for_each_entry(entry, &node->pid_list, list) {
proc_ctx = esched_proc_get(node, entry->pid);
if (proc_ctx == NULL) {
continue;
}
handle(buf, offset, proc_ctx);
esched_proc_put(proc_ctx);
}
ka_task_mutex_unlock(&node->pid_list_mutex);
esched_dev_put(node);
}
* Due to engineering problems, there will be false alarm,
* here to shield until the problem is solved.
*/
STATIC void sched_sysfs_write_file(ka_file_t *file, const void *buf, size_t count, loff_t *pos)
{
ssize_t ret;
ret = ka_fs_kernel_write_ret(file, buf, count, pos);
#if !defined (EVENT_SCHED_UT) && !defined (EMU_ST)
if (ret != (ssize_t)count) {
sched_warn("Unable to invoke the kernel_write. (count=%lu; ret=%ld)\n", count, ret);
}
#endif
}
STATIC int32_t sched_sysfs_clear_node_stat(struct sched_numa_node *node)
{
int32_t ret;
ret = memset_s(&node->event_trace, sizeof(struct sched_node_event_trace), 0,
sizeof(struct sched_node_event_trace));
if (ret != 0) {
sched_err("Failed to clear the event_trace node.\n");
return ret;
}
node->event_trace.enable_flag = SCHED_TRACE_ENABLE;
return 0;
}
STATIC ssize_t sched_sysfs_node_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_numa_node *node = NULL;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"node id,cpu num,sched cpu num\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_CHIP_NUM; i++) {
node = esched_dev_get(i);
if (node != NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u,%u,%u\n",
i, node->cpu_num, node->sched_cpu_num);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
}
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"node id,msg_type,dst_pid,dst_event_id,dst_subevent_id\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_CHIP_NUM; i++) {
node = esched_dev_get(i);
if (node != NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u,%u,%u,%u,%u\n",
i, node->curr_msg.msg_type, node->curr_msg.dst_pid, node->curr_msg.dst_event_id, node->curr_msg.dst_subevent_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
}
}
return offset;
}
STATIC ssize_t sched_sysfs_node_id_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u\n", g_node_id);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t sched_sysfs_node_id_write(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
struct sched_numa_node *node = NULL;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
node = sched_get_numa_node(val);
if (node == NULL) {
sched_err("The node_id is invalid. (node_id=%u)\n", val);
return count;
}
g_node_id = val;
sched_info("Set node_id %u.\n", val);
return (ssize_t)count;
}
STATIC ssize_t sched_sysfs_node_debug_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "0x%x\n", node->debug_flag);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "bit0: clear node event trace, bit1:"
"record cpu usage and event num sample data, bit2: support trigger sched event trace, bit3: record all event"
"trace (only valid when bit2 = 1)\n");
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
void sched_sysfs_node_debug_uninit(struct sched_numa_node *node)
{
if (node->node_event_sample != NULL) {
sched_vfree(node->node_event_sample);
node->node_event_sample = NULL;
}
if (node->proc_event_sample != NULL) {
sched_vfree(node->proc_event_sample);
node->proc_event_sample = NULL;
}
}
STATIC int32_t sched_sysfs_node_debug_init(struct sched_numa_node *node)
{
if (node->node_event_sample == NULL) {
node->node_event_sample = (struct sched_event_sample *)sched_vzalloc(sizeof(struct sched_event_sample));
if (node->node_event_sample == NULL) {
sched_err("Failed to vzalloc memory. (size=0x%lx)\n", sizeof(struct sched_event_sample));
return -ENOMEM;
}
}
if (node->proc_event_sample == NULL) {
node->proc_event_sample = (struct sched_event_sample *)sched_vzalloc(sizeof(struct sched_event_sample));
if (node->proc_event_sample == NULL) {
sched_err("Failed to vzalloc memory. (size=0x%lx)\n", sizeof(struct sched_event_sample));
return -ENOMEM;
}
}
return 0;
}
STATIC ssize_t sched_sysfs_node_debug_write(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
int32_t ret;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
sched_err("Dev not valid. (devid=%u)\n", g_node_id);
return count;
}
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
esched_dev_put(node);
return count;
}
if ((val == 0) && (node->node_event_sample == NULL) && (node->proc_event_sample == NULL)) {
#if !defined (EVENT_SCHED_UT) && !defined (EMU_ST)
sched_info("Set node dbg %u.\n", val);
#endif
esched_dev_put(node);
return count;
}
ka_task_mutex_lock(&node->node_guard_work_mutex);
if (val != 0) {
ret = sched_sysfs_node_debug_init(node);
if (ret != 0) {
ka_task_mutex_unlock(&node->node_guard_work_mutex);
sched_err("Failed to invoke the sched_sysfs_node_debug_init. (node_id=%u; ret=%d)\n",
node->node_id, ret);
esched_dev_put(node);
return ret;
}
}
if ((val & (0x1 << SCHED_DEBUG_EVENT_TRACE_BIT)) != 0) {
(void)sched_sysfs_clear_node_stat(node);
}
if ((val & (0x1 << SCHED_DEBUG_SAMPLE_BIT)) != 0) {
sched_sysfs_clear_sample_data(node);
} else if ((val & (0x1 << SCHED_DEBUG_TRIGGER_SAMPLE_FILE_BIT)) != 0) {
sched_sysfs_record_sample_data(node);
}
if ((val & (0x1 << SCHED_DEBUG_SCHED_TRACE_RECORD_BIT)) != 0) {
node->trace_record.num = 0;
}
node->debug_flag = val;
if (val == 0) {
sched_sysfs_node_debug_uninit(node);
}
ka_task_mutex_unlock(&node->node_guard_work_mutex);
sched_info("Set node dbg %u.\n", val);
esched_dev_put(node);
return count;
}
STATIC ssize_t sched_sysfs_node_cpu_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "cpuid,sched_mode,"
"sched stat:sched_event_num,check_sched_num,proc_exit_drop_num,exclusive_sched_num,timeout_cnt\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < node->sched_cpu_num; i++) {
struct sched_cpu_ctx *cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
struct sched_cpu_stat *stat = &cpu_ctx->stat;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%u,sched,%llu,%llu,%llu,%llu,%llu\n", cpu_ctx->cpuid, stat->sched_event_num,
stat->check_sched_num, stat->proc_exit_drop_num, stat->exclusive_sched_num, stat->timeout_cnt);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "cpuid,"
"thread(pid,gid,task_id,tid,event_id,sub_event_id,cpu_sched_time,curr_timestamp)\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < node->sched_cpu_num; i++) {
struct sched_cpu_ctx *cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
struct esched_abnormal_thread_record *record = &cpu_ctx->cpu_abnormal_thread;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%u,(%d,%u,%u,%u,%u,%u,%llu,%llu)\n", cpu_ctx->cpuid,
record->thread_info.pid, record->thread_info.gid, record->thread_info.task_id, record->thread_info.tid,
record->event_id, record->sub_event_id, record->cpu_sched_time, record->curr_timestamp);
if (ret >= 0) {
offset += ret;
}
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_cpu_mask(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
u32 i;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
for (i = 0; i < node->sched_cpu_num; i++) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u\n", node->sched_cpuid[i]);
if (ret >= 0) {
offset += ret;
}
}
esched_dev_put(node);
return offset;
}
STATIC void sched_sysfs_node_get_proc_list(char *buf, ssize_t *offset, struct sched_proc_ctx *proc_ctx)
{
int ret = snprintf_s(buf + *offset, KA_MM_PAGE_SIZE - *offset, KA_MM_PAGE_SIZE - *offset - 1, "%d,%s,%d,%d,%d\n",
proc_ctx->pid, proc_ctx->name, proc_ctx->refcnt,
ka_base_atomic_read(&proc_ctx->publish_event_num), ka_base_atomic_read(&proc_ctx->sched_event_num));
if (ret >= 0) {
*offset += ret;
}
}
STATIC ssize_t sched_sysfs_node_proc_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
pid_list_for_each_handle(buf, &offset, sched_sysfs_node_get_proc_list);
return offset;
}
STATIC ssize_t sched_sysfs_node_del_proc_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_proc_ctx *proc_ctx = NULL;
ka_list_head_t *pos = NULL;
ka_list_head_t *n = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ka_task_mutex_lock(&node->proc_mng_mutex);
if (!ka_list_empty_careful(&node->del_proc_head)) {
ka_list_for_each_safe(pos, n, &node->del_proc_head) {
proc_ctx = ka_list_entry(pos, struct sched_proc_ctx, list);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%d,%d\n",
proc_ctx->pid, proc_ctx->refcnt);
if (ret >= 0) {
offset += ret;
}
}
}
ka_task_mutex_unlock(&node->proc_mng_mutex);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_event_resource(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_event_que *res_que = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"resource total:use:que head:que tail,max use,enque_full,deque empty\n");
if (ret >= 0) {
offset += ret;
}
res_que = &node->event_res;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u:%u:%u:%u:%u:%llu:%llu\n",
res_que->depth, res_que->depth - sched_que_element_num(res_que), res_que->head, res_que->tail,
res_que->stat.max_use, res_que->stat.enque_full, res_que->stat.deque_empty);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_event_que_trace(struct sched_event *event_base,
struct sched_event_que *que, char *buf, ssize_t offset, const char *que_name, u32 que_id)
{
u32 i, j, flag;
int32_t ret;
struct sched_event *event = NULL;
if ((que->depth - sched_que_element_num(que)) == 0) {
return offset;
}
for (i = 0; i < que->depth; i++) {
event = &event_base[i];
flag = SCHED_INVALID;
for (j = que->head; j < que->tail; j++) {
if (event == que->ring[j & (que->mask)]) {
flag = SCHED_VALID;
break;
}
}
if (flag == SCHED_INVALID) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%s(%u),%u,%u,%u,%u,%u\n",
que_name, que_id, i, event->trace.type, event->trace.a, event->trace.b, event->trace.c);
if (ret >= 0) {
offset += ret;
}
}
}
return offset;
}
STATIC ssize_t sched_sysfs_event_trace(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"que name(que id),event index,sched type,dest_pid,dest_gid,event_pri\n");
if (ret >= 0) {
offset += ret;
}
offset = sched_sysfs_event_que_trace(node->event_base, &node->event_res, buf, offset, "node", 0);
for (i = 0; i < node->sched_cpu_num; i++) {
u32 cpuid = node->sched_cpuid[i];
cpu_ctx = sched_get_cpu_ctx(node, cpuid);
offset = sched_sysfs_event_que_trace(cpu_ctx->event_base, &cpu_ctx->event_res, buf, offset, "cpu", cpuid);
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_sample_period_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u ms\n", node->sample_period);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_sample_period_write(ka_device_t *dev,
ka_device_attribute_t *attr,
const char *buf,
size_t count)
{
u32 val = 0;
struct sched_numa_node *node = NULL;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
if ((val < SCHED_SAMPLE_MIN_PERIOD) || (val > SCHED_SAMPLE_MAX_PERIOD)) {
sched_err("The value of variable val is out of range. (val=%u)\n", val);
return count;
}
val = val / SCHED_SAMPLE_MIN_PERIOD * SCHED_SAMPLE_MIN_PERIOD;
node = esched_dev_get(g_node_id);
if (node == NULL) {
return count;
}
node->sample_period = val;
node->sample_interval = val / SCHED_GUARD_WORK_PERIOD;
esched_dev_put(node);
sched_info("Set sample_period %u.\n", val);
return count;
}
STATIC ssize_t sched_sysfs_event_sample_format(const char *period, char *buf, u32 buf_len, u32 idx, u32 pre_index,
struct sched_event_sample_data *data)
{
int32_t i, ret, submit_speed, sched_speed;
ssize_t offset = 0;
u64 duration, total_event_num, cur_event_num, event_num;
duration = tick_to_millisecond(data[idx].timestamp - data[pre_index].timestamp);
total_event_num = data[idx].total_event_num - data[pre_index].total_event_num;
cur_event_num = data[idx].cur_event_num - data[pre_index].cur_event_num;
if (duration == 0) {
return offset;
}
submit_speed = (int)((total_event_num * SCHED_SYSFS_EVENT_NUM) / duration);
sched_speed = (int)(((total_event_num - cur_event_num) * SCHED_SYSFS_EVENT_NUM) / duration);
if (ka_base_strlen(period) > 0) {
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1,
"%s,%llu,%d,%d", period, data[idx].timestamp, submit_speed, sched_speed);
} else {
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1,
"%llu,%llu,%llu", data[idx].timestamp, total_event_num, data[idx].cur_event_num);
}
if (ret >= 0) {
offset += ret;
}
for (i = 0 ; i < SCHED_MAX_EVENT_TYPE_NUM; i++) {
if (ka_base_strlen(period) > 0) {
event_num = data[idx].publish_event_num[i] - data[pre_index].sched_event_num[i];
submit_speed = (int)((event_num * SCHED_SYSFS_EVENT_NUM) / duration);
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1, ",%d", submit_speed);
} else {
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1,
",(%d,%llu,%llu)", i, data[idx].publish_event_num[i] -
data[pre_index].publish_event_num[i], data[idx].publish_event_num[i] -
data[idx].sched_event_num[i]);
}
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1, "\n");
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC int32_t sched_sysfs_record_event_sample_data(struct sched_numa_node *node, u64 timestamp,
struct sched_event_sample *sample_data, SAMPLE_TYPE_VALUE type)
{
struct sched_proc_ctx *proc_stat = NULL;
ka_file_t *fp = NULL;
char *buf = NULL;
int32_t ret;
loff_t offset_tmp = 0;
u32 i;
if (sample_data == NULL) {
sched_err("The sample_data is NULL.\n");
return DRV_ERROR_INNER_ERR;
}
#if !defined (EVENT_SCHED_UT) && !defined (EMU_ST)
buf = (char *)sched_kzalloc(KA_MM_PAGE_SIZE, KA_GFP_KERNEL);
if (buf == NULL) {
sched_err("Failed to alloc memory.(size=%lx)\n", KA_MM_PAGE_SIZE);
return DRV_ERROR_OUT_OF_MEMORY;
}
if (type == NODE_SAMPLE_TYPE) {
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%s/event_sample_%llu", SCHED_FILE_PATH, timestamp);
} else {
proc_stat = esched_proc_get(node, node->sample_proc_id);
if (proc_stat == NULL) {
sched_kfree(buf);
return 0;
}
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%s/event_sample_pid_%d_%llu", SCHED_FILE_PATH,
proc_stat->pid, timestamp);
esched_proc_put(proc_stat);
}
if (ret < 0) {
sched_err("Failed to invoke the snprintf_s.\n");
sched_kfree(buf);
return ret;
}
fp = ka_fs_filp_open(buf, KA_O_RDWR | KA_O_TRUNC | KA_O_CREAT, SCHED_FILE_MODE);
if (KA_IS_ERR(fp)) {
sched_err("Failed to invoke the filp_open. (buf=\"%s\")\n", buf);
sched_kfree(buf);
return DRV_ERROR_INNER_ERR;
}
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "timestamp, publish_event_num, cur_event_num,"
"(event_id, publish_event_num, cur_event_num).....\n");
if (ret > 0) {
sched_sysfs_write_file(fp, (const void *)buf, ka_base_strlen(buf), &offset_tmp);
}
for (i = 1; i < sample_data->record_num; i++) {
ret = sched_sysfs_event_sample_format("", buf, KA_MM_PAGE_SIZE, i, i - 1, sample_data->data);
if (ret > 0) {
sched_sysfs_write_file(fp, (const void *)buf, ka_base_strlen(buf), &offset_tmp);
}
}
sched_kfree(buf);
#endif
(void)ka_fs_filp_close(fp, NULL);
return 0;
}
STATIC ssize_t sched_sysfs_event_sample(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 idx, pre_index, period;
int32_t ret;
ssize_t offset = 0;
struct sched_event_sample *sample = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ka_task_mutex_lock(&node->node_guard_work_mutex);
sample = node->node_event_sample;
if (sample == NULL) {
ka_task_mutex_unlock(&node->node_guard_work_mutex);
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"timestamp, publish_speed(num/s), sched_speed(num/s), each type\n");
if (ret >= 0) {
offset += ret;
}
if (sample->record_num == 0) {
ka_task_mutex_unlock(&node->node_guard_work_mutex);
esched_dev_put(node);
return offset;
}
idx = sample->record_num - 1;
period = node->sample_period;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_event_sample_format("single", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index,
sample->data);
}
period = SYS_SCHED_PERIOD_TIME_1S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_event_sample_format("1s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index,
sample->data);
}
period = SYS_SCHED_PERIOD_TIME_10S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_event_sample_format("10s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index,
sample->data);
}
period = SYS_SCHED_PERIOD_TIME_60S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_event_sample_format("60s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index,
sample->data);
}
period = SYS_SCHED_PERIOD_TIME_300S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_event_sample_format("300s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index,
sample->data);
}
ka_task_mutex_unlock(&node->node_guard_work_mutex);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_cpu_usage_sample_format(struct sched_cpu_sample *sample_data,
char *buf, u32 buf_len, u32 idx, u32 pre_index)
{
int32_t usage;
u64 duration, total_use_time;
duration = sample_data->data[idx].timestamp - sample_data->data[pre_index].timestamp;
if (duration == 0) {
return 0;
}
total_use_time = sample_data->data[idx].total_use_time - sample_data->data[pre_index].total_use_time;
usage = (int)((total_use_time * SCHED_SYSFS_CPU_USAGE_NUM) / duration);
if (usage > SCHED_SYSFS_CPU_USAGE_NUM) {
usage = SCHED_SYSFS_CPU_USAGE_NUM;
}
return snprintf_s(buf, buf_len, buf_len - 1, "%llu,%d\n", sample_data->data[idx].timestamp, usage);
}
STATIC int32_t sched_sysfs_record_cpu_sample_data(u64 timestamp, int32_t cpu_id, struct sched_cpu_sample *sample_data)
{
ka_file_t *fp = NULL;
char buf[MAX_LENTH];
loff_t offset_tmp = 0;
int32_t ret;
u32 i;
ret = snprintf_s(buf, MAX_LENTH, MAX_LENTH - 1, "%s/cpu_%d_sample_%llu", SCHED_FILE_PATH, cpu_id, timestamp);
if (ret < 0) {
sched_err("Failed to invoke the snprintf_s.\n");
return ret;
}
fp = ka_fs_filp_open(buf, KA_O_RDWR | KA_O_TRUNC | KA_O_CREAT, SCHED_FILE_MODE);
if (KA_IS_ERR(fp)) {
sched_err("Failed to invoke the filp_open.\n");
return DRV_ERROR_INNER_ERR;
}
ret = snprintf_s(buf, MAX_LENTH, MAX_LENTH - 1, "timestamp, cpu_usage(percent)\n");
if (ret > 0) {
sched_sysfs_write_file(fp, (const void *)buf, ka_base_strlen(buf), &offset_tmp);
}
for (i = 1; i < sample_data->record_num; i++) {
ret = sched_sysfs_cpu_usage_sample_format(sample_data, buf, MAX_LENTH, i, i - 1);
if (ret > 0) {
sched_sysfs_write_file(fp, (const void *)buf, ka_base_strlen(buf), &offset_tmp);
}
}
(void)ka_fs_filp_close(fp, NULL);
return 0;
}
STATIC ssize_t sched_sysfs_cpu_usage_sample_period(const char *period, char *buf, u32 buf_len, u32 idx, u32 pre_index)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_cpu_sample *sample = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1, "%s\n", period);
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < node->sched_cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
sample = cpu_ctx->sample;
if (sample == NULL) {
continue;
}
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1, "%d,", cpu_ctx->cpuid);
if (ret >= 0) {
offset += ret;
}
offset += sched_sysfs_cpu_usage_sample_format(sample, buf + offset, buf_len - offset, idx, pre_index);
}
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1, "\n");
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_cpu_usage_sample(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 idx, pre_index, period;
int32_t ret;
ssize_t offset = 0;
struct sched_event_sample *sample = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ka_task_mutex_lock(&node->node_guard_work_mutex);
sample = node->node_event_sample;
if (sample == NULL) {
ka_task_mutex_unlock(&node->node_guard_work_mutex);
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"cpuid,timestamp,usage(%%)\n");
if (ret >= 0) {
offset += ret;
}
if (sample->record_num == 0) {
ka_task_mutex_unlock(&node->node_guard_work_mutex);
esched_dev_put(node);
return offset;
}
idx = sample->record_num - 1;
period = node->sample_period;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_cpu_usage_sample_period("single", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index);
}
period = SYS_SCHED_PERIOD_TIME_1S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_cpu_usage_sample_period("1s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index);
}
period = SYS_SCHED_PERIOD_TIME_10S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_cpu_usage_sample_period("10s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index);
}
period = SYS_SCHED_PERIOD_TIME_60S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_cpu_usage_sample_period("60s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index);
}
period = SYS_SCHED_PERIOD_TIME_300S;
if (idx >= (period / node->sample_period)) {
pre_index = idx - (period / node->sample_period);
offset += sched_sysfs_cpu_usage_sample_period("300s", buf + offset, KA_MM_PAGE_SIZE - offset, idx, pre_index);
}
ka_task_mutex_unlock(&node->node_guard_work_mutex);
esched_dev_put(node);
return offset;
}
void sched_sysfs_record_sample_data(struct sched_numa_node *node)
{
u64 timestamp = sched_get_cur_timestamp();
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_cpu_sample *sample = NULL;
int32_t ret;
u32 i;
ret = sched_sysfs_record_event_sample_data(node, timestamp, node->node_event_sample, NODE_SAMPLE_TYPE);
if (ret != 0) {
sched_info("Invoke the sched_sysfs_record_event_sample_data. (ret=%d, type=%d)\n", ret, NODE_SAMPLE_TYPE);
}
ret = sched_sysfs_record_event_sample_data(node, timestamp, node->proc_event_sample, PID_SAMPLE_TYPE);
if (ret != 0) {
sched_info("Invoke the sched_sysfs_record_event_sample_data. (ret=%d, type=%d)\n", ret, PID_SAMPLE_TYPE);
}
for (i = 0; i < node->sched_cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
sample = cpu_ctx->sample;
if (sample != NULL) {
(void)sched_sysfs_record_cpu_sample_data(timestamp, cpu_ctx->cpuid, sample);
}
}
}
void sched_sysfs_clear_sample_data(struct sched_numa_node *node)
{
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_cpu_sample *sample = NULL;
u32 i;
node->node_event_sample->record_num = 0;
node->proc_event_sample->record_num = 0;
for (i = 0; i < node->sched_cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
sample = cpu_ctx->sample;
if (sample != NULL) {
sample->record_num = 0;
}
}
sched_info("End of calling sched_sysfs_clear_sample_data. "
"(cur_timestamp=%llu; frequence=%llu)\n", sched_get_cur_timestamp(), sched_get_sys_freq());
}
STATIC ssize_t sched_sysfs_node_sched_abnormal_time_read(char *buf, u64 timestamp_thres)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%llu (us)\n", tick_to_microsecond(timestamp_thres));
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_abnormal_time_write(const char *buf,
size_t count, u64 *timestamp_thres)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
*timestamp_thres = microsecond_to_tick((u64)val);
sched_info("Set abnormal_time %u.\n", val);
return count;
}
STATIC ssize_t sched_sysfs_node_sched_proc_abnormal_time_read(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
size_t count = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_read(buf, node->abnormal_event.proc.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_proc_abnormal_time_write(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_write(buf, count, &node->abnormal_event.proc.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_publish_syscall_abnormal_time_read(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
size_t count = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_read(buf, node->abnormal_event.publish_syscall.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_publish_syscall_abnormal_time_write(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_write(buf, count,
&node->abnormal_event.publish_syscall.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_publish_in_kernel_abnormal_time_read(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
size_t count = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_read(buf, node->abnormal_event.publish_in_kernel.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_publish_in_kernel_abnormal_time_write(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_write(buf, count,
&node->abnormal_event.publish_in_kernel.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_wakeup_abnormal_time_read(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
size_t count = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_read(buf, node->abnormal_event.wakeup.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_wakeup_abnormal_time_write(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_write(buf, count, &node->abnormal_event.wakeup.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_publish_subscribe_abnormal_time_read(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
size_t count = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_read(buf, node->abnormal_event.publish_subscribe.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_publish_subscribe_abnormal_time_write(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_write(buf, count,
&node->abnormal_event.publish_subscribe.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_thread_run_abnormal_time_read(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
size_t count = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_read(buf, node->abnormal_event.thread_run.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC ssize_t sched_sysfs_node_sched_thread_run_abnormal_time_write(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
struct sched_numa_node *node = NULL;
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
if (val < (SCHED_GUARD_WORK_PERIOD * MILLISECOND_TO_MICROSECOND)) {
sched_err("The value of unit us must be large than 10ms. (val=%u)\n", val);
return count;
}
node = esched_dev_get(g_node_id);
if (node != NULL) {
count = sched_sysfs_node_sched_abnormal_time_write(buf, count,
&node->abnormal_event.thread_run.timestamp_thres);
esched_dev_put(node);
}
return count;
}
STATIC int32_t sched_sysfs_node_single_event_info(char *buf, struct sched_abnormal_event_item *event_info,
struct sched_event_timestamp *timestamp, ssize_t *offset, u32 idx, ABNORMAL_EVENT_TYPE_VALUE type)
{
u64 wakeup_to_waked;
u64 wakeup_offset;
s64 subscribe_in_kernel;
int32_t ret;
char *format_string[] = {
"%d,%llu,%llu,%llu,%llu,%llu,%lld,%llu,%llu,%llu,(%llu),%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n",
"%d,%llu,%llu,%llu,%llu,%llu,%lld,(%llu),%llu,%llu,%llu,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n",
"%d,%llu,%llu,%llu,%llu,%llu,%lld,%llu,%llu,(%llu),%llu,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n",
"%d,%llu,%llu,%llu,%llu,%llu,%lld,%llu,%llu,%llu,%llu,%d,%d,%d,%d,%d,%d,%d,%d,%d,%s\n"
};
wakeup_offset = 0;
if (timestamp->publish_wakeup != 0) {
wakeup_offset = tick_to_microsecond(timestamp->publish_wakeup - timestamp->publish_user);
}
wakeup_to_waked = 0;
if (timestamp->publish_wakeup != 0) {
wakeup_to_waked = tick_to_microsecond(timestamp->subscribe_waked - timestamp->publish_wakeup);
}
subscribe_in_kernel = (timestamp->subscribe_in_kernel >= timestamp->publish_user) ?
tick_to_microsecond(timestamp->subscribe_in_kernel - timestamp->publish_user) :
tick_to_microsecond((timestamp->publish_user - timestamp->subscribe_in_kernel) * (-1));
ret = snprintf_s(buf + *offset, KA_MM_PAGE_SIZE - *offset, KA_MM_PAGE_SIZE - *offset - 1,
format_string[type], idx, timestamp->publish_user, timestamp->publish_user_of_day,
tick_to_microsecond(timestamp->publish_in_kernel - timestamp->publish_user), wakeup_offset,
tick_to_microsecond(timestamp->publish_out_kernel - timestamp->publish_user), subscribe_in_kernel,
wakeup_to_waked, tick_to_microsecond(timestamp->subscribe_waked - timestamp->publish_user),
tick_to_microsecond(timestamp->subscribe_out_kernel - timestamp->publish_user),
tick_to_microsecond(event_info->proc_time),
event_info->event_id, event_info->publish_pid, event_info->publish_cpuid,
event_info->wait_event_num_in_que, event_info->pid, event_info->gid, event_info->tid,
event_info->bind_cpuid, event_info->kernel_tid, event_info->name);
if (ret >= 0) {
*offset += ret;
}
return ret;
}
STATIC ssize_t sched_sysfs_node_event_all_info(char *buf, struct sched_abnormal_event_item *events,
int32_t cur_id, u32 event_num, ABNORMAL_EVENT_TYPE_VALUE type)
{
static u32 i = 0;
int32_t ret;
ssize_t offset = 0;
struct sched_abnormal_event_item *event_info = NULL;
struct sched_event_timestamp *timestamp = NULL;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "record index %d\n\n", cur_id);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"index,publish_user,publish_user_of_day,publish_syscall(+),publish_to_wakeup(+),publish_finish(+),"
"publish_to_wait_start(+),wakeup_to_waked(+),publish_to_waked(+),publish_to_wait_end(+),proc time(us),event id,"
"publish_pid,publish_cpuid,wait_event_num_in_que,pid,gid,tid,bind cpuid,kernel tid,thread name\n");
if (ret >= 0) {
offset += ret;
}
if (i >= event_num) {
i = 0;
}
for (; i < event_num; i++) {
event_info = &events[i];
timestamp = &event_info->timestamp;
if (timestamp->publish_user == 0) {
continue;
}
ret = sched_sysfs_node_single_event_info(buf, event_info, timestamp, &offset, i, type);
if (ret < 0) {
break;
}
}
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_abnormal_event_clear(ka_device_t *dev,
ka_device_attribute_t *attr, const char *buf, size_t count)
{
u32 val = 0;
struct sched_node_abnormal_event *abnormal_event = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return count;
}
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
esched_dev_put(node);
return count;
}
if (val == 1) {
abnormal_event = &node->abnormal_event;
(void)memset_s(abnormal_event, sizeof(struct sched_node_abnormal_event), 0,
sizeof(struct sched_node_abnormal_event));
abnormal_event->publish_syscall.timestamp_thres =
microsecond_to_tick(SCHED_DEFAULT_PUBLISH_SYSCALL_TIME_THRES);
abnormal_event->publish_in_kernel.timestamp_thres =
microsecond_to_tick(SCHED_DEFAULT_PUBLISH_IN_KERNEL_TIME_THRES);
abnormal_event->wakeup.timestamp_thres =
microsecond_to_tick(SCHED_DEFAULT_WAKEUP_TIME_THRES);
abnormal_event->publish_subscribe.timestamp_thres =
microsecond_to_tick(SCHED_DEFAULT_PUBLISH_SUBSCRIBE_TIME_THRES);
abnormal_event->proc.timestamp_thres =
microsecond_to_tick(SCHED_DEFAULT_PROC_TIME_THRES);
abnormal_event->thread_run.timestamp_thres =
microsecond_to_tick(SCHED_DEFAULT_PROC_TIME_THRES);
}
esched_dev_put(node);
sched_info("Set abnormal_event %u.\n", val);
return count;
}
STATIC ssize_t sched_sysfs_node_sched_proc_abnormal_event(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
offset = sched_sysfs_node_event_all_info(buf, node->abnormal_event.proc.event_info,
ka_base_atomic_read(&node->abnormal_event.proc.cur_index), SCHED_ABNORMAL_EVENT_MAX_NUM, PROC_ABNORMAL_EVENT);
esched_dev_put(node);
}
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_thread_run_abnormal_event(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
offset = sched_sysfs_node_event_all_info(buf, node->abnormal_event.thread_run.event_info,
ka_base_atomic_read(&node->abnormal_event.thread_run.cur_index),
SCHED_ABNORMAL_EVENT_MAX_NUM, PROC_ABNORMAL_EVENT);
esched_dev_put(node);
}
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_publish_syscall_abnormal_event(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
static u32 i = 0;
int32_t ret;
ssize_t offset = 0;
struct sched_abnormal_event_item *event_info = NULL;
struct sched_event_timestamp *timestamp = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"record index %d\n\n", ka_base_atomic_read(&node->abnormal_event.publish_syscall.cur_index));
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"index,publish_user,publish_syscall(+),event id,publish_pid,publish_cpuid\n");
if (ret >= 0) {
offset += ret;
}
if (i == SCHED_ABNORMAL_EVENT_MAX_NUM) {
i = 0;
}
for (; i < SCHED_ABNORMAL_EVENT_MAX_NUM; i++) {
event_info = &node->abnormal_event.publish_syscall.event_info[i];
timestamp = &event_info->timestamp;
if (timestamp->publish_user == 0) {
continue;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%d,%llu,%llu,%d,%d,%d\n", i,
timestamp->publish_user, tick_to_microsecond(timestamp->publish_in_kernel - timestamp->publish_user),
event_info->event_id, event_info->publish_pid, event_info->publish_cpuid);
if (ret >= 0) {
offset += ret;
} else {
break;
}
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_publish_in_kernel_abnormal_event(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
static u32 i = 0;
int32_t ret;
ssize_t offset = 0;
struct sched_abnormal_event_item *event_info = NULL;
struct sched_event_timestamp *timestamp = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"record index %d\n\n", ka_base_atomic_read(&node->abnormal_event.publish_in_kernel.cur_index));
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"index,publish_user,publish_syscall(+),publish_finish(+),event id,publish_pid,publish_cpuid\n");
if (ret >= 0) {
offset += ret;
}
if (i == SCHED_ABNORMAL_EVENT_MAX_NUM) {
i = 0;
}
for (; i < SCHED_ABNORMAL_EVENT_MAX_NUM; i++) {
event_info = &node->abnormal_event.publish_in_kernel.event_info[i];
timestamp = &event_info->timestamp;
if (timestamp->publish_user == 0) {
continue;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%d,%llu,%llu,%llu,%d,%d,%d\n", i,
timestamp->publish_user, tick_to_microsecond(timestamp->publish_in_kernel - timestamp->publish_user),
tick_to_microsecond(timestamp->publish_out_kernel - timestamp->publish_user),
event_info->event_id, event_info->publish_pid, event_info->publish_cpuid);
if (ret >= 0) {
offset += ret;
} else {
break;
}
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_wakeup_abnormal_event(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
offset = sched_sysfs_node_event_all_info(buf, node->abnormal_event.wakeup.event_info,
ka_base_atomic_read(&node->abnormal_event.wakeup.cur_index), SCHED_ABNORMAL_EVENT_MAX_NUM, WAKEUP_ABNORMAL_EVENT);
esched_dev_put(node);
}
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_publish_subscribe_abnormal_event(ka_device_t *dev,
ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
offset = sched_sysfs_node_event_all_info(buf, node->abnormal_event.publish_subscribe.event_info,
ka_base_atomic_read(&node->abnormal_event.publish_subscribe.cur_index), SCHED_ABNORMAL_EVENT_MAX_NUM,
PUBLISH_SUBSCRIBE_ABNORMAL_EVENT);
esched_dev_put(node);
}
return offset;
}
STATIC ssize_t sched_sysfs_node_sched_event_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
offset = sched_sysfs_node_event_all_info(buf, node->event_trace.event_info,
ka_base_atomic_read(&node->event_trace.cur_index), SCHED_EVENT_TRACE_MAX_NUM, NORMAL_EVENT);
esched_dev_put(node);
}
return offset;
}
STATIC void sched_sysfs_get_all_cpu_event_summary(struct sched_cpu_perf_stat *perf_stat)
{
u32 i, j;
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return;
}
for (i = 0; i < node->cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, i);
if (cpu_ctx == NULL) {
continue;
}
for (j = 0 ; j < SCHED_MAX_EVENT_TYPE_NUM; j++) {
perf_stat->sw_publish_event_num[j] += cpu_ctx->perf_stat.sw_publish_event_num[j];
perf_stat->hw_publish_event_num[j] += cpu_ctx->perf_stat.hw_publish_event_num[j];
perf_stat->publish_fail_event_num[j] += cpu_ctx->perf_stat.publish_fail_event_num[j];
perf_stat->sched_event_num[j] += cpu_ctx->perf_stat.sched_event_num[j];
perf_stat->submit_event_num[j] += cpu_ctx->perf_stat.submit_event_num[j];
perf_stat->submit_fail_event_num[j] += cpu_ctx->perf_stat.submit_fail_event_num[j];
}
perf_stat->total_publish_event_num += cpu_ctx->perf_stat.total_publish_event_num;
perf_stat->total_publish_fail_event_num += cpu_ctx->perf_stat.total_publish_fail_event_num;
perf_stat->total_sched_event_num += cpu_ctx->perf_stat.total_sched_event_num;
perf_stat->total_wakeup_event_num += cpu_ctx->perf_stat.total_wakeup_event_num;
perf_stat->total_submit_event_num += cpu_ctx->perf_stat.total_submit_event_num;
perf_stat->total_submit_fail_event_num += cpu_ctx->perf_stat.total_submit_fail_event_num;
perf_stat->wakeup_total_time += cpu_ctx->perf_stat.wakeup_total_time;
perf_stat->publish_in_kernel_total_time += cpu_ctx->perf_stat.publish_in_kernel_total_time;
perf_stat->publish_subscribe_total_time += cpu_ctx->perf_stat.publish_subscribe_total_time;
perf_stat->publish_syscall_total_time += cpu_ctx->perf_stat.publish_syscall_total_time;
if (cpu_ctx->perf_stat.publish_in_kernel_max_time > perf_stat->publish_in_kernel_max_time) {
perf_stat->publish_in_kernel_max_time = cpu_ctx->perf_stat.publish_in_kernel_max_time;
}
if (cpu_ctx->perf_stat.publish_subscribe_max_time > perf_stat->publish_subscribe_max_time) {
perf_stat->publish_subscribe_max_time = cpu_ctx->perf_stat.publish_subscribe_max_time;
}
if (cpu_ctx->perf_stat.publish_syscall_max_time > perf_stat->publish_syscall_max_time) {
perf_stat->publish_syscall_max_time = cpu_ctx->perf_stat.publish_syscall_max_time;
}
if (cpu_ctx->perf_stat.wakeup_max_time > perf_stat->wakeup_max_time) {
perf_stat->wakeup_max_time = cpu_ctx->perf_stat.wakeup_max_time;
}
}
esched_dev_put(node);
}
STATIC ssize_t sched_sysfs_node_event_summary(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i, dump_times;
int32_t ret;
ssize_t offset = 0;
struct sched_cpu_perf_stat *perf_stat = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
struct wakeup_err_info *err_info;
u64 wakeup_err_times;
if (node == NULL) {
return offset;
}
wakeup_err_times = node->wakeup_err_info.wakeup_err_times;
perf_stat = (struct sched_cpu_perf_stat *)sched_kzalloc(sizeof(struct sched_cpu_perf_stat), KA_GFP_KERNEL);
if (perf_stat == NULL) {
sched_err("Failed to alloc memory.(size=%lx)\n", sizeof(struct sched_cpu_perf_stat));
esched_dev_put(node);
return offset;
}
sched_sysfs_get_all_cpu_event_summary(perf_stat);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"submit_event_num %llu\ntotal_submit_fail_event_num %llu\npublish_event_num %llu\ntotal_publish_fail_event_num %llu\nsched_event_num %llu\nwakeup_event_num %llu\nwakeup_err_num %llu\n\n",
perf_stat->total_submit_event_num, perf_stat->total_submit_fail_event_num, perf_stat->total_publish_event_num,
perf_stat->total_publish_fail_event_num, perf_stat->total_sched_event_num, perf_stat->total_wakeup_event_num, wakeup_err_times);
if (ret >= 0) {
offset += ret;
}
if (perf_stat->total_publish_event_num != 0) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"publish system call:\nave time(us) %llu \nmax time(us) %llu \n",
tick_to_microsecond(perf_stat->publish_syscall_total_time / perf_stat->total_publish_event_num),
tick_to_microsecond(perf_stat->publish_syscall_max_time));
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"publish in kernel:\nave time(us) %llu \nmax time(us) %llu \n",
tick_to_microsecond(perf_stat->publish_in_kernel_total_time / perf_stat->total_publish_event_num),
tick_to_microsecond(perf_stat->publish_in_kernel_max_time));
if (ret >= 0) {
offset += ret;
}
}
if (perf_stat->total_wakeup_event_num != 0) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"wakeup:\nave time(us) %llu \nmax time(us) %llu \n",
tick_to_microsecond(perf_stat->wakeup_total_time / perf_stat->total_wakeup_event_num),
tick_to_microsecond(perf_stat->wakeup_max_time));
if (ret >= 0) {
offset += ret;
}
}
if (perf_stat->total_sched_event_num != 0) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"publish subscribe:\nave time(us) %llu \nmax time(us) %llu \n",
tick_to_microsecond(perf_stat->publish_subscribe_total_time / perf_stat->total_sched_event_num),
tick_to_microsecond(perf_stat->publish_subscribe_max_time));
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"\nevent id,submit_event_num,submit_fail_event_num,sw_publish_event_num,hw_publish_event_num,publish_fail_event_num,sched_event_num\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_EVENT_TYPE_NUM; i++) {
if ((perf_stat->sw_publish_event_num[i] != 0) || (perf_stat->sched_event_num[i] != 0) ||
(perf_stat->submit_event_num[i] != 0) || (perf_stat->hw_publish_event_num[i] != 0)) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%d, %llu, %llu, %llu, %llu, %llu, %llu\n",
i, perf_stat->submit_event_num[i], perf_stat->submit_fail_event_num[i], perf_stat->sw_publish_event_num[i],
perf_stat->hw_publish_event_num[i], perf_stat->publish_fail_event_num[i], perf_stat->sched_event_num[i]);
if (ret >= 0) {
offset += ret;
}
}
}
if (wakeup_err_times != 0) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"\nthread_status,bind_cpuid,pid,gid,tid,kernel_tid,curr_wakeup_reason,pre_wakeup_reason\n");
if (ret >= 0) {
offset += ret;
}
dump_times = (wakeup_err_times > SCHED_WAKEUP_ERR_RECORD_NUM) ? SCHED_WAKEUP_ERR_RECORD_NUM : wakeup_err_times;
for (i = 0; i < dump_times; i++) {
err_info = &node->wakeup_err_info.err_info[i];
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%u, %u, %u, %u, %u, %u, %u, %u\n",
err_info->thread_status, err_info->bind_cpuid, err_info->pid, err_info->group_id, err_info->tid,
err_info->kernel_tid, err_info->normal_wakeup_reason, err_info->pre_normal_wakeup_reason);
if (ret >= 0) {
offset += ret;
}
}
}
sched_kfree(perf_stat);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_cpuid_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u\n", cpuid_in_node);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t sched_sysfs_node_cpuid_write(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return count;
}
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
esched_dev_put(node);
return count;
}
if ((val >= node->cpu_num) || (sched_get_cpu_ctx(node, val) == NULL)) {
sched_err("The cpuid is invalid. (val=%u)\n", val);
esched_dev_put(node);
return count;
}
cpuid_in_node = val;
esched_dev_put(node);
sched_info("Set node_cpuid %u.\n", val);
return count;
}
STATIC ssize_t sched_sysfs_node_cur_event_num(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
#ifdef CFG_FEATURE_VFIO
int32_t k;
#endif
int32_t ret, i, j;
ssize_t offset = 0;
struct sched_event_list *event_list = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"node_id %u current event num: %u\n\nnode_id proc_pri event_pri event_num (vf0~vf16)\n",
node->node_id, ka_base_atomic_read(&node->cur_event_num));
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_PROC_PRI_NUM; i++) {
for (j = 0; j < SCHED_MAX_EVENT_PRI_NUM; j++) {
event_list = sched_get_sched_event_list(node, i, j);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%u,%d,%d,%u", node->node_id, i, j, event_list->cur_num);
if (ret >= 0) {
offset += ret;
}
#ifdef CFG_FEATURE_VFIO
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, " (");
if (ret >= 0) {
offset += ret;
}
for (k = 0; k < VMNG_VDEV_MAX_PER_PDEV; k++) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u ",
event_list->slice_cur_event_num[k]);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, ")\n");
if (ret >= 0) {
offset += ret;
}
#else
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\n");
if (ret >= 0) {
offset += ret;
}
#endif
}
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_cpu_cur_thread(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_thread_ctx *thread_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "cpuid,pid,gid,tid\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < node->sched_cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
thread_ctx = esched_cpu_cur_thread_get(cpu_ctx);
if (thread_ctx != NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%u,pid:%d(%s),gid:%u,tid:%u\n",
i, thread_ctx->grp_ctx->pid, thread_ctx->grp_ctx->proc_ctx->name,
thread_ctx->grp_ctx->gid, thread_ctx->tid);
if (ret >= 0) {
offset += ret;
}
esched_cpu_cur_thread_put(thread_ctx);
} else {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%d,idle\n", cpu_ctx->cpuid);
if (ret >= 0) {
offset += ret;
}
}
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_cpu_event_resource(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_event_que *res_que = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"cpuid,resouce total:use:que head:que tail,max use, enque_full cnt, deque empty cnt\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < node->cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, i);
if (cpu_ctx == NULL) {
continue;
}
res_que = &cpu_ctx->event_res;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u,%u:%u:%u:%u:%u:%llu:%llu\n", i,
res_que->depth, res_que->depth - sched_que_element_num(res_que), res_que->head, res_que->tail,
res_que->stat.max_use, res_que->stat.enque_full, res_que->stat.deque_empty);
if (ret >= 0) {
offset += ret;
}
}
esched_dev_put(node);
return offset;
}
STATIC int32_t sched_sysfs_node_proc_single_thread_info(char *buf, struct sched_thread_ctx *thread_ctx,
struct sched_grp_ctx *grp_ctx, ssize_t *offset, int32_t idx)
{
int32_t ret;
char *status = NULL;
if (ka_base_atomic_read(&thread_ctx->status) == SCHED_THREAD_STATUS_IDLE) {
status = "idle";
} else if (ka_base_atomic_read(&thread_ctx->status) == SCHED_THREAD_STATUS_RUN) {
status = "running";
} else {
status = "ready";
}
if (grp_ctx->sched_mode == SCHED_MODE_SCHED_CPU) {
ret = snprintf_s(buf + *offset, KA_MM_PAGE_SIZE - *offset, KA_MM_PAGE_SIZE - *offset - 1,
"%u,%d,%d,%d,%s,%u,%s,%u,%u,%d,%d,%llu,%llu,%llu,%llu,%llu,%llx,%u,%u,%u\n",
thread_ctx->bind_cpuid, grp_ctx->pid, grp_ctx->gid, idx,
thread_ctx->name, thread_ctx->kernel_tid, status, thread_ctx->wait_flag, thread_ctx->timeout_flag,
thread_ctx->pre_normal_wakeup_reason, thread_ctx->normal_wakeup_reason,
tick_to_millisecond(thread_ctx->start_time), tick_to_microsecond(thread_ctx->max_proc_time),
(thread_ctx->stat.sched_event != 0) ? (tick_to_microsecond(thread_ctx->total_proc_time) /
thread_ctx->stat.sched_event) : 0, tick_to_microsecond(thread_ctx->max_sched_time),
(thread_ctx->stat.sched_event != 0) ? (tick_to_microsecond(thread_ctx->total_sched_time) /
thread_ctx->stat.sched_event) : 0, thread_ctx->subscribe_event_bitmap,
thread_ctx->stat.sched_event, thread_ctx->stat.timeout_cnt,
ka_base_atomic_read(&thread_ctx->stat.discard_event));
} else {
ret = snprintf_s(buf + *offset, KA_MM_PAGE_SIZE - *offset, KA_MM_PAGE_SIZE - *offset - 1,
"%d,%s,%u,%s,%u,%llu,%llu,%llu,%llu,%llu,%llx,%u,%u\n",
idx,
thread_ctx->name, thread_ctx->kernel_tid, status, thread_ctx->wait_flag,
tick_to_millisecond(thread_ctx->start_time), tick_to_microsecond(thread_ctx->max_proc_time),
(thread_ctx->stat.sched_event != 0) ? (tick_to_microsecond(thread_ctx->total_proc_time) /
thread_ctx->stat.sched_event) : 0, tick_to_microsecond(thread_ctx->max_sched_time),
(thread_ctx->stat.sched_event != 0) ? (tick_to_microsecond(thread_ctx->total_sched_time) /
thread_ctx->stat.sched_event) : 0, thread_ctx->subscribe_event_bitmap,
ka_base_atomic_read(&grp_ctx->cur_event_num), thread_ctx->stat.sched_event);
}
if (ret >= 0) {
*offset += ret;
}
return ret;
}
STATIC void sched_sysfs_node_grp_thread_info(char *buf, struct sched_grp_ctx *grp_ctx, ssize_t *offset)
{
struct sched_thread_ctx *thread_ctx = NULL;
u32 i;
int32_t ret;
for (i = 0; i < grp_ctx->thread_num; i++) {
thread_ctx = sched_get_thread_ctx(grp_ctx, grp_ctx->thread[i]);
if (thread_ctx->bind_cpuid == cpuid_in_node) {
ret = sched_sysfs_node_proc_single_thread_info(buf, thread_ctx, grp_ctx, offset, i);
if (ret < 0) {
break;
}
}
}
}
STATIC void sched_sysfs_node_proc_thread_info(char *buf, ssize_t *offset, struct sched_proc_ctx *proc_ctx)
{
struct sched_grp_ctx *grp_ctx = NULL;
u32 i;
for (i = 0; i < SCHED_MAX_GRP_NUM; i++) {
grp_ctx = sched_get_grp_ctx(proc_ctx, i);
if (grp_ctx->sched_mode != SCHED_MODE_SCHED_CPU) {
continue;
}
sched_sysfs_node_grp_thread_info(buf, grp_ctx, offset);
}
}
STATIC ssize_t sched_sysfs_node_cpu_thread_info(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
if ((cpuid_in_node >= node->cpu_num) || (sched_get_cpu_ctx(node, cpuid_in_node) == NULL)) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"current cpu is not sched cpu\n");
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"bind_cpuid,pid,gid,tid,name,kernel_tid,status,wait flag,timeout flag,pre_wakeup reason,normal wakeup reason,"
"start time(ms),max proc time(us),ave proc time(us),max sched time(us),ave sched time(us),"
"subscribe event bitmap,fwd event,sched event,timeout cnt,discard cnt\n");
if (ret >= 0) {
offset += ret;
}
pid_list_for_each_handle(buf, &offset, sched_sysfs_node_proc_thread_info);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_cpu_sched_track_format(struct sched_cpu_sched_trace *sched_trace,
char *buf, u32 buf_len, u32 start_index, u32 num, u64 *last_timestamp)
{
u32 i, idx;
int32_t ret;
u64 timestamp, use_time;
u64 callback_time = 0;
int32_t record_finish_flag = SCHED_INVALID;
ssize_t offset = 0;
struct sched_cpu_sched_thread *sched_thread = NULL;
timestamp = *last_timestamp;
for (i = 0; i < num; i++) {
idx = (u32)((start_index + i) & SCHED_SWICH_THREAD_NUM_MASK);
sched_thread = &sched_trace->sched_thread_list[idx];
if (sched_thread->sched_timestamp == 0) {
continue;
}
if ((sched_thread->sched_timestamp - timestamp) != 0) {
use_time = tick_to_microsecond(sched_thread->sched_timestamp - timestamp);
if (use_time > 5) {
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1, "idle,(%llu) -->\n", use_time);
if (ret >= 0) {
offset += ret;
}
}
}
if (sched_thread->finish_timestamp == 0) {
record_finish_flag = SCHED_VALID;
use_time = tick_to_microsecond(sched_get_cur_timestamp() - sched_thread->sched_timestamp);
callback_time = tick_to_microsecond(sched_get_cur_timestamp() - sched_thread->finish_timestamp);
} else {
use_time = tick_to_microsecond(sched_thread->finish_timestamp - sched_thread->sched_timestamp);
callback_time = tick_to_microsecond(sched_thread->callback_timestamp - sched_thread->finish_timestamp);
}
ret = snprintf_s(buf + offset, buf_len - offset, buf_len - offset - 1,
"(%u)(%llu,%llu,%llu): (%d %u %u %u),(%u %u),(%d),(%llu),(%u,%llu,%llu,%llu) -->\n",
idx, sched_thread->sched_timestamp, sched_thread->publish_timestamp,
sched_thread->add_queue_list_timestamp, sched_thread->pid, sched_thread->gid, sched_thread->tid,
sched_thread->event_id, sched_thread->pid_pri, sched_thread->event_pri, sched_thread->normal_wakeup_reason,
use_time, sched_thread->cur_event_num, tick_to_microsecond(sched_thread->wait_time),
tick_to_microsecond(sched_thread->waked_to_wakeup_time), callback_time);
if (ret >= 0) {
offset += ret;
}
timestamp = sched_thread->finish_timestamp;
if (record_finish_flag == SCHED_VALID) {
break;
}
sched_thread->sched_timestamp = 0;
}
*last_timestamp = timestamp;
return offset;
}
STATIC void sched_cpu_trace_record(struct sched_cpu_ctx *cpu_ctx,
u64 trace_num, const struct sched_trace_record_info *trace_record)
{
static char sched_sysfs_buf[KA_MM_PAGE_SIZE];
ka_file_t *fp = NULL;
char buf[MAX_LENTH];
loff_t offset_tmp = 0;
int32_t ret;
u32 i, start_index;
u64 timestamp = 0;
ret = snprintf_s(buf, MAX_LENTH, MAX_LENTH - 1, "%s/cpu_%d_%s_%s_%llu",
SCHED_FILE_PATH, cpu_ctx->cpuid, trace_record->record_reason, trace_record->key, trace_record->timestamp);
if (ret < 0) {
sched_err("Failed to invoke the snprintf_s.\n");
return;
}
fp = ka_fs_filp_open(buf, KA_O_RDWR | KA_O_TRUNC | KA_O_CREAT, SCHED_FILE_MODE);
if (KA_IS_ERR(fp)) {
sched_err("Failed to invoke the filp_open. (buf=\"%s\")\n", buf);
return;
}
ret = snprintf_s(sched_sysfs_buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "cpuid %d thread schedule track\n"
"(index)(sched timestamp,publish timestamp,add list timestamp): (pid gid tid event),(pid pri, event pri),"
"(wakeup reason),(use time(us)),(cpu cur event num, sched wait time(us),waked to wakeup time(us),"
"callback time(us)) -->\n",
cpu_ctx->cpuid);
if (ret > 0) {
sched_sysfs_write_file(fp, (const void *)sched_sysfs_buf, ka_base_strlen(sched_sysfs_buf), &offset_tmp);
}
sched_debug("Show details. (cpuid=%u; trace_num=%llu)\n", cpu_ctx->cpuid, trace_num);
for (i = 0; i < SCHED_SWICH_THREAD_RECORD_NUM; i += SCHED_SWICH_THREAD_SHOW_NUM) {
start_index = (trace_num - SCHED_SWICH_THREAD_RECORD_NUM + i) & SCHED_SWICH_THREAD_NUM_MASK;
ret = sched_sysfs_node_cpu_sched_track_format(cpu_ctx->sched_trace, sched_sysfs_buf, KA_MM_PAGE_SIZE,
start_index, SCHED_SWICH_THREAD_SHOW_NUM, ×tamp);
if (ret > 0) {
sched_sysfs_write_file(fp, (const void *)sched_sysfs_buf, ka_base_strlen(sched_sysfs_buf), &offset_tmp);
}
}
(void)ka_fs_filp_close(fp, NULL);
}
void sched_trace_record(struct sched_numa_node *node, struct sched_trace_record_info *trace_record)
{
u32 i;
struct sched_cpu_ctx *cpu_ctx = NULL;
for (i = 0; i < node->sched_cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
if (cpu_ctx->sched_trace != NULL) {
sched_cpu_trace_record(cpu_ctx, cpu_ctx->sched_trace->trace_num, trace_record);
}
}
}
STATIC ssize_t sched_sysfs_node_cpu_sched_track(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
struct sched_cpu_ctx *cpu_ctx = NULL;
int32_t ret;
u32 start_index;
ssize_t offset = 0;
u64 timestamp = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "cpuid %d thread schedule track\n"
"(index)timestamp: (pid gid tid event),(use time(us)),(cpu cur event num, sched wait time(us),"
"waked to wakeup time(us), callback time(us)) -->\n",
cpuid_in_node);
if (ret >= 0) {
offset += ret;
}
cpu_ctx = sched_get_cpu_ctx(node, cpuid_in_node);
if (((cpu_ctx == NULL) || (cpu_ctx->sched_trace == NULL))) {
esched_dev_put(node);
return offset;
}
start_index = (cpu_ctx->sched_trace->trace_num - SCHED_SWICH_THREAD_SHOW_NUM) & SCHED_SWICH_THREAD_NUM_MASK;
offset += sched_sysfs_node_cpu_sched_track_format(cpu_ctx->sched_trace, buf + offset, KA_MM_PAGE_SIZE - offset,
start_index, SCHED_SWICH_THREAD_SHOW_NUM, ×tamp);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_pid_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u\n", cur_pid);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t sched_sysfs_pid_write(ka_device_t *dev, ka_device_attribute_t *attr, const char *buf, size_t count)
{
int32_t val = 0;
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
sched_err("Dev not valid. (devid=%u)\n", g_node_id);
return count;
}
if (ka_base_kstrtou32(buf, 0, (u32 *)&val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
esched_dev_put(node);
return count;
}
proc_ctx = esched_proc_get(node, val);
if (proc_ctx == NULL) {
sched_err("The pid is invalid. (pid=%d)\n", val);
esched_dev_put(node);
return count;
}
cur_pid = (u32)val;
node->sample_proc_id = val;
esched_proc_put(proc_ctx);
esched_dev_put(node);
sched_info("Set pid %d.\n", val);
return count;
}
STATIC ssize_t sched_sysfs_proc_status(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_proc_ctx *proc_ctx = NULL;
char *msg = "normal";
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
proc_ctx = esched_proc_get(node, cur_pid);
if (proc_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d invalid. can not find in node %u.\n", cur_pid, node->node_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
if (proc_ctx->status == SCHED_INVALID) {
msg = "deleting";
}
esched_proc_put(proc_ctx);
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%s\n", msg);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_proc_pri(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
proc_ctx = esched_proc_get(node, cur_pid);
if (proc_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %u invalid. can not find in node %u.\n", cur_pid, node->node_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u\n", proc_ctx->pri);
if (ret >= 0) {
offset += ret;
}
esched_proc_put(proc_ctx);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_proc_event_num(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
proc_ctx = esched_proc_get(node, cur_pid);
if (proc_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d invalid. can not find in node %u.\n", cur_pid, node->node_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "publish,schedule\n");
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%d,%d\n",
ka_base_atomic_read(&proc_ctx->publish_event_num), ka_base_atomic_read(&proc_ctx->sched_event_num));
if (ret >= 0) {
offset += ret;
}
esched_proc_put(proc_ctx);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_proc_event_pri(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
proc_ctx = esched_proc_get(node, cur_pid);
if (proc_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d invalid. can not find in node %u.\n", cur_pid, node->node_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "event id,pri\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_EVENT_TYPE_NUM; i++) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u,%u\n",
i, proc_ctx->event_pri[i]);
if (ret >= 0) {
offset += ret;
}
}
esched_proc_put(proc_ctx);
esched_dev_put(node);
return offset;
}
STATIC void sched_sysfs_info_to_log(int32_t pid, char *buf, u32 mode, ssize_t offset, ssize_t size)
{
}
STATIC ssize_t sched_sysfs_node_proc_group_list_inner(struct sched_numa_node *node, int32_t pid, char *buf, u32 mode)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_grp_ctx *grp_ctx = NULL;
char *sched_mode = NULL;
proc_ctx = esched_proc_get(node, pid);
if (proc_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d invalid. can not find in chip %d\n", pid, node->node_id);
if (ret >= 0) {
offset += ret;
}
sched_sysfs_info_to_log(pid, buf, mode, offset, ret);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"group,sched type,is_exclusive,thread num,run status,wait cpu mask,tid, cur event num\n");
if (ret >= 0) {
offset += ret;
sched_sysfs_info_to_log(pid, buf, mode, offset, ret);
}
for (i = 0; i < SCHED_MAX_GRP_NUM; i++) {
grp_ctx = sched_get_grp_ctx(proc_ctx, i);
if (grp_ctx->sched_mode == SCHED_MODE_UNINIT) {
continue;
} else if (grp_ctx->sched_mode == SCHED_MODE_SCHED_CPU) {
sched_mode = "sched";
} else {
sched_mode = "non sched";
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u,%s,%u,%u,%d,0x%x,%u,%d\n",
i, sched_mode, grp_ctx->is_exclusive, grp_ctx->thread_num,
ka_base_atomic_read(&grp_ctx->run_status), ka_base_atomic_read(&grp_ctx->wait_cpu_mask),
grp_ctx->cur_tid, ka_base_atomic_read(&grp_ctx->cur_event_num));
if (ret >= 0) {
sched_sysfs_info_to_log(pid, buf + offset, mode, offset, ret);
offset += ret;
}
}
esched_proc_put(proc_ctx);
return offset;
}
STATIC ssize_t sched_sysfs_node_proc_group_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
ssize_t offset = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node != NULL) {
offset = sched_sysfs_node_proc_group_list_inner(node, cur_pid, buf, INFO_TO_SYSFS);
esched_dev_put(node);
}
return offset;
}
STATIC ssize_t sched_sysfs_proc_group_id_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u\n", cur_gid);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t sched_sysfs_proc_group_id_write(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
if (val >= SCHED_MAX_GRP_NUM) {
sched_err("The gid is out of range. (gid=%u; max=%d)\n", val, SCHED_MAX_GRP_NUM);
return count;
}
cur_gid = val;
sched_info("Set proc_group_id %u.\n", val);
return count;
}
static struct sched_grp_ctx *sched_sysfs_cur_grp_get(struct sched_numa_node *node)
{
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_grp_ctx *grp_ctx = NULL;
proc_ctx = esched_proc_get(node, cur_pid);
if (proc_ctx == NULL) {
return NULL;
}
grp_ctx = sched_get_grp_ctx(proc_ctx, cur_gid);
if (grp_ctx->sched_mode == SCHED_MODE_UNINIT) {
esched_proc_put(proc_ctx);
return NULL;
}
return grp_ctx;
}
static void sched_sysfs_cur_grp_put(struct sched_grp_ctx *grp_ctx)
{
esched_proc_put(grp_ctx->proc_ctx);
}
STATIC ssize_t sched_sysfs_node_proc_group_event_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
u32 i, j;
int32_t ret;
ssize_t offset = 0;
struct sched_grp_ctx *grp_ctx = NULL;
struct sched_event_thread_map *event_thread_map = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
grp_ctx = sched_sysfs_cur_grp_get(node);
if (grp_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d gid %d invalid. can not find in node %u.\n", cur_pid, cur_gid, node->node_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"event id,thread num(thread list),max_event_num,event_num,drop_event_num\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_EVENT_TYPE_NUM; i++) {
event_thread_map = &grp_ctx->event_thread_map[i];
if (event_thread_map->thread_num == 0) {
continue;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u,%u(%u",
i, event_thread_map->thread_num, event_thread_map->thread[0]);
if (ret >= 0) {
offset += ret;
}
for (j = 1; j < event_thread_map->thread_num; j++) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, ",%u",
event_thread_map->thread[j]);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "),%u,%u,%u\n",
grp_ctx->max_event_num[i], ka_base_atomic_read(&grp_ctx->event_num[i]), ka_base_atomic_read(&grp_ctx->drop_event_num[i]));
if (ret >= 0) {
offset += ret;
}
}
sched_sysfs_cur_grp_put(grp_ctx);
esched_dev_put(node);
return offset;
}
STATIC ssize_t sched_sysfs_node_proc_group_thread_inner(struct sched_grp_ctx *grp_ctx, char *buf, int32_t mode)
{
u32 i;
int32_t ret;
ssize_t offset = 0;
struct sched_thread_ctx *thread_ctx = NULL;
if (grp_ctx->sched_mode == SCHED_MODE_SCHED_CPU) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"bind_cpuid,pid,gid,tid,name,kernel_tid,status,wait flag,timeout flag,pre_wakeup reason,normal wakeup reason,"
"start time(ms),max proc time(us),ave proc time(us),max sched time(us),ave sched time(us),"
"subscribe event bitmap,fwd event,sched event,timeout cnt,discard cnt\n");
} else {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"tid,name,kernel_tid,status,wait flag,start time(ms),max proc time(us),ave proc time(us),"
"max sched time(us),ave sched time(us),subscribe event bitmap,queue remain event,sched event,"
"publish enque full\n");
}
if (ret >= 0) {
sched_sysfs_info_to_log(grp_ctx->pid, buf + offset, mode, offset, ret);
offset += ret;
}
for (i = 0; i < grp_ctx->cfg_thread_num; i++) {
thread_ctx = sched_get_thread_ctx(grp_ctx, i);
if (thread_ctx->valid == SCHED_INVALID) {
continue;
}
ret = sched_sysfs_node_proc_single_thread_info(buf, thread_ctx, grp_ctx, &offset, i);
if (ret < 0) {
break;
}
sched_sysfs_info_to_log(grp_ctx->pid, buf + offset - ret, mode, offset, ret);
}
return offset;
}
STATIC ssize_t sched_sysfs_node_proc_group_thread(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
struct sched_grp_ctx *grp_ctx = NULL;
ssize_t offset = 0;
ssize_t ret;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
grp_ctx = sched_sysfs_cur_grp_get(node);
if (grp_ctx == NULL) {
int count;
count = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d gid %d invalid. can not find in node %u.\n", cur_pid, cur_gid, node->node_id);
if (count >= 0) {
offset += count;
}
esched_dev_put(node);
return offset;
}
ret = sched_sysfs_node_proc_group_thread_inner(grp_ctx, buf, INFO_TO_SYSFS);
sched_sysfs_cur_grp_put(grp_ctx);
esched_dev_put(node);
return ret;
}
void sched_sysfs_show_proc_info(u32 chip_id, int32_t pid)
{
struct sched_proc_ctx *proc_ctx = NULL;
struct sched_grp_ctx *grp_ctx = NULL;
char *buf = NULL;
int32_t i;
struct sched_numa_node *node = NULL;
node = sched_get_numa_node(chip_id);
if (node == NULL) {
return;
}
proc_ctx = esched_proc_get(node, pid);
if (proc_ctx == NULL) {
sched_warn("The variable node_id or pid is invalid. (node_id=%u; pid=%d)\n", node->node_id, pid);
return;
}
buf = (char *)sched_kzalloc(sizeof(char) * KA_MM_PAGE_SIZE, KA_GFP_KERNEL);
if (buf == NULL) {
esched_proc_put(proc_ctx);
return;
}
(void)sched_sysfs_node_proc_group_list_inner(node, pid, buf, INFO_TO_LOG);
for (i = 0; i < SCHED_MAX_GRP_NUM; i++) {
grp_ctx = sched_get_grp_ctx(proc_ctx, i);
if (grp_ctx->sched_mode == SCHED_MODE_UNINIT) {
continue;
}
(void)sched_sysfs_node_proc_group_thread_inner(grp_ctx, buf, INFO_TO_LOG);
}
esched_proc_put(proc_ctx);
sched_kfree(buf);
buf = NULL;
}
STATIC ssize_t sched_sysfs_group_cur_event_num(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret, i;
ssize_t offset = 0;
struct sched_grp_ctx *grp_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
grp_ctx = sched_sysfs_cur_grp_get(node);
if (grp_ctx == NULL) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d gid %d invalid. can not find in node %u.\n", cur_pid, cur_gid, node->node_id);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
if (grp_ctx->sched_mode != SCHED_MODE_NON_SCHED_CPU) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"pid %d gid %d mode is invalid, cur_mode %d.\n", cur_pid, cur_gid, grp_ctx->sched_mode);
if (ret >= 0) {
offset += ret;
}
sched_sysfs_cur_grp_put(grp_ctx);
esched_dev_put(node);
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"node_id %d pid %d gid %d current event num: %u\n\npid gid event_pri event_num\n",
node->node_id, cur_pid, cur_gid, ka_base_atomic_read(&grp_ctx->cur_event_num));
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < SCHED_MAX_EVENT_PRI_NUM; i++) {
struct sched_event_list *event_list = NULL;
struct sched_event *event = NULL;
event_list = sched_get_non_sched_event_list(grp_ctx, i);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"%d,%u,%d,%u\n", cur_pid, cur_gid, i, event_list->cur_num);
if (ret >= 0) {
offset += ret;
}
ka_task_spin_lock_bh(&event_list->lock);
ka_list_for_each_entry(event, &event_list->head, list) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
" %u,%u\n", event->event_id, event->subevent_id);
if (ret >= 0) {
offset += ret;
}
}
ka_task_spin_unlock_bh(&event_list->lock);
}
sched_sysfs_cur_grp_put(grp_ctx);
esched_dev_put(node);
return offset;
}
#ifdef CFG_FEATURE_VFIO
void sched_get_vf_proc_list(char *buf, ssize_t *offset, struct sched_proc_ctx *proc_ctx)
{
int ret;
if ((u32)proc_ctx->vfid == g_cur_vf) {
ret = snprintf_s(buf + *offset, KA_MM_PAGE_SIZE - *offset, KA_MM_PAGE_SIZE - *offset - 1, "%ld, %s\n",
proc_ctx->pid, proc_ctx->name);
if (ret >= 0) {
*offset += ret;
}
}
}
ssize_t sched_sysfs_node_vf_proc_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_vf_ctx *vf_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
if (g_cur_vf == SCHED_DEFAULT_VF_ID) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"vf_0 (used by physical machine) is not supported\n");
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
vf_ctx = sched_get_vf_ctx(node, g_cur_vf);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"vf_%u (status: %u) have %u valid proc.\n", g_cur_vf, ka_base_atomic_read(&vf_ctx->status),
ka_base_atomic_read(&vf_ctx->proc_num));
if (ret >= 0) {
offset += ret;
}
pid_list_for_each_handle(buf, &offset, sched_get_vf_proc_list);
esched_dev_put(node);
return offset;
}
ssize_t sched_sysfs_node_vf_list(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret, i;
ssize_t offset = 0;
struct sched_vf_ctx *vf_ctx = NULL;
char *msg = "normal";
int vf_status;
u64 total_sched_cpu_mask = 0;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "vf_id, status, resource_packet_num.\n");
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < VMNG_VDEV_MAX_PER_PDEV; i++) {
vf_ctx = sched_get_vf_ctx(node, i);
vf_status = ka_base_atomic_read(&vf_ctx->status);
switch (vf_status) {
case SCHED_VF_STATUS_UNCREATED:
msg = "not_created";
break;
case SCHED_VF_STATUS_NORMAL:
msg = "normal";
total_sched_cpu_mask += vf_ctx->config_sched_cpu_mask;
break;
case SCHED_VF_STATUS_DELETING:
msg = "deleting";
break;
default:
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"vf_%d unknown status: %d.\n", i, vf_status);
break;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%5d, %s, %llx.\n", i, msg,
vf_ctx->config_sched_cpu_mask);
if (ret >= 0) {
offset += ret;
}
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"total used resource packet num: %llx.\n", total_sched_cpu_mask);
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ssize_t sched_sysfs_vfid_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "%u\n", g_cur_vf);
if (ret >= 0) {
offset += ret;
}
return offset;
}
ssize_t sched_sysfs_vfid_write(ka_device_t *dev, ka_device_attribute_t *attr, const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
if (val >= VMNG_VDEV_MAX_PER_PDEV) {
sched_err("The vfid is out of range. (vfid=%u)\n", val);
return count;
}
g_cur_vf = val;
sched_info("Set vfid %u.\n", val);
return count;
}
ssize_t sched_sysfs_vf_info_show(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
struct sched_vf_ctx *vf_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
if (g_cur_vf == SCHED_DEFAULT_VF_ID) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"vf_0 (used by physical machine) is not supported\n");
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
vf_ctx = sched_get_vf_ctx(node, g_cur_vf);
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "vf_ctx %u info show: \n"
"vf_id: %u \nstatus: %u \ncreate timestamp: %llu \n"
"proc num: %u \nque depth: %u \nconfig_sched_cpu_mask: 0x%llx \nsched_cpu_mask: 0x%llx",
g_cur_vf, vf_ctx->vfid, ka_base_atomic_read(&vf_ctx->status), vf_ctx->create_timestamp,
ka_base_atomic_read(&vf_ctx->proc_num), vf_ctx->que_depth, vf_ctx->config_sched_cpu_mask, vf_ctx->sched_cpu_mask);
if (ret >= 0) {
offset += ret;
}
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "\n\nvf_ctx: %u stat show \n"
"publish event num: %llu \nsched event num: %llu \ncur event num: %llu \n\n", g_cur_vf,
ka_base_atomic64_read(&vf_ctx->stat.publish_event_num), ka_base_atomic64_read(&vf_ctx->stat.sched_event_num),
ka_base_atomic64_read(&vf_ctx->stat.cur_event_num));
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
ssize_t sched_sysfs_vf_occupy_cpu(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
u32 i;
u64 config_sched_cpu_mask;
ssize_t offset = 0;
struct sched_vf_ctx *vf_ctx = NULL;
struct sched_cpu_ctx *cpu_ctx = NULL;
struct sched_thread_ctx *thread_ctx = NULL;
struct sched_numa_node *node = esched_dev_get(g_node_id);
if (node == NULL) {
return offset;
}
if (g_cur_vf == SCHED_DEFAULT_VF_ID) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"vf_0 (used by physical machine) is not supported\n");
if (ret >= 0) {
offset += ret;
}
esched_dev_put(node);
return offset;
}
vf_ctx = sched_get_vf_ctx(node, g_cur_vf);
config_sched_cpu_mask = vf_ctx->config_sched_cpu_mask;
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1, "vf %u(status %u) max occupy aicpu\n"
"config sched cpu mask: 0x%llx sched cpu mask: 0x%llx\n", g_cur_vf, ka_base_atomic_read(&vf_ctx->status),
config_sched_cpu_mask, vf_ctx->sched_cpu_mask);
if (ret >= 0) {
offset += ret;
}
for (i = 0; i < node->sched_cpu_num; i++) {
cpu_ctx = sched_get_cpu_ctx(node, node->sched_cpuid[i]);
thread_ctx = esched_cpu_cur_thread_get(cpu_ctx);
if (thread_ctx == NULL) {
continue;
}
if (config_sched_cpu_mask & (0x1ULL << node->sched_cpuid[i])) {
ret = snprintf_s(buf + offset, KA_MM_PAGE_SIZE - offset, KA_MM_PAGE_SIZE - offset - 1,
"aicpu:%u, pid:%d(%s), gid:%u, tid:%u\n",
cpu_ctx->cpuid, thread_ctx->grp_ctx->pid, thread_ctx->grp_ctx->proc_ctx->name,
thread_ctx->grp_ctx->gid, thread_ctx->tid);
if (ret >= 0) {
offset += ret;
}
}
esched_cpu_cur_thread_put(thread_ctx);
}
esched_dev_put(node);
return offset;
}
#endif
#define SCHED_RECORD_DEFAULT_NUM 1000
#define SCHED_SYSFS_RECORD_MAX_NUM 65536
static uint32_t sched_sysfs_record_num = SCHED_RECORD_DEFAULT_NUM;
STATIC ssize_t sched_sysfs_record_num_read(ka_device_t *dev, ka_device_attribute_t *attr, char *buf)
{
int32_t ret;
ssize_t offset = 0;
ret = snprintf_s(buf, KA_MM_PAGE_SIZE, KA_MM_PAGE_SIZE - 1, "%u\n", sched_sysfs_record_num);
if (ret >= 0) {
offset += ret;
}
return offset;
}
STATIC ssize_t sched_sysfs_record_num_write(ka_device_t *dev, ka_device_attribute_t *attr,
const char *buf, size_t count)
{
u32 val = 0;
if (ka_base_kstrtou32(buf, 0, &val) < 0) {
sched_err("Failed to invoke the kstrtou32.\n");
return count;
}
if ((val > SCHED_SYSFS_RECORD_MAX_NUM) || (val == 0)) {
sched_err("The value of variable record_num is out of range. "
"(record_num=%u; max=%d)\n", val, SCHED_SYSFS_RECORD_MAX_NUM);
return count;
}
sched_sysfs_record_num = val;
sched_info("Set record_num %u.\n", val);
return count;
}
uint32_t sched_sysfs_record_num_data(void)
{
return sched_sysfs_record_num;
}
#define SCHED_ATTR_RD (KA_S_IRUSR | KA_S_IRGRP | KA_S_IROTH)
#define SCHED_ATTR_WR (KA_S_IWUSR | KA_S_IWGRP)
#define SCHED_ATTR_RW (SCHED_ATTR_RD | SCHED_ATTR_WR)
#define DRV_FS_ATTR KA_DRIVER_DEVICE_ATTR
#define DRV_FS_ATTR_NAME_POINTER(_name) &dev_attr_##_name.attr
#define DECLEAR_ESCHED_FS_ATTR \
static DRV_FS_ATTR(node_list, SCHED_ATTR_RD, sched_sysfs_node_list, NULL); \
static DRV_FS_ATTR(node_id, SCHED_ATTR_RW, sched_sysfs_node_id_read, sched_sysfs_node_id_write); \
static DRV_FS_ATTR(node_debug, SCHED_ATTR_RW, sched_sysfs_node_debug_read, sched_sysfs_node_debug_write); \
static DRV_FS_ATTR(cpu_list, SCHED_ATTR_RD, sched_sysfs_node_cpu_list, NULL); \
static DRV_FS_ATTR(sched_cpu_mask, SCHED_ATTR_RD, sched_sysfs_node_sched_cpu_mask, NULL); \
static DRV_FS_ATTR(proc_list, SCHED_ATTR_RD, sched_sysfs_node_proc_list, NULL); \
static DRV_FS_ATTR(proc_list_del, SCHED_ATTR_RD, sched_sysfs_node_del_proc_list, NULL); \
static DRV_FS_ATTR(node_event_resource, SCHED_ATTR_RD, sched_sysfs_node_event_resource, NULL); \
static DRV_FS_ATTR(event_trace, SCHED_ATTR_RD, sched_sysfs_event_trace, NULL); \
static DRV_FS_ATTR(sample_period, SCHED_ATTR_RW, sched_sysfs_sample_period_read, sched_sysfs_sample_period_write); \
static DRV_FS_ATTR(event_sample, SCHED_ATTR_RD, sched_sysfs_event_sample, NULL); \
static DRV_FS_ATTR(cpu_usage_sample, SCHED_ATTR_RD, sched_sysfs_cpu_usage_sample, NULL); \
static DRV_FS_ATTR(node_sched_proc_abnormal_time_in_microsecond, SCHED_ATTR_RW, \
sched_sysfs_node_sched_proc_abnormal_time_read, sched_sysfs_node_sched_proc_abnormal_time_write); \
static DRV_FS_ATTR(node_sched_abnormal_event_clear, SCHED_ATTR_WR, \
NULL, sched_sysfs_node_sched_abnormal_event_clear); \
static DRV_FS_ATTR(node_sched_proc_abnormal_event, SCHED_ATTR_RD, \
sched_sysfs_node_sched_proc_abnormal_event, NULL); \
static DRV_FS_ATTR(node_sched_publish_syscall_abnormal_time_in_microsecond, SCHED_ATTR_RW, \
sched_sysfs_node_sched_publish_syscall_abnormal_time_read, \
sched_sysfs_node_sched_publish_syscall_abnormal_time_write); \
static DRV_FS_ATTR(node_sched_publish_syscall_abnormal_event, SCHED_ATTR_RD, \
sched_sysfs_node_sched_publish_syscall_abnormal_event, NULL); \
static DRV_FS_ATTR(node_sched_publish_in_kernel_abnormal_time_in_microsecond, SCHED_ATTR_RW, \
sched_sysfs_node_sched_publish_in_kernel_abnormal_time_read, \
sched_sysfs_node_sched_publish_in_kernel_abnormal_time_write); \
static DRV_FS_ATTR(node_sched_publish_in_kernel_abnormal_event, SCHED_ATTR_RD, \
sched_sysfs_node_sched_publish_in_kernel_abnormal_event, NULL); \
static DRV_FS_ATTR(node_sched_wakeup_abnormal_time_in_microsecond, SCHED_ATTR_RW, \
sched_sysfs_node_sched_wakeup_abnormal_time_read, sched_sysfs_node_sched_wakeup_abnormal_time_write); \
static DRV_FS_ATTR(node_sched_wakeup_abnormal_event, SCHED_ATTR_RD, \
sched_sysfs_node_sched_wakeup_abnormal_event, NULL); \
static DRV_FS_ATTR(node_sched_publish_subscribe_abnormal_time_in_microsecond, SCHED_ATTR_RW, \
sched_sysfs_node_sched_publish_subscribe_abnormal_time_read, \
sched_sysfs_node_sched_publish_subscribe_abnormal_time_write); \
static DRV_FS_ATTR(node_sched_publish_subscribe_abnormal_event, SCHED_ATTR_RD, \
sched_sysfs_node_sched_publish_subscribe_abnormal_event, NULL); \
static DRV_FS_ATTR(node_sched_thread_run_abnormal_time_in_microsecond, SCHED_ATTR_RW, \
sched_sysfs_node_sched_thread_run_abnormal_time_read, \
sched_sysfs_node_sched_thread_run_abnormal_time_write); \
static DRV_FS_ATTR(node_sched_thread_run_abnormal_event, SCHED_ATTR_RD, \
sched_sysfs_node_sched_thread_run_abnormal_event, NULL); \
static DRV_FS_ATTR(node_event_summary, SCHED_ATTR_RD, sched_sysfs_node_event_summary, NULL); \
static DRV_FS_ATTR(node_sched_event_list, SCHED_ATTR_RD, sched_sysfs_node_sched_event_list, NULL); \
static DRV_FS_ATTR(node_cur_event_num, SCHED_ATTR_RD, sched_sysfs_node_cur_event_num, NULL); \
static DRV_FS_ATTR(cpuid_in_node, SCHED_ATTR_RW, sched_sysfs_node_cpuid_read, sched_sysfs_node_cpuid_write); \
static DRV_FS_ATTR(cpu_cur_thread, SCHED_ATTR_RD, sched_sysfs_node_cpu_cur_thread, NULL); \
static DRV_FS_ATTR(cpu_event_resource, SCHED_ATTR_RD, sched_sysfs_node_cpu_event_resource, NULL); \
static DRV_FS_ATTR(cpu_sched_track, SCHED_ATTR_RD, sched_sysfs_node_cpu_sched_track, NULL); \
static DRV_FS_ATTR(cpu_thread_info, SCHED_ATTR_RD, sched_sysfs_node_cpu_thread_info, NULL); \
static DRV_FS_ATTR(pid, SCHED_ATTR_RW, sched_sysfs_pid_read, sched_sysfs_pid_write); \
static DRV_FS_ATTR(proc_status, SCHED_ATTR_RD, sched_sysfs_proc_status, NULL); \
static DRV_FS_ATTR(proc_pri, SCHED_ATTR_RD, sched_sysfs_proc_pri, NULL); \
static DRV_FS_ATTR(proc_event_num, SCHED_ATTR_RD, sched_sysfs_proc_event_num, NULL); \
static DRV_FS_ATTR(proc_event_pri, SCHED_ATTR_RD, sched_sysfs_node_proc_event_pri, NULL); \
static DRV_FS_ATTR(proc_group_list, SCHED_ATTR_RD, sched_sysfs_node_proc_group_list, NULL); \
static DRV_FS_ATTR(proc_gid, SCHED_ATTR_RW, sched_sysfs_proc_group_id_read, sched_sysfs_proc_group_id_write); \
static DRV_FS_ATTR(proc_group_event_list, SCHED_ATTR_RD, sched_sysfs_node_proc_group_event_list, NULL); \
static DRV_FS_ATTR(proc_group_thread, SCHED_ATTR_RD, sched_sysfs_node_proc_group_thread, NULL); \
static DRV_FS_ATTR(sched_record_num, SCHED_ATTR_RW, sched_sysfs_record_num_read, sched_sysfs_record_num_write); \
static DRV_FS_ATTR(proc_group_cur_event_num, SCHED_ATTR_RD, sched_sysfs_group_cur_event_num, NULL)
#ifdef CFG_FEATURE_VFIO
#define DECLEAR_ESCHED_FS_VFIO_ATTR \
static DRV_FS_ATTR(vfid, SCHED_ATTR_RW, sched_sysfs_vfid_read, sched_sysfs_vfid_write); \
static DRV_FS_ATTR(vf_list, SCHED_ATTR_RD, sched_sysfs_node_vf_list, NULL); \
static DRV_FS_ATTR(vf_proc_list, SCHED_ATTR_RD, sched_sysfs_node_vf_proc_list, NULL); \
static DRV_FS_ATTR(vf_info_show, SCHED_ATTR_RD, sched_sysfs_vf_info_show, NULL); \
static DRV_FS_ATTR(vf_occupy_cpu, SCHED_ATTR_RD, sched_sysfs_vf_occupy_cpu, NULL)
#endif
#define DECLEAR_ESCHED_FS_ATTR_NORMAL_LIST(_struct_type, _profix) \
static struct _struct_type *g_sched_##_profix##_normal_list[] = { \
DRV_FS_ATTR_NAME_POINTER(node_list), \
DRV_FS_ATTR_NAME_POINTER(node_id), \
DRV_FS_ATTR_NAME_POINTER(node_debug), \
DRV_FS_ATTR_NAME_POINTER(cpu_list), \
DRV_FS_ATTR_NAME_POINTER(sched_cpu_mask), \
DRV_FS_ATTR_NAME_POINTER(proc_list), \
DRV_FS_ATTR_NAME_POINTER(proc_list_del), \
DRV_FS_ATTR_NAME_POINTER(node_event_resource), \
DRV_FS_ATTR_NAME_POINTER(event_trace), \
DRV_FS_ATTR_NAME_POINTER(sample_period), \
DRV_FS_ATTR_NAME_POINTER(event_sample), \
DRV_FS_ATTR_NAME_POINTER(cpu_usage_sample), \
DRV_FS_ATTR_NAME_POINTER(node_sched_abnormal_event_clear), \
DRV_FS_ATTR_NAME_POINTER(node_sched_proc_abnormal_time_in_microsecond), \
DRV_FS_ATTR_NAME_POINTER(node_sched_proc_abnormal_event), \
DRV_FS_ATTR_NAME_POINTER(node_sched_publish_syscall_abnormal_time_in_microsecond), \
DRV_FS_ATTR_NAME_POINTER(node_sched_publish_syscall_abnormal_event), \
DRV_FS_ATTR_NAME_POINTER(node_sched_publish_in_kernel_abnormal_time_in_microsecond), \
DRV_FS_ATTR_NAME_POINTER(node_sched_publish_in_kernel_abnormal_event), \
DRV_FS_ATTR_NAME_POINTER(node_sched_wakeup_abnormal_time_in_microsecond), \
DRV_FS_ATTR_NAME_POINTER(node_sched_wakeup_abnormal_event), \
DRV_FS_ATTR_NAME_POINTER(node_sched_publish_subscribe_abnormal_time_in_microsecond), \
DRV_FS_ATTR_NAME_POINTER(node_sched_publish_subscribe_abnormal_event), \
DRV_FS_ATTR_NAME_POINTER(node_sched_thread_run_abnormal_time_in_microsecond), \
DRV_FS_ATTR_NAME_POINTER(node_sched_thread_run_abnormal_event), \
DRV_FS_ATTR_NAME_POINTER(node_event_summary), \
DRV_FS_ATTR_NAME_POINTER(node_sched_event_list), \
DRV_FS_ATTR_NAME_POINTER(node_cur_event_num), \
DRV_FS_ATTR_NAME_POINTER(cpuid_in_node), \
DRV_FS_ATTR_NAME_POINTER(cpu_cur_thread), \
DRV_FS_ATTR_NAME_POINTER(cpu_event_resource), \
DRV_FS_ATTR_NAME_POINTER(cpu_sched_track), \
DRV_FS_ATTR_NAME_POINTER(cpu_thread_info), \
DRV_FS_ATTR_NAME_POINTER(pid), \
DRV_FS_ATTR_NAME_POINTER(proc_status), \
DRV_FS_ATTR_NAME_POINTER(proc_pri), \
DRV_FS_ATTR_NAME_POINTER(proc_event_num), \
DRV_FS_ATTR_NAME_POINTER(proc_event_pri), \
DRV_FS_ATTR_NAME_POINTER(proc_group_list), \
DRV_FS_ATTR_NAME_POINTER(proc_gid), \
DRV_FS_ATTR_NAME_POINTER(proc_group_event_list), \
DRV_FS_ATTR_NAME_POINTER(proc_group_thread), \
DRV_FS_ATTR_NAME_POINTER(sched_record_num), \
DRV_FS_ATTR_NAME_POINTER(proc_group_cur_event_num), \
NULL, \
}
#ifdef CFG_FEATURE_VFIO
#define DECLEAR_ESCHED_FS_VFIO_ATTR_LIST(_struct_type, _profix) \
static ka_attribute_t *g_sched_##_profix##_vfio_attrs[] = { \
DRV_FS_ATTR_NAME_POINTER(vfid), \
DRV_FS_ATTR_NAME_POINTER(vf_proc_list), \
DRV_FS_ATTR_NAME_POINTER(vf_list), \
DRV_FS_ATTR_NAME_POINTER(vf_info_show), \
DRV_FS_ATTR_NAME_POINTER(vf_occupy_cpu), \
NULL, \
}
#endif
DECLEAR_ESCHED_FS_ATTR;
DECLEAR_ESCHED_FS_ATTR_NORMAL_LIST(attribute, sysfs);
static const ka_attribute_group_t g_sched_sysfs_node_normal_group = {
.attrs = g_sched_sysfs_normal_list,
.name = "node"
};
#ifdef CFG_FEATURE_VFIO
DECLEAR_ESCHED_FS_VFIO_ATTR;
DECLEAR_ESCHED_FS_VFIO_ATTR_LIST(attribute, sysfs);
static const ka_attribute_group_t g_sched_sysfs_node_vfio_group = {
.attrs = g_sched_sysfs_vfio_attrs,
.name = "vfio"
};
#endif
void sched_sysfs_init(ka_device_t *dev)
{
int32_t ret;
int32_t node_id;
struct sched_numa_node *numa_node = NULL;
for (node_id = 0; node_id < SCHED_MAX_CHIP_NUM; node_id++) {
numa_node = sched_get_numa_node(node_id);
if (numa_node != NULL) {
sched_info("Loop details. (node_id=%d)\n", node_id);
sched_fs_set_node_id(node_id);
break;
}
}
ret = ka_sysfs_create_group(&dev->kobj, &g_sched_sysfs_node_normal_group);
sched_debug("Show details. (sysfs_create_group=\"%s\"; ret=%d)\n", g_sched_sysfs_node_normal_group.name, ret);
#ifdef CFG_FEATURE_VFIO
ret = ka_sysfs_create_group(&dev->kobj, &g_sched_sysfs_node_vfio_group);
sched_debug("Show details. (sysfs_create_group=\"%s\"; ret=%d)\n", g_sched_sysfs_node_vfio_group.name, ret);
#endif
return;
}
void sched_sysfs_uninit(ka_device_t *dev)
{
ka_sysfs_remove_group(&dev->kobj, &g_sched_sysfs_node_normal_group);
#ifdef CFG_FEATURE_VFIO
ka_sysfs_remove_group(&dev->kobj, &g_sched_sysfs_node_vfio_group);
#endif
}