Files
mkrtos-real/mkrtos_knl/knl/thread_knl.c

350 lines
11 KiB
C
Raw Normal View History

2023-09-29 01:03:19 +08:00
/**
* @file thread_knl.c
* @author ATShining (1358745329@qq.com)
2023-09-29 01:03:19 +08:00
* @brief
* @version 0.1
* @date 2023-09-29
*
* @copyright Copyright (c) 2023
*
2023-08-20 20:52:23 +08:00
*/
2024-04-27 03:47:45 +00:00
#include "app.h"
#include "arch.h"
2023-08-20 20:52:23 +08:00
#include "factory.h"
#include "globals.h"
2024-04-27 03:47:45 +00:00
#include "init.h"
#include "knl_misc.h"
2023-08-22 00:26:34 +08:00
#include "map.h"
#include "mm_wrap.h"
2025-01-25 15:29:06 +08:00
#include "mpu.h"
2024-04-27 03:47:45 +00:00
#include "printk.h"
#include "task.h"
#include "thread.h"
2024-04-01 16:10:59 +00:00
#include "thread_task_arch.h"
2024-04-27 03:47:45 +00:00
#include "types.h"
2025-02-05 14:44:49 +08:00
#include "prot.h"
2024-04-03 16:08:09 +00:00
#include <assert.h>
2024-04-01 16:10:59 +00:00
#if IS_ENABLED(CONFIG_KNL_TEST)
#include <knl_test.h>
#endif
2024-04-03 16:08:09 +00:00
#if ARCH_WORD_SIZE == 64
#include <elf64.h>
#endif
2024-04-06 16:41:37 +00:00
#if IS_ENABLED(CONFIG_MMU)
#include <vma.h>
#endif
2025-01-21 16:20:51 +08:00
#if IS_ENABLED(CONFIG_CPIO_SUPPORT)
2024-04-03 16:08:09 +00:00
#include <cpio.h>
2025-01-21 16:20:51 +08:00
#else
#include <appfs_tiny.h>
#endif
#include <boot_info.h>
2025-02-05 14:44:49 +08:00
#include "pre_cpu.h"
2024-04-01 16:10:59 +00:00
2024-04-27 03:47:45 +00:00
static uint8_t knl_msg_buf[CONFIG_CPU][THREAD_MSG_BUG_LEN];
2025-02-12 17:29:30 +08:00
static thread_fast_ipc_com_t knl_th_ipc_com;
2023-08-20 20:52:23 +08:00
static task_t knl_task;
static thread_t *init_thread;
static task_t *init_task;
2025-02-05 14:44:49 +08:00
static thread_t *knl_thread[CONFIG_CPU];
static slist_head_t del_task_head;
2025-02-05 14:44:49 +08:00
static umword_t cpu_usage[CONFIG_CPU];
static spinlock_t del_lock;
2025-03-11 17:03:30 +08:00
static umword_t cpu_usage_last_tick_val[CONFIG_CPU];
2023-08-20 20:52:23 +08:00
static void knl_main(void)
{
umword_t status;
umword_t status2;
2024-04-01 16:10:59 +00:00
printk("knl main run..\n");
while (1)
{
task_t *pos;
if (slist_is_empty(&del_task_head))
{
2024-08-07 22:51:57 +08:00
cpu_sleep();
continue;
}
status2 = spinlock_lock(&del_lock);
if (slist_is_empty(&del_task_head))
{
spinlock_set(&del_lock, status2);
continue;
}
2025-02-05 14:44:49 +08:00
// 在这里删除进程
slist_foreach_not_next(pos, &del_task_head, del_node)
{
task_t *next = slist_next_entry(pos, &del_task_head, del_node);
slist_del(&pos->del_node);
{
msg_tag_t tag;
umword_t user_id;
ipc_msg_t *msg = (ipc_msg_t *)knl_msg_buf;
2024-12-27 08:23:26 +08:00
if (pos->pid != 0)
{
2024-12-27 08:23:26 +08:00
msg->msg_buf[0] = 1; /*KILL_TASK*/
msg->msg_buf[1] = pos->pid;
msg->msg_buf[2] = 0;
if (thread_get_ipc_state(init_thread) != THREAD_IPC_ABORT)
{
2025-02-05 14:44:49 +08:00
#define PM_PROT 0x0005
#define MAGIC_NS_USERPID 0xbabababa
entry_frame_t f;
f.regs[0] = msg_tag_init4(0, 3, 0, PM_PROT).raw;
f.regs[1] = 0;
f.regs[2] = 0x2222; /*传递两个参数,没有用到,暂时用不上*/
f.regs[3] = 0x3333;
tag = thread_fast_ipc_call(init_task, &f, MAGIC_NS_USERPID);
2025-02-05 14:44:49 +08:00
if (msg_tag_get_val(tag) < 0)
{
printk("init thread comm failed, ret:%d\n", __func__, __LINE__, msg_tag_get_val(tag));
}
2024-12-27 08:23:26 +08:00
}
}
}
task_kill(pos);
pos = next;
}
spinlock_set(&del_lock, status2);
}
}
2025-02-05 14:44:49 +08:00
static inline uint32_t thread_knl_get_current_run_nr(void)
{
if (knl_thread[arch_get_current_cpu_id()] == NULL)
{
return 0;
}
return atomic_read(&knl_thread[arch_get_current_cpu_id()]->time_count);
}
/**
* cpu占用率
*/
void thread_calc_cpu_usage(void)
{
uint8_t cur_cpu_id = arch_get_current_cpu_id();
2025-03-11 17:03:30 +08:00
umword_t tick = thread_knl_get_current_run_nr();
2025-02-05 14:44:49 +08:00
if (sys_tick_cnt_get() % 1000 == 0)
{
2025-03-11 17:03:30 +08:00
mword_t calc = tick - cpu_usage_last_tick_val[cur_cpu_id];
calc = calc > 1000 ? 1000 : calc;
cpu_usage[cur_cpu_id] = 1000 - calc;
cpu_usage_last_tick_val[cur_cpu_id] = tick;
2025-02-05 14:44:49 +08:00
}
}
uint16_t cpu_get_current_usage(void)
{
return (uint16_t)cpu_usage[arch_get_current_cpu_id()];
}
2023-08-20 20:52:23 +08:00
/**
* 线
*
*/
2024-04-11 16:08:25 +00:00
void knl_init_1(void)
2023-08-20 20:52:23 +08:00
{
2025-02-05 14:44:49 +08:00
thread_t *knl_th;
2023-08-20 20:52:23 +08:00
2025-02-05 14:44:49 +08:00
knl_thread[arch_get_current_cpu_id()] = thread_get_current();
knl_th = knl_thread[arch_get_current_cpu_id()];
2025-02-12 17:29:30 +08:00
knl_th->com = &knl_th_ipc_com;
2025-02-05 14:44:49 +08:00
thread_init(knl_th, &root_factory_get()->limit, FALSE);
2023-08-27 21:25:09 +08:00
task_init(&knl_task, &root_factory_get()->limit, TRUE);
2024-04-01 16:10:59 +00:00
task_knl_init(&knl_task);
kobject_set_name(&knl_task.kobj, "tk_knl");
2025-02-05 14:44:49 +08:00
thread_knl_pf_set(knl_th, knl_main);
thread_bind(knl_th, &knl_task.kobj);
kobject_set_name(&knl_th->kobj, "th_knl");
thread_set_msg_buf(knl_th, knl_msg_buf[arch_get_current_cpu_id()],
2024-04-27 03:47:45 +00:00
knl_msg_buf[arch_get_current_cpu_id()]);
2025-02-05 14:44:49 +08:00
knl_th->cpu = arch_get_current_cpu_id();
thread_ready(knl_th, FALSE);
2023-08-20 20:52:23 +08:00
}
2023-08-22 00:26:34 +08:00
INIT_STAGE1(knl_init_1);
2023-08-26 23:12:31 +08:00
2025-02-05 14:44:49 +08:00
/**
* 线
*/
bool_t thread_is_knl(thread_t *thread)
{
if (thread == knl_thread[arch_get_current_cpu_id()])
return TRUE;
else
return FALSE;
}
2023-08-20 20:52:23 +08:00
/**
* init线程
*
*
* init进程
*/
2023-08-22 00:26:34 +08:00
static void knl_init_2(void)
2023-08-20 20:52:23 +08:00
{
mm_trace();
2024-04-11 16:08:25 +00:00
slist_init(&del_task_head);
2024-04-01 16:10:59 +00:00
#if IS_ENABLED(CONFIG_KNL_TEST)
knl_test();
#else
2024-04-03 16:08:09 +00:00
umword_t ret_addr;
2024-04-04 16:51:29 +00:00
size_t size;
2024-04-03 16:08:09 +00:00
init_thread = thread_create(&root_factory_get()->limit, FALSE);
2024-04-04 16:51:29 +00:00
assert(init_thread);
2024-04-27 03:47:45 +00:00
init_task = task_create(&root_factory_get()->limit, FALSE);
2024-04-04 16:51:29 +00:00
assert(init_task);
#if IS_ENABLED(CONFIG_ELF_LAUNCH)
addr_t entry;
2025-01-21 16:20:51 +08:00
#if IS_ENABLED(CONFIG_CPIO_SUPPORT)
2024-04-10 17:08:21 +00:00
ret_addr = cpio_find_file(cpio_images, (umword_t)(-1), "init", &size);
2025-01-21 16:20:51 +08:00
#else
ret_addr = appfs_find_file_addr_by_name(appfs_get_form_addr((void *)(cpio_images)), "init", &size);
#endif
2024-04-03 16:08:09 +00:00
assert(ret_addr);
2024-04-04 16:51:29 +00:00
elf_load(init_task, ret_addr, size, &entry);
void *init_msg_buf = mm_buddy_alloc_one_page();
assert(init_msg_buf);
2024-04-06 16:41:37 +00:00
assert(task_vma_alloc(&init_task->mm_space.mem_vma,
2024-04-07 15:04:30 +00:00
vma_addr_create(VPAGE_PROT_RW, VMA_ADDR_RESV, CONFIG_MSG_BUF_VADDR),
2024-04-06 16:41:37 +00:00
PAGE_SIZE, (paddr_t)init_msg_buf, 0) >= 0);
2024-04-07 15:04:30 +00:00
assert(task_vma_alloc(&init_task->mm_space.mem_vma,
vma_addr_create(VPAGE_PROT_RO, VMA_ADDR_RESV, CONFIG_BOOT_FS_VADDR),
cpio_get_size(cpio_images), (paddr_t)cpio_images, 0) >= 0);
2024-04-09 16:07:36 +00:00
thread_set_msg_buf(init_thread, (void *)init_msg_buf, (void *)CONFIG_MSG_BUF_VADDR);
thread_user_pf_set(init_thread, (void *)(entry), (void *)0xdeaddead,
2024-12-27 08:23:26 +08:00
NULL);
2024-04-04 16:51:29 +00:00
#else
app_info_t *app;
2025-01-21 16:20:51 +08:00
#if IS_ENABLED(CONFIG_CPIO_SUPPORT)
ret_addr = cpio_find_file(arch_get_boot_info()->flash_layer.flash_layer_list[BOOTFS_LAYER_3].st_addr, (umword_t)(-1), "init", &size);
2025-01-21 16:20:51 +08:00
#else
ret_addr = appfs_find_file_addr_by_name(appfs_get_form_addr((void *)(arch_get_boot_info()->flash_layer.flash_layer_list[BOOTFS_LAYER_3].st_addr)), "init", &size);
#endif
assert(ret_addr);
app = app_info_get((void *)(ret_addr));
2024-04-10 17:08:21 +00:00
assert(app);
printk("init task text is 0x%x.\n", app);
2024-04-04 16:51:29 +00:00
// 申请init的ram内存
2024-12-29 21:50:20 +08:00
assert(task_alloc_base_ram(init_task, &root_factory_get()->limit, app->i.ram_size + THREAD_MSG_BUG_LEN, 0) >= 0);
2024-04-04 16:51:29 +00:00
void *sp_addr = (char *)init_task->mm_space.mm_block + app->i.stack_offset - app->i.data_offset;
void *sp_addr_top = (char *)sp_addr + app->i.stack_size;
2024-04-09 16:07:36 +00:00
thread_set_msg_buf(init_thread, (char *)(init_task->mm_space.mm_block) + app->i.ram_size, (char *)(init_task->mm_space.mm_block) + app->i.ram_size);
thread_user_pf_set(init_thread, (void *)(app), (void *)((umword_t)sp_addr_top - 8),
2024-12-27 08:23:26 +08:00
init_task->mm_space.mm_block);
2024-04-04 16:51:29 +00:00
#endif
thread_bind(init_thread, &init_task->kobj);
assert(obj_map_root(&init_thread->kobj, &init_task->obj_space, &root_factory_get()->limit, vpage_create3(KOBJ_ALL_RIGHTS, 0, THREAD_PROT)));
assert(obj_map_root(&init_task->kobj, &init_task->obj_space, &root_factory_get()->limit, vpage_create3(KOBJ_ALL_RIGHTS, 0, TASK_PROT)));
for (int i = FACTORY_PORT_START; i < FACTORY_PORT_END; i++)
{
2024-04-04 16:51:29 +00:00
kobject_t *kobj = global_get_kobj(i);
if (kobj)
{
2024-04-04 16:51:29 +00:00
assert(obj_map_root(kobj, &init_task->obj_space, &root_factory_get()->limit, vpage_create3(KOBJ_ALL_RIGHTS, 0, i)));
}
}
2025-02-12 17:29:30 +08:00
init_thread->sche.prio = 3;
2024-04-04 16:51:29 +00:00
init_task->pid = 0;
thread_ready(init_thread, FALSE);
2024-03-31 16:06:11 +00:00
#endif
2023-08-22 00:26:34 +08:00
}
INIT_STAGE2(knl_init_2);
2023-08-22 00:26:34 +08:00
2025-01-25 15:29:06 +08:00
bool_t task_knl_kill(thread_t *kill_thread, bool_t is_knl)
{
2025-01-25 15:29:06 +08:00
bool_t reset_ram = FALSE;
task_t *task = container_of(kill_thread->task, task_t, kobj);
if (!is_knl)
{
2025-02-16 23:11:18 +08:00
printk("kill %s th:0x%x task:0x%x, pid:%d\n", kobject_get_name(&task->kobj), kill_thread, task, task->pid);
umword_t status2;
status2 = spinlock_lock(&del_lock);
2025-02-12 17:29:30 +08:00
if (stack_len(&kill_thread->com->fast_ipc_stack) != 0)
2025-01-25 15:29:06 +08:00
{
// 在通信的时候出现了错误
// fast_ipc需要测试场景
// 1. 在ipc到其他进程中时其他进程死亡
// 2. 在ipc到其他进程中时当前进程死亡
2025-01-21 22:04:29 +08:00
int ret;
thread_fast_ipc_item_t ipc_item;
2025-01-25 15:29:06 +08:00
ret = thread_fast_ipc_restore(kill_thread);
2025-01-21 22:04:29 +08:00
if (ret >= 0)
{
// 还原栈和usp FIXME:arch相关的
2025-01-25 15:29:06 +08:00
thread_user_pf_restore(kill_thread, (void *)arch_get_user_sp());
mpu_switch_to_task(thread_get_bind_task(kill_thread));
2025-01-21 22:04:29 +08:00
ref_counter_dec_and_release(&task->ref_cn, &task->kobj);
2025-02-05 14:44:49 +08:00
reset_ram = TRUE;
2025-01-21 22:04:29 +08:00
}
2025-01-25 15:29:06 +08:00
}
else
{
2025-01-21 22:04:29 +08:00
thread_suspend(kill_thread);
kill_thread->ipc_status = THREAD_IPC_ABORT;
}
slist_add_append(&del_task_head, &task->del_node);
spinlock_set(&del_lock, status2);
}
else
{
printk("[knl]: knl panic.\n");
assert(0);
}
2025-01-25 15:29:06 +08:00
return reset_ram;
}
2023-08-22 00:26:34 +08:00
static void print_mkrtos_info(void)
{
2024-03-31 16:06:11 +00:00
static const char *start_info[] = {
2023-08-22 00:26:34 +08:00
" _____ ______ ___ __ ________ _________ ________ ________ \r\n",
"|\\ _ \\ _ \\|\\ \\|\\ \\ |\\ __ \\|\\___ ___\\\\ __ \\|\\ ____\\ \r\n",
"\\ \\ \\\\\\__\\ \\ \\ \\ \\/ /|\\ \\ \\|\\ \\|___ \\ \\_\\ \\ \\|\\ \\ \\ \\___|_ \r\n",
" \\ \\ \\\\|__| \\ \\ \\ ___ \\ \\ _ _\\ \\ \\ \\ \\ \\ \\\\\\ \\ \\_____ \\ \r\n",
" \\ \\ \\ \\ \\ \\ \\ \\\\ \\ \\ \\ \\\\ \\| \\ \\ \\ \\ \\ \\\\\\ \\|____|\\ \\ \r\n",
" \\ \\__\\ \\ \\__\\ \\__\\\\ \\__\\ \\__\\\\ _\\ \\ \\__\\ \\ \\_______\\____\\_\\ \\ \r\n",
" \\|__| \\|__|\\|__| \\|__|\\|__|\\|__| \\|__| \\|_______|\\_________\\\r\n",
" \\|_________|\r\n",
"Complie Time:" __DATE__ " " __TIME__ "\r\n",
};
for (umword_t i = 0; i < sizeof(start_info) / sizeof(void *); i++)
{
2023-08-22 00:26:34 +08:00
printk(start_info[i]);
}
2023-08-20 20:52:23 +08:00
}
void start_kernel(void *boot_info)
2023-08-20 20:52:23 +08:00
{
// 初始化系统时钟
// 初始化串口
// 初始化定时器
2024-10-17 23:31:20 +08:00
#if IS_ENABLED(CONFIG_BOOT_INFO_SUPPORT)
arch_set_boot_info(boot_info);
2024-10-17 23:31:20 +08:00
#endif
2023-08-20 20:52:23 +08:00
sys_call_init();
printk("mkrtos init done..\n");
printk("mkrtos running..\n");
2024-02-24 14:30:37 +08:00
printk("sys freq:%d\n", arch_get_sys_clk());
2023-08-22 00:26:34 +08:00
print_mkrtos_info();
2024-03-31 16:06:11 +00:00
cli();
sys_startup(); //!< 开始调度
2024-04-27 03:47:45 +00:00
thread_sched(FALSE);
arch_to_sche();
2024-03-31 16:06:11 +00:00
sti();
2023-08-20 20:52:23 +08:00
while (1)
{
2024-04-27 03:47:45 +00:00
knl_main();
2024-04-06 16:41:37 +00:00
}
2023-08-20 20:52:23 +08:00
}