From 4803239498a85d85e1043cf517f56ae78c619094 Mon Sep 17 00:00:00 2001 From: TXuian <1163589503@qq.com> Date: Sun, 19 May 2024 11:48:43 +0800 Subject: [PATCH] Support thread. --- .../mmu/arm/armv7-a/cortex-a9/bootmmu.c | 2 +- .../XiZi_AIoT/kernel_actracer/actracer.c | 4 + Ubiquitous/XiZi_AIoT/services/app/Makefile | 6 +- .../XiZi_AIoT/services/app/test_thread.c | 47 ++++++++++ .../XiZi_AIoT/services/fs/fs_server/fs.c | 2 +- .../services/fs/fs_server/fs_server.c | 2 +- .../services/lib/usyscall/usyscall.c | 5 ++ .../services/lib/usyscall/usyscall.h | 3 +- .../services/shell/letter-shell/shell_cfg.h | 2 +- .../XiZi_AIoT/softkernel/include/syscall.h | 3 +- .../XiZi_AIoT/softkernel/syscall/Makefile | 1 + .../XiZi_AIoT/softkernel/syscall/sys_spawn.c | 33 +------ .../XiZi_AIoT/softkernel/syscall/sys_thread.c | 86 +++++++++++++++++++ .../XiZi_AIoT/softkernel/syscall/syscall.c | 7 +- .../XiZi_AIoT/softkernel/task/memspace.c | 2 +- Ubiquitous/XiZi_AIoT/softkernel/task/task.c | 21 +++-- .../softkernel/trap/software_irq_handler.c | 5 +- 17 files changed, 175 insertions(+), 56 deletions(-) create mode 100644 Ubiquitous/XiZi_AIoT/services/app/test_thread.c create mode 100644 Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_thread.c diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c index 00f484725..bc5b48a2c 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/bootmmu.c @@ -63,7 +63,7 @@ static void build_boot_pgdir() // kern mem uint32_t kern_mem_start_idx = KERN_MEM_BASE >> LEVEL3_PDE_SHIFT; - uint32_t kern_mem_end_idx = (KERN_MEM_BASE + (PHY_MEM_STOP - PHY_MEM_BASE)) >> LEVEL3_PDE_SHIFT; + uint32_t kern_mem_end_idx = (KERN_MEM_BASE + (PHY_USER_FREEMEM_BASE - PHY_MEM_BASE)) >> LEVEL3_PDE_SHIFT; for (uint32_t i = kern_mem_start_idx; i < kern_mem_end_idx; i++) { boot_pgdir[i] = V2P(i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_AP0; } diff --git a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c index 497b58bfb..8412f6f59 100644 --- a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c +++ b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c @@ -153,6 +153,10 @@ bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta return false; } assert(owner->meta->type == TRACER_OWNER); + if (tracer_find_node_onestep(owner->meta, name) != NULL) { + return false; + } + TracerNode* new_node = (TracerNode*)slab_alloc(&sys_tracer.node_allocator); if (new_node == NULL) { ERROR("Tracer: No memory for new node\n"); diff --git a/Ubiquitous/XiZi_AIoT/services/app/Makefile b/Ubiquitous/XiZi_AIoT/services/app/Makefile index 0fdf53553..9eac2949b 100644 --- a/Ubiquitous/XiZi_AIoT/services/app/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/app/Makefile @@ -26,7 +26,7 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \ -I$(KERNEL_ROOT)/services/app ifeq ($(BOARD), imx6q-sabrelite) -all: init test_fs simple_client simple_server shell fs_server test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server readme.txt | bin +all: init test_fs simple_client simple_server shell fs_server test_thread test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server readme.txt | bin else all: init test_fs simple_client simple_server shell fs_server test_irq_hdlr readme.txt | bin endif @@ -52,6 +52,10 @@ epit_server: timer.o epit.o ccm_pll.o usyscall.o arch_usyscall.o libserial.o pri @${objdump} -S $@ > $@.asm endif +test_thread: test_thread.o libserial.o printf.o usyscall.o arch_usyscall.o + @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} + @${objdump} -S $@ > $@.asm + test_irq_block: test_irq_block.o libserial.o printf.o libipc.o session.o usyscall.o arch_usyscall.o libmem.o @${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs} @${objdump} -S $@ > $@.asm diff --git a/Ubiquitous/XiZi_AIoT/services/app/test_thread.c b/Ubiquitous/XiZi_AIoT/services/app/test_thread.c new file mode 100644 index 000000000..63bcac3db --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/app/test_thread.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#include "libserial.h" +#include "usyscall.h" + +static int global_value; + +int sub_thread_entry(int argc, char** argv) +{ + for (int i = 0; i < 1000; i++) { + global_value++; + printf("[gval]: %d\n", global_value); + } + exit(0); + return 0; +} + +int main(int argc, char** argv) +{ + global_value = 0; + + for (int i = 0; i < 10; i++) { + global_value++; + printf("|gval|: %d\n", global_value); + } + + char* task_param[2] = { "add_gval", NULL }; + int tid = thread(sub_thread_entry, "add_gval", task_param); + + for (int i = 0; i < 1000; i++) { + global_value++; + printf("|gval|: %d\n", global_value); + } + + exit(0); + return 0; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs.c b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs.c index ee5ef8447..964251cbb 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs.c +++ b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs.c @@ -57,7 +57,7 @@ static int InodeFreeRecursive(struct Inode* dp); static char* PathElementExtract(char* path, char* name); static uint32_t InodeBlockMapping(struct Inode* inode, uint32_t block_num); -#define MAX_SUPPORT_FD 2048 +#define MAX_SUPPORT_FD 4096 static struct FileDescriptor fd_table[MAX_SUPPORT_FD]; struct MemFsRange MemFsRange; diff --git a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c index 5f13e6737..bf2f31646 100644 --- a/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c +++ b/Ubiquitous/XiZi_AIoT/services/fs/fs_server/fs_server.c @@ -23,7 +23,7 @@ struct CwdPair { struct Inode* Inode; }; -#define MAX_SUPPORT_SESSION 2048 +#define MAX_SUPPORT_SESSION 4096 static struct CwdPair session_cwd[MAX_SUPPORT_SESSION]; static struct CwdPair* get_session_cwd(void) diff --git a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c index 77d96be01..8038de4d6 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c +++ b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c @@ -26,6 +26,11 @@ int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ip return ret; } +int thread(void* entry, char* name, char** argv) +{ + return syscall(SYSCALL_THREAD, (uintptr_t)entry, (uintptr_t)name, (uintptr_t)argv, 0); +} + void exit(int status) { syscall(SYSCALL_EXIT, (uintptr_t)status, 0, 0, 0); diff --git a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h index 68b488da7..eda606788 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h @@ -27,7 +27,7 @@ #define SYSCALL_POLL_SESSION 7 // server poll for it's server sessions #define SYSCALL_CLOSE_SESSION 8 // client close it's client sessions -#define SYSCALL_EXEC 9 // run elf using current task +#define SYSCALL_THREAD 9 // generate a thread using old memspace #define SYSCALL_SYS_STATE 10 // run system state #define SYSCALL_REGISTER_IRQ 11 // @@ -65,6 +65,7 @@ typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offs int syscall(int sys_num, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4); int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ipc_fsize, char* name, char** argv); +int thread(void* entry, char* name, char** argv); void exit(int status); int yield(task_yield_reason reason); int kill(int pid); diff --git a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cfg.h b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cfg.h index 04263e976..b84856573 100644 --- a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cfg.h +++ b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cfg.h @@ -225,7 +225,7 @@ /** * @brief shell默认用户 */ -#define SHELL_DEFAULT_USER "letter" +#define SHELL_DEFAULT_USER "xizi" #endif /** SHELL_DEFAULT_USER */ #ifndef SHELL_DEFAULT_USER_PASSWORD diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h b/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h index 57764b4fd..96dac0b89 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h @@ -41,7 +41,7 @@ Modification: #define SYSCALL_POLL_SESSION 7 // server poll for it's server sessions #define SYSCALL_CLOSE_SESSION 8 // client close it's client sessions -#define SYSCALL_EXEC 9 // run elf using current task +#define SYSCALL_THREAD 9 // generate a thread using old memspace #define SYSCALL_SYS_STATE 10 // run system state #define SYSCALL_REGISTER_IRQ 11 // @@ -85,6 +85,7 @@ typedef int (*ipc_write_fn)(struct Session* session, int fd, char* src, int offs int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4); int sys_spawn(char* img_start, char* name, char** argv); +int sys_thread(uintptr_t entry, char* name, char** argv); int sys_exit(struct Thread* ptask); int sys_yield(task_yield_reason reason); int sys_kill(int id); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile index 1ad1bd337..8fac5ddff 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/Makefile @@ -1,5 +1,6 @@ SRC_FILES := syscall.c \ sys_spawn.c \ + sys_thread.c \ sys_yield.c \ sys_register_as_server.c \ sys_connect_session.c \ diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c index bc23a86c3..052a03ed1 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c @@ -34,7 +34,7 @@ Modification: #include "syscall.h" #include "task.h" -extern int task_exec(struct Thread* task, char* img_start, char* name, char** argv); +extern int sys_new_thread(struct MemSpace* pmemspace, struct Thread* task, uintptr_t entry, char* name, char** argv); int sys_spawn(char* img_start, char* name, char** argv) { // alloc a new memspace @@ -60,34 +60,5 @@ int sys_spawn(char* img_start, char* name, char** argv) } assert(!IS_DOUBLE_LIST_EMPTY(&pmemspace->thread_list_guard)); - // init params - struct ThreadStackPointer loaded_sp = load_user_stack(pmemspace, argv); - if (loaded_sp.stack_idx == -1) { - ERROR("Uable to load params to memspace.\n"); - /* memspace is freed alone with free_pcb() */ - xizi_task_manager.free_pcb(new_task_cb); - return -1; - } - - // init trapframe - new_task_cb->thread_context.user_stack_idx = loaded_sp.stack_idx; - new_task_cb->thread_context.uspace_stack_addr = USER_MEM_TOP - ((loaded_sp.stack_idx + 1) * USER_STACK_SIZE); - new_task_cb->thread_context.ustack_kvaddr = loaded_sp.user_stack_vaddr; - arch_init_trapframe(new_task_cb->thread_context.trapframe, 0, 0); - arch_trapframe_set_sp_pc(new_task_cb->thread_context.trapframe, loaded_sp.user_sp, (uintptr_t)entry); - arch_set_main_params(new_task_cb->thread_context.trapframe, loaded_sp.argc, loaded_sp.user_sp); - - // init thread name - char* last = NULL; - for (last = name; *name; name++) { - if (*name == '/') { - last = name + 1; - } - } - strncpy(new_task_cb->name, last, sizeof(new_task_cb->name)); - - // init pcb schedule attributes - xizi_task_manager.task_set_default_schedule_attr(new_task_cb); - - return 0; + return sys_new_thread(pmemspace, new_task_cb, (uintptr_t)entry, name, argv); } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_thread.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_thread.c new file mode 100644 index 000000000..5d08d655e --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_thread.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +/** + * @file sys_spawn.c + * @brief spawn a task + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2023.08.25 + */ + +/************************************************* +File name: sys_thread.c +Description: spawn a thread +Others: +History: +1. Date: 2023-08-28 +Author: AIIT XUOS Lab +Modification: +1. first version +*************************************************/ +#include "actracer.h" +#include "assert.h" +#include "memspace.h" +#include "multicores.h" +#include "share_page.h" +#include "syscall.h" +#include "task.h" + +int sys_new_thread(struct MemSpace* pmemspace, struct Thread* task, uintptr_t entry, char* name, char** argv) +{ + struct ThreadStackPointer loaded_sp = load_user_stack(pmemspace, argv); + if (loaded_sp.stack_idx == -1) { + ERROR("Uable to load params to memspace.\n"); + /* memspace is freed alone with free_pcb() */ + xizi_task_manager.free_pcb(task); + return -1; + } + + // init trapframe + task->thread_context.user_stack_idx = loaded_sp.stack_idx; + task->thread_context.uspace_stack_addr = USER_MEM_TOP - ((loaded_sp.stack_idx + 1) * USER_STACK_SIZE); + task->thread_context.ustack_kvaddr = loaded_sp.user_stack_vaddr; + arch_init_trapframe(task->thread_context.trapframe, 0, 0); + arch_trapframe_set_sp_pc(task->thread_context.trapframe, loaded_sp.user_sp, (uintptr_t)entry); + arch_set_main_params(task->thread_context.trapframe, loaded_sp.argc, loaded_sp.user_sp); + + // init thread name + char* last = NULL; + for (last = name; *name; name++) { + if (*name == '/') { + last = name + 1; + } + } + strncpy(task->name, last, sizeof(task->name)); + + // init pcb schedule attributes + xizi_task_manager.task_set_default_schedule_attr(task); + + return task->tid; +} + +int sys_thread(uintptr_t entry, char* name, char** argv) +{ + struct Thread* cur_task = cur_cpu()->task; + + // use current task's memspace + struct MemSpace* pmemspace = cur_task->memspace; + + struct Thread* task = xizi_task_manager.new_task_cb(pmemspace); + if (UNLIKELY(!task)) { + ERROR("Unable to new task control block.\n"); + return -1; + } + assert(!IS_DOUBLE_LIST_EMPTY(&pmemspace->thread_list_guard)); + + return sys_new_thread(pmemspace, task, entry, name, argv); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c index 11ec6bdd3..8c5891584 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/syscall.c @@ -44,6 +44,9 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u case SYSCALL_SPAWN: ret = sys_spawn((char*)param1, (char*)param2, (char**)param3); break; + case SYSCALL_THREAD: + ret = sys_thread((uintptr_t)param1, (char*)param2, (char**)param3); + break; case SYSCALL_EXIT: ret = sys_exit(cur_cpu()->task); break; @@ -62,10 +65,6 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u case SYSCALL_CLOSE_SESSION: ret = sys_close_session(cur_cpu()->task, (struct Session*)param1); break; - case SYSCALL_EXEC: - // ret = sys_exec((char*)param1, (char*)param2, (char**)param3); - ret = -1; - break; case SYSCALL_SYS_STATE: ret = sys_state(param1, (sys_state_info*)param2); break; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c b/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c index dd3c7b444..1963e737d 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c @@ -214,7 +214,7 @@ struct ThreadStackPointer load_user_stack(struct MemSpace* pmemspace, char** arg /* start loading main params into user stack */ /// @warning supports only main style params - uintptr_t user_vspace_sp = USER_MEM_TOP; + uintptr_t user_vspace_sp = USER_MEM_TOP - (stack_idx * USER_STACK_SIZE); static uintptr_t user_stack_init[MAX_SUPPORT_PARAMS]; memset(user_stack_init, 0, sizeof(user_stack_init)); uintptr_t argc = 0; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c index defc16254..6fe34d7c2 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c @@ -204,28 +204,31 @@ static struct Thread* _new_task_cb(struct MemSpace* pmemspace) if (!task) { return NULL; } - // init vm - if (pmemspace != NULL) { - task->memspace = pmemspace; - task->thread_context.user_stack_idx = -1; - doubleListNodeInit(&task->memspace_list_node); - doubleListAddOnBack(&task->memspace_list_node, &pmemspace->thread_list_guard); - } else { - task->memspace = NULL; - } /* init basic task member */ doubleListNodeInit(&task->cli_sess_listhead); doubleListNodeInit(&task->svr_sess_listhead); + /* when creating a new task, memspace will be freed outside during memory shortage */ + task->memspace = NULL; + /* init main thread of task */ task->thread_context.task = task; // alloc stack page for task if ((void*)(task->thread_context.kern_stack_addr = (uintptr_t)kalloc(USER_STACK_SIZE)) == NULL) { + /* here inside, will no free memspace */ _dealloc_task_cb(task); return NULL; } + /* from now on, _new_task_cb() will not generate error */ + /* init vm */ + assert(pmemspace != NULL); + task->memspace = pmemspace; + task->thread_context.user_stack_idx = -1; + doubleListNodeInit(&task->memspace_list_node); + doubleListAddOnBack(&task->memspace_list_node, &pmemspace->thread_list_guard); + /* set context of main thread stack */ /// stack bottom memset((void*)task->thread_context.kern_stack_addr, 0x00, USER_STACK_SIZE); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c b/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c index a6b7d04c4..25c4bd1de 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/trap/software_irq_handler.c @@ -61,10 +61,7 @@ void software_irq_dispatch(struct trapframe* tf) // call syscall int ret = arch_syscall(cur_task->thread_context.trapframe, &syscall_num); - - if (syscall_num != SYSCALL_EXEC) { - arch_set_return(tf, ret); - } + arch_set_return(tf, ret); } if ((cur_cpu()->task == NULL && cur_task != NULL) || cur_task->state != RUNNING) {