forked from xuos/xiuos
Merge branch 'smp' of https://gitlink.org.cn/tuyuyang/xiuos into lwip
This commit is contained in:
commit
4e67992516
|
@ -1,7 +1,8 @@
|
||||||
export CROSS_COMPILE ?= arm-none-eabi-
|
export CROSS_COMPILE ?= arm-none-eabi-
|
||||||
export DEVICE = -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp
|
export DEVICE = -march=armv7-a -mtune=cortex-a9 -mfpu=vfpv3-d16 -ftree-vectorize -ffast-math -mfloat-abi=softfp
|
||||||
# export CFLAGS := $(DEVICE) -std=c11 -Wall -O2 -g -gdwarf-2 -Wnull-dereference -Waddress -Warray-bounds -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wunused-function
|
# export CFLAGS := $(DEVICE) -std=c11 -Wall -O2 -g -gdwarf-2 -Wnull-dereference -Waddress -Warray-bounds -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wunused-function
|
||||||
export CFLAGS := $(DEVICE) -std=c11 -Wall -O2 -g -gdwarf-2 -Waddress -Warray-bounds -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wunused-function
|
# export CFLAGS := $(DEVICE) -std=c11 -Wall -O2 -g -gdwarf-2 -Waddress -Warray-bounds -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wunused-function
|
||||||
|
export CFLAGS := $(DEVICE) -std=c11 -Wall -O0 -g -gdwarf-2 -Waddress -Warray-bounds -Wchar-subscripts -Wimplicit-int -Wimplicit-function-declaration -Wcomment -Wformat -Wmissing-braces -Wnonnull -Wparentheses -Wpointer-sign -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wstrict-overflow=1 -Wswitch -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunused-function -Wunused-label -Wunused-value -Wunused-variable -Wunused-function
|
||||||
export AFLAGS := -c $(DEVICE) -x assembler-with-cpp -D__ASSEMBLY__ -gdwarf-2
|
export AFLAGS := -c $(DEVICE) -x assembler-with-cpp -D__ASSEMBLY__ -gdwarf-2
|
||||||
# export LFLAGS := $(DEVICE) -Wl,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds
|
# export LFLAGS := $(DEVICE) -Wl,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds
|
||||||
export LFLAGS := $(DEVICE) --specs=nosys.specs -Wl,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds
|
export LFLAGS := $(DEVICE) --specs=nosys.specs -Wl,-Map=XiZi-imx6q-sabrelite.map,-cref,-u,_boot_start -T $(KERNEL_ROOT)/hardkernel/arch/arm/armv7-a/cortex-a9/preboot_for_imx6q-sabrelite/nxp_imx6q_sabrelite.lds
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void build_boot_pgdir()
|
||||||
|
|
||||||
// kern mem
|
// kern mem
|
||||||
uint32_t kern_mem_start_idx = KERN_MEM_BASE >> LEVEL3_PDE_SHIFT;
|
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++) {
|
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;
|
boot_pgdir[i] = V2P(i << LEVEL3_PDE_SHIFT) | L1_TYPE_SEC | L1_SECT_AP0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,13 @@ Modification:
|
||||||
#define MAX_NR_FREE_PAGES ((PHY_MEM_STOP - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT)
|
#define MAX_NR_FREE_PAGES ((PHY_MEM_STOP - PHY_MEM_BASE) >> LEVEL4_PTE_SHIFT)
|
||||||
|
|
||||||
/* User memory layout */
|
/* User memory layout */
|
||||||
|
#define NR_MAX_TREADS_PER_TASK 64
|
||||||
#define USER_STACK_SIZE MODE_STACK_SIZE
|
#define USER_STACK_SIZE MODE_STACK_SIZE
|
||||||
#define USER_MEM_BASE (0x00000000)
|
#define USER_MEM_BASE (0x00000000)
|
||||||
#define USER_MEM_TOP DEV_VRTMEM_BASE
|
#define USER_MEM_TOP DEV_VRTMEM_BASE
|
||||||
#define USER_IPC_SPACE_BASE (0x70000000)
|
#define USER_IPC_SPACE_BASE (0x70000000)
|
||||||
#define USER_IPC_USE_ALLOCATOR_WATERMARK (0x70010000)
|
#define USER_IPC_USE_ALLOCATOR_WATERMARK (0x70010000)
|
||||||
#define USER_IPC_SPACE_TOP (USER_MEM_TOP - USER_STACK_SIZE)
|
#define USER_IPC_SPACE_TOP (USER_MEM_TOP - (NR_MAX_TREADS_PER_TASK * USER_STACK_SIZE))
|
||||||
|
|
||||||
/* Deivce memory layout */
|
/* Deivce memory layout */
|
||||||
#define DEV_PHYMEM_BASE (0x00000000)
|
#define DEV_PHYMEM_BASE (0x00000000)
|
||||||
|
|
|
@ -153,6 +153,10 @@ bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(owner->meta->type == TRACER_OWNER);
|
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);
|
TracerNode* new_node = (TracerNode*)slab_alloc(&sys_tracer.node_allocator);
|
||||||
if (new_node == NULL) {
|
if (new_node == NULL) {
|
||||||
ERROR("Tracer: No memory for new node\n");
|
ERROR("Tracer: No memory for new node\n");
|
||||||
|
|
|
@ -27,7 +27,7 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \
|
||||||
-I$(KERNEL_ROOT)/services/app
|
-I$(KERNEL_ROOT)/services/app
|
||||||
|
|
||||||
ifeq ($(BOARD), imx6q-sabrelite)
|
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 test_net lwip | 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 test_net lwip | bin
|
||||||
else
|
else
|
||||||
all: init test_fs simple_client simple_server shell fs_server test_irq_hdlr readme.txt | bin
|
all: init test_fs simple_client simple_server shell fs_server test_irq_hdlr readme.txt | bin
|
||||||
endif
|
endif
|
||||||
|
@ -53,6 +53,10 @@ epit_server: timer.o epit.o ccm_pll.o usyscall.o arch_usyscall.o libserial.o pri
|
||||||
@${objdump} -S $@ > $@.asm
|
@${objdump} -S $@ > $@.asm
|
||||||
endif
|
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
|
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}
|
@${ld} ${user_ldflags} -e main -o $@ $^ ${board_specs}
|
||||||
@${objdump} -S $@ > $@.asm
|
@${objdump} -S $@ > $@.asm
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -57,7 +57,7 @@ static int InodeFreeRecursive(struct Inode* dp);
|
||||||
static char* PathElementExtract(char* path, char* name);
|
static char* PathElementExtract(char* path, char* name);
|
||||||
static uint32_t InodeBlockMapping(struct Inode* inode, uint32_t block_num);
|
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];
|
static struct FileDescriptor fd_table[MAX_SUPPORT_FD];
|
||||||
|
|
||||||
struct MemFsRange MemFsRange;
|
struct MemFsRange MemFsRange;
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct CwdPair {
|
||||||
struct Inode* Inode;
|
struct Inode* Inode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SUPPORT_SESSION 2048
|
#define MAX_SUPPORT_SESSION 4096
|
||||||
static struct CwdPair session_cwd[MAX_SUPPORT_SESSION];
|
static struct CwdPair session_cwd[MAX_SUPPORT_SESSION];
|
||||||
|
|
||||||
static struct CwdPair* get_session_cwd(void)
|
static struct CwdPair* get_session_cwd(void)
|
||||||
|
|
|
@ -26,6 +26,11 @@ int spawn(struct Session* session, int fd, ipc_read_fn ipc_read, ipc_fsize_fn ip
|
||||||
return ret;
|
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)
|
void exit(int status)
|
||||||
{
|
{
|
||||||
syscall(SYSCALL_EXIT, (uintptr_t)status, 0, 0, 0);
|
syscall(SYSCALL_EXIT, (uintptr_t)status, 0, 0, 0);
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#define SYSCALL_POLL_SESSION 7 // server poll for it's server sessions
|
#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_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_SYS_STATE 10 // run system state
|
||||||
#define SYSCALL_REGISTER_IRQ 11 //
|
#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 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 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);
|
void exit(int status);
|
||||||
int yield(task_yield_reason reason);
|
int yield(task_yield_reason reason);
|
||||||
int kill(int pid);
|
int kill(int pid);
|
||||||
|
|
|
@ -225,7 +225,7 @@
|
||||||
/**
|
/**
|
||||||
* @brief shell默认用户
|
* @brief shell默认用户
|
||||||
*/
|
*/
|
||||||
#define SHELL_DEFAULT_USER "letter"
|
#define SHELL_DEFAULT_USER "xizi"
|
||||||
#endif /** SHELL_DEFAULT_USER */
|
#endif /** SHELL_DEFAULT_USER */
|
||||||
|
|
||||||
#ifndef SHELL_DEFAULT_USER_PASSWORD
|
#ifndef SHELL_DEFAULT_USER_PASSWORD
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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 bitmap64.h
|
||||||
|
* @brief 64 bit bitmap support
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2023.08.25
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
File name: bitmap64.h
|
||||||
|
Description: 64 bit bitmap support
|
||||||
|
Others:
|
||||||
|
History:
|
||||||
|
1. Date: 2024-05-18
|
||||||
|
Author: AIIT XUOS Lab
|
||||||
|
Modification:
|
||||||
|
1. first version
|
||||||
|
*************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "assert.h"
|
||||||
|
|
||||||
|
struct bitmap64 {
|
||||||
|
uint64_t map;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void bitmap64_init(struct bitmap64* bitmap)
|
||||||
|
{
|
||||||
|
bitmap->map = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bitmap64_alloc(struct bitmap64* bitmap)
|
||||||
|
{
|
||||||
|
int free_bit = -1;
|
||||||
|
// free bit is the first 0 bit, from [1, 64]
|
||||||
|
free_bit = __builtin_ffsl(~(uint64_t)(bitmap->map));
|
||||||
|
// handle if bitmap is full (no using 64th bit here)
|
||||||
|
if (free_bit == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
assert(free_bit < 64 && free_bit >= 1);
|
||||||
|
// alloc and return
|
||||||
|
bitmap->map |= (1 << (free_bit - 1));
|
||||||
|
return free_bit - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap64_free(struct bitmap64* bitmap, int idx)
|
||||||
|
{
|
||||||
|
// usages of bitmap64 must be correct
|
||||||
|
assert((bitmap->map & (1 << idx)) != 0);
|
||||||
|
// free bit
|
||||||
|
bitmap->map &= ~(uint64_t)(1 << idx);
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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 memspace.h
|
||||||
|
* @brief memspace loader
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2023.08.25
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
File name: memspace.h
|
||||||
|
Description: memspace loader
|
||||||
|
Others:
|
||||||
|
History:
|
||||||
|
1. Date: 2023-08-28
|
||||||
|
Author: AIIT XUOS Lab
|
||||||
|
Modification:
|
||||||
|
1. first version
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
struct ThreadStackPointer {
|
||||||
|
int argc;
|
||||||
|
int stack_idx;
|
||||||
|
uintptr_t user_sp;
|
||||||
|
uintptr_t user_stack_vaddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MemSpace* alloc_memspace();
|
||||||
|
void free_memspace(struct MemSpace* pmemspace);
|
||||||
|
uintptr_t* load_memspace(struct MemSpace* pmemspace, char* img_start);
|
||||||
|
struct ThreadStackPointer load_user_stack(struct MemSpace* pmemspace, char** argv);
|
|
@ -36,7 +36,7 @@ Modification:
|
||||||
struct CPU {
|
struct CPU {
|
||||||
int cpuid;
|
int cpuid;
|
||||||
|
|
||||||
struct TaskMicroDescriptor* task;
|
struct Thread* task;
|
||||||
struct context* scheduler;
|
struct context* scheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -59,8 +59,8 @@ struct PagerRightGroup {
|
||||||
struct XiziPageManager {
|
struct XiziPageManager {
|
||||||
bool (*new_pgdir)(struct TopLevelPageDirectory* pgdir);
|
bool (*new_pgdir)(struct TopLevelPageDirectory* pgdir);
|
||||||
void (*free_user_pgdir)(struct TopLevelPageDirectory* pgdir);
|
void (*free_user_pgdir)(struct TopLevelPageDirectory* pgdir);
|
||||||
bool (*map_pages)(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t paddr, uintptr_t len, bool is_dev);
|
bool (*map_pages)(uintptr_t* pd_addr, uintptr_t vaddr, uintptr_t paddr, uintptr_t len, bool is_dev);
|
||||||
bool (*unmap_pages)(uintptr_t* pgdir, uintptr_t vaddr, uintptr_t len);
|
bool (*unmap_pages)(uintptr_t* pd_addr, uintptr_t vaddr, uintptr_t len);
|
||||||
|
|
||||||
uintptr_t (*resize_user_pgdir)(struct TopLevelPageDirectory* pgdir, uintptr_t old_size, uintptr_t new_size);
|
uintptr_t (*resize_user_pgdir)(struct TopLevelPageDirectory* pgdir, uintptr_t old_size, uintptr_t new_size);
|
||||||
uintptr_t (*address_translate)(struct TopLevelPageDirectory* pgdir, uintptr_t vaddr);
|
uintptr_t (*address_translate)(struct TopLevelPageDirectory* pgdir, uintptr_t vaddr);
|
||||||
|
|
|
@ -31,6 +31,6 @@ Modification:
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
struct TaskMicroDescriptor* max_priority_runnable_task(void);
|
struct Thread* max_priority_runnable_task(void);
|
||||||
struct TaskMicroDescriptor* round_robin_runnable_task(uint32_t priority);
|
struct Thread* round_robin_runnable_task(uint32_t priority);
|
||||||
void recover_priority(void);
|
void recover_priority(void);
|
|
@ -69,8 +69,8 @@ struct session_backend {
|
||||||
struct client_session client_side;
|
struct client_session client_side;
|
||||||
int session_id; // id of this session
|
int session_id; // id of this session
|
||||||
int nr_pages; // pages used by this pipe
|
int nr_pages; // pages used by this pipe
|
||||||
struct TaskMicroDescriptor* client; // client of this pipe
|
struct Thread* client; // client of this pipe
|
||||||
struct TaskMicroDescriptor* server; // server of this pipe
|
struct Thread* server; // server of this pipe
|
||||||
|
|
||||||
uintptr_t buf_kernel_addr;
|
uintptr_t buf_kernel_addr;
|
||||||
};
|
};
|
||||||
|
@ -81,11 +81,11 @@ struct SharePageRightGroup {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XiziSharePageManager {
|
struct XiziSharePageManager {
|
||||||
struct session_backend* (*create_share_pages)(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, const int capacity);
|
struct session_backend* (*create_share_pages)(struct Thread* client, struct Thread* server, const int capacity);
|
||||||
void (*unmap_task_share_pages)(struct TaskMicroDescriptor* task, const uintptr_t task_vaddr, const int nr_pages);
|
void (*unmap_task_share_pages)(struct Thread* task, const uintptr_t task_vaddr, const int nr_pages);
|
||||||
int (*delete_share_pages)(struct session_backend* session_backend);
|
int (*delete_share_pages)(struct session_backend* session_backend);
|
||||||
|
|
||||||
uintptr_t (*task_map_pages)(struct TaskMicroDescriptor* task, const uintptr_t vaddr, const uintptr_t paddr, const int nr_pages, const int is_dev);
|
uintptr_t (*task_map_pages)(struct Thread* task, const uintptr_t vaddr, const uintptr_t paddr, const int nr_pages, const int is_dev);
|
||||||
};
|
};
|
||||||
extern struct XiziSharePageManager xizi_share_page_manager;
|
extern struct XiziSharePageManager xizi_share_page_manager;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ Modification:
|
||||||
#define SYSCALL_POLL_SESSION 7 // server poll for it's server sessions
|
#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_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_SYS_STATE 10 // run system state
|
||||||
#define SYSCALL_REGISTER_IRQ 11 //
|
#define SYSCALL_REGISTER_IRQ 11 //
|
||||||
|
|
||||||
|
@ -85,20 +85,21 @@ 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 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_spawn(char* img_start, char* name, char** argv);
|
||||||
int sys_exit(struct TaskMicroDescriptor* ptask);
|
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_yield(task_yield_reason reason);
|
||||||
int sys_kill(int id);
|
int sys_kill(int id);
|
||||||
|
|
||||||
int sys_register_as_server(char* name);
|
int sys_register_as_server(char* name);
|
||||||
int sys_connect_session(char* path, int capacity, struct Session* user_session);
|
int sys_connect_session(char* path, int capacity, struct Session* user_session);
|
||||||
int sys_poll_session(struct Session* userland_session_arr, int arr_capacity);
|
int sys_poll_session(struct Session* userland_session_arr, int arr_capacity);
|
||||||
int sys_close_session(struct TaskMicroDescriptor* task, struct Session* session);
|
int sys_close_session(struct Thread* task, struct Session* session);
|
||||||
|
|
||||||
int sys_exec(char* img_start, char* name, char** argv);
|
int sys_exec(char* img_start, char* name, char** argv);
|
||||||
int sys_state(sys_state_option option, sys_state_info* info);
|
int sys_state(sys_state_option option, sys_state_info* info);
|
||||||
int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev);
|
int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev);
|
||||||
|
|
||||||
int sys_register_irq(int irq_num, int irq_opcode);
|
int sys_register_irq(int irq_num, int irq_opcode);
|
||||||
int sys_unbind_irq_all(struct TaskMicroDescriptor* task);
|
int sys_unbind_irq_all(struct Thread* task);
|
||||||
int sys_unbind_irq(struct TaskMicroDescriptor* task, int irq_num);
|
int sys_unbind_irq(struct Thread* task, int irq_num);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,6 +31,7 @@ Modification:
|
||||||
|
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
|
||||||
|
#include "bitmap64.h"
|
||||||
#include "buddy.h"
|
#include "buddy.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "object_allocator.h"
|
#include "object_allocator.h"
|
||||||
|
@ -52,41 +53,58 @@ enum ProcState {
|
||||||
NEVER_RUN,
|
NEVER_RUN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MemSpace {
|
||||||
|
/* task memory resources */
|
||||||
|
struct TopLevelPageDirectory pgdir; // [phy] vm pgtbl base address
|
||||||
|
uintptr_t heap_base; // mem size of proc used(allocated by kernel)
|
||||||
|
uintptr_t mem_size;
|
||||||
|
/* task communication mem resources */
|
||||||
|
struct KBuddy* massive_ipc_allocator;
|
||||||
|
|
||||||
|
/* thread using this memspace */
|
||||||
|
struct bitmap64 thread_stack_idx_bitmap;
|
||||||
|
struct double_list_node thread_list_guard;
|
||||||
|
};
|
||||||
|
|
||||||
/* Thread Control Block */
|
/* Thread Control Block */
|
||||||
struct Thread {
|
struct ThreadContext {
|
||||||
struct TaskMicroDescriptor* task; // process of current thread
|
struct Thread* task; // process of current thread
|
||||||
uintptr_t stack_addr; // [virt] stack base address
|
|
||||||
|
/* kernel stack of thread */
|
||||||
|
uintptr_t kern_stack_addr; // [virt] stack base address
|
||||||
|
|
||||||
|
/* user stack */
|
||||||
|
int user_stack_idx; // [virt] stack idx in user memspace
|
||||||
|
uintptr_t uspace_stack_addr; // [virt] user stack base address in memspace
|
||||||
|
uintptr_t ustack_kvaddr; // [virt] user stack memeory's kernel vaddr
|
||||||
|
|
||||||
|
/* kernel context of thread */
|
||||||
struct context* context;
|
struct context* context;
|
||||||
|
/* user context of thread */
|
||||||
struct trapframe* trapframe;
|
struct trapframe* trapframe;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Process Control Block */
|
/* Process Control Block */
|
||||||
struct TaskMicroDescriptor {
|
struct Thread {
|
||||||
/* task debug resources */
|
/* task name */
|
||||||
int pid;
|
|
||||||
bool bind_irq;
|
|
||||||
bool dead;
|
|
||||||
char name[TASK_NAME_MAX_LEN];
|
char name[TASK_NAME_MAX_LEN];
|
||||||
|
|
||||||
/// @todo support return value
|
/* task debug resources */
|
||||||
int ret; // state val that be returned to parent
|
int tid;
|
||||||
/// @todo support parent
|
bool bind_irq;
|
||||||
struct TaskMicroDescriptor* parent;
|
bool dead;
|
||||||
|
|
||||||
/* task context resources */
|
/* task context resources */
|
||||||
struct Thread main_thread; // will only access by task itself
|
struct ThreadContext thread_context; // will only access by task itself
|
||||||
|
|
||||||
/* task memory resources */
|
/* thread mem space */
|
||||||
struct TopLevelPageDirectory pgdir; // [phy] vm pgtbl base address
|
struct MemSpace* memspace;
|
||||||
uintptr_t heap_base; // mem size of proc used(allocated by kernel)
|
struct double_list_node memspace_list_node;
|
||||||
/// @todo support heap_base
|
|
||||||
uintptr_t mem_size;
|
|
||||||
|
|
||||||
/* task communication resources */
|
/* task communication resources */
|
||||||
struct double_list_node cli_sess_listhead;
|
struct double_list_node cli_sess_listhead;
|
||||||
struct double_list_node svr_sess_listhead;
|
struct double_list_node svr_sess_listhead;
|
||||||
bool current_ipc_handled;
|
bool current_ipc_handled;
|
||||||
struct KBuddy* massive_ipc_allocator;
|
|
||||||
struct TraceTag server_identifier;
|
struct TraceTag server_identifier;
|
||||||
|
|
||||||
/* task schedule attributes */
|
/* task schedule attributes */
|
||||||
|
@ -106,36 +124,39 @@ struct XiziTaskManager {
|
||||||
struct double_list_node task_list_head[TASK_MAX_PRIORITY]; /* list of task control blocks that are allocated */
|
struct double_list_node task_list_head[TASK_MAX_PRIORITY]; /* list of task control blocks that are allocated */
|
||||||
struct double_list_node task_running_list_head;
|
struct double_list_node task_running_list_head;
|
||||||
struct double_list_node task_blocked_list_head;
|
struct double_list_node task_blocked_list_head;
|
||||||
struct slab_allocator task_allocator;
|
|
||||||
struct slab_allocator task_buddy_allocator;
|
/* mem allocator */
|
||||||
|
struct slab_allocator memspace_allocator;
|
||||||
|
struct slab_allocator task_allocator; // allocate struct Tread
|
||||||
|
struct slab_allocator task_buddy_allocator; // allocate buddy for memspace
|
||||||
uint32_t next_pid;
|
uint32_t next_pid;
|
||||||
|
|
||||||
/* init task manager */
|
/* init task manager */
|
||||||
void (*init)();
|
void (*init)();
|
||||||
/* new a task control block, checkout #sys_spawn for usage */
|
/* new a task control block, checkout #sys_spawn for usage */
|
||||||
struct TaskMicroDescriptor* (*new_task_cb)();
|
struct Thread* (*new_task_cb)(struct MemSpace* pmemspace);
|
||||||
/* free a task control block, this calls #free_user_pgdir to free all vitual spaces */
|
/* free a task control block, this calls #free_user_pgdir to free all vitual spaces */
|
||||||
void (*free_pcb)(struct TaskMicroDescriptor*);
|
void (*free_pcb)(struct Thread*);
|
||||||
/* init a task control block, set name, remain_tick, state, cwd, priority, etc. */
|
/* init a task control block, set name, remain_tick, state, cwd, priority, etc. */
|
||||||
void (*task_set_default_schedule_attr)(struct TaskMicroDescriptor*);
|
void (*task_set_default_schedule_attr)(struct Thread*);
|
||||||
|
|
||||||
/* use by task_scheduler, find next READY task, should be in locked */
|
/* use by task_scheduler, find next READY task, should be in locked */
|
||||||
struct TaskMicroDescriptor* (*next_runnable_task)(void);
|
struct Thread* (*next_runnable_task)(void);
|
||||||
/* function that's runing by kernel thread context, schedule use tasks */
|
/* function that's runing by kernel thread context, schedule use tasks */
|
||||||
void (*task_scheduler)(struct SchedulerRightGroup);
|
void (*task_scheduler)(struct SchedulerRightGroup);
|
||||||
|
|
||||||
/* handle task state */
|
/* handle task state */
|
||||||
/* call to yield current use task */
|
/* call to yield current use task */
|
||||||
void (*task_yield_noschedule)(struct TaskMicroDescriptor* task, bool is_blocking);
|
void (*task_yield_noschedule)(struct Thread* task, bool is_blocking);
|
||||||
/* block and unblock task */
|
/* block and unblock task */
|
||||||
void (*task_block)(struct TaskMicroDescriptor* task);
|
void (*task_block)(struct Thread* task);
|
||||||
void (*task_unblock)(struct TaskMicroDescriptor* task);
|
void (*task_unblock)(struct Thread* task);
|
||||||
/* set task priority */
|
/* set task priority */
|
||||||
void (*set_cur_task_priority)(int priority);
|
void (*set_cur_task_priority)(int priority);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern uint32_t ready_task_priority;
|
extern uint32_t ready_task_priority;
|
||||||
extern struct TaskMicroDescriptor* next_task_emergency;
|
extern struct Thread* next_task_emergency;
|
||||||
extern struct XiziTaskManager xizi_task_manager;
|
extern struct XiziTaskManager xizi_task_manager;
|
||||||
|
|
||||||
int spawn_embedded_task(char* img_start, char* name, char** argv);
|
int spawn_embedded_task(char* img_start, char* name, char** argv);
|
||||||
|
|
|
@ -30,7 +30,6 @@ Modification:
|
||||||
#include "kern_init.h"
|
#include "kern_init.h"
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "kalloc.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ char* kalloc(size_t size)
|
||||||
if (mem_alloc == NULL) {
|
if (mem_alloc == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
assert((uintptr_t)mem_alloc >= V2P(&kernel_data_end) && (uintptr_t)mem_alloc < PHY_USER_FREEMEM_BASE);
|
||||||
mem_alloc = P2V(mem_alloc);
|
mem_alloc = P2V(mem_alloc);
|
||||||
if ((uintptr_t)mem_alloc < KERN_MEM_BASE) {
|
if ((uintptr_t)mem_alloc < KERN_MEM_BASE) {
|
||||||
DEBUG("Error Alloc: %x by size: %d (Caused by double free)\n", mem_alloc, size);
|
DEBUG("Error Alloc: %x by size: %d (Caused by double free)\n", mem_alloc, size);
|
||||||
|
|
|
@ -54,11 +54,11 @@ static struct slab_allocator* SessionAllocator()
|
||||||
/// @param vaddr
|
/// @param vaddr
|
||||||
/// @param nr_pages
|
/// @param nr_pages
|
||||||
/// @return true if mem range is free, false if at least one page inside [vaddr, vaddr + nr_pages * PAGE_SIZE) is mapped
|
/// @return true if mem range is free, false if at least one page inside [vaddr, vaddr + nr_pages * PAGE_SIZE) is mapped
|
||||||
static inline bool check_pages_unmapped(struct TaskMicroDescriptor* task, uintptr_t vaddr, int nr_pages)
|
static inline bool check_pages_unmapped(struct Thread* task, uintptr_t vaddr, int nr_pages)
|
||||||
{
|
{
|
||||||
static uintptr_t paddr = UINT32_MAX;
|
static uintptr_t paddr = UINT32_MAX;
|
||||||
for (uintptr_t i = 0; i < nr_pages; i++) {
|
for (uintptr_t i = 0; i < nr_pages; i++) {
|
||||||
if ((paddr = xizi_pager.address_translate(&task->pgdir, vaddr)) != 0) {
|
if ((paddr = xizi_pager.address_translate(&task->memspace->pgdir, vaddr)) != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
vaddr += PAGE_SIZE;
|
vaddr += PAGE_SIZE;
|
||||||
|
@ -71,7 +71,7 @@ static inline bool check_pages_unmapped(struct TaskMicroDescriptor* task, uintpt
|
||||||
/// @param nr_pages continuously map nr_pages
|
/// @param nr_pages continuously map nr_pages
|
||||||
/// @return addr to be mapped, aligned by page
|
/// @return addr to be mapped, aligned by page
|
||||||
/// @todo optimize, and suppurt multiple pages
|
/// @todo optimize, and suppurt multiple pages
|
||||||
static uintptr_t alloc_share_page_addr(struct TaskMicroDescriptor* task, const int nr_pages)
|
static uintptr_t alloc_share_page_addr(struct Thread* task, const int nr_pages)
|
||||||
{
|
{
|
||||||
uintptr_t vaddr = USER_IPC_SPACE_BASE;
|
uintptr_t vaddr = USER_IPC_SPACE_BASE;
|
||||||
while (!check_pages_unmapped(task, vaddr, nr_pages)) {
|
while (!check_pages_unmapped(task, vaddr, nr_pages)) {
|
||||||
|
@ -85,7 +85,7 @@ static uintptr_t alloc_share_page_addr(struct TaskMicroDescriptor* task, const i
|
||||||
return vaddr;
|
return vaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uintptr_t paddr, const int nr_pages)
|
static uintptr_t map_task_share_page(struct Thread* task, const uintptr_t paddr, const int nr_pages)
|
||||||
{
|
{
|
||||||
/* get driver codes */
|
/* get driver codes */
|
||||||
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
|
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
|
||||||
|
@ -93,15 +93,15 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin
|
||||||
|
|
||||||
// map double vaddr page to support uniform ring buffer r/w
|
// map double vaddr page to support uniform ring buffer r/w
|
||||||
uintptr_t vaddr = (uintptr_t)NULL;
|
uintptr_t vaddr = (uintptr_t)NULL;
|
||||||
if (task->massive_ipc_allocator != NULL) {
|
if (task->memspace->massive_ipc_allocator != NULL) {
|
||||||
vaddr = (uintptr_t)KBuddyAlloc(task->massive_ipc_allocator, PAGE_SIZE * nr_pages * 2);
|
vaddr = (uintptr_t)KBuddyAlloc(task->memspace->massive_ipc_allocator, PAGE_SIZE * nr_pages * 2);
|
||||||
assert(xizi_pager.address_translate(&task->pgdir, vaddr) == (uintptr_t)NULL);
|
assert(xizi_pager.address_translate(&task->memspace->pgdir, vaddr) == (uintptr_t)NULL);
|
||||||
} else {
|
} else {
|
||||||
vaddr = alloc_share_page_addr(task, nr_pages * 2);
|
vaddr = alloc_share_page_addr(task, nr_pages * 2);
|
||||||
if (vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) {
|
if (vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) {
|
||||||
task->massive_ipc_allocator = (struct KBuddy*)slab_alloc(&xizi_task_manager.task_buddy_allocator);
|
task->memspace->massive_ipc_allocator = (struct KBuddy*)slab_alloc(&xizi_task_manager.task_buddy_allocator);
|
||||||
KBuddyInit(task->massive_ipc_allocator, USER_IPC_USE_ALLOCATOR_WATERMARK, USER_IPC_SPACE_TOP);
|
KBuddyInit(task->memspace->massive_ipc_allocator, USER_IPC_USE_ALLOCATOR_WATERMARK, USER_IPC_SPACE_TOP);
|
||||||
if (!task->massive_ipc_allocator) {
|
if (!task->memspace->massive_ipc_allocator) {
|
||||||
ERROR("Alloc task buddy failed.\n");
|
ERROR("Alloc task buddy failed.\n");
|
||||||
return (uintptr_t)NULL;
|
return (uintptr_t)NULL;
|
||||||
}
|
}
|
||||||
|
@ -112,11 +112,11 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin
|
||||||
if (UNLIKELY(vaddr == (uintptr_t)NULL)) {
|
if (UNLIKELY(vaddr == (uintptr_t)NULL)) {
|
||||||
return (uintptr_t)NULL;
|
return (uintptr_t)NULL;
|
||||||
}
|
}
|
||||||
if (!xizi_pager.map_pages(task->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, false)) {
|
if (!xizi_pager.map_pages(task->memspace->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, false)) {
|
||||||
return (uintptr_t)NULL;
|
return (uintptr_t)NULL;
|
||||||
}
|
}
|
||||||
if (!xizi_pager.map_pages(task->pgdir.pd_addr, vaddr + (nr_pages * PAGE_SIZE), paddr, nr_pages * PAGE_SIZE, false)) {
|
if (!xizi_pager.map_pages(task->memspace->pgdir.pd_addr, vaddr + (nr_pages * PAGE_SIZE), paddr, nr_pages * PAGE_SIZE, false)) {
|
||||||
xizi_pager.unmap_pages(task->pgdir.pd_addr, vaddr, nr_pages * PAGE_SIZE);
|
xizi_pager.unmap_pages(task->memspace->pgdir.pd_addr, vaddr, nr_pages * PAGE_SIZE);
|
||||||
return (uintptr_t)NULL;
|
return (uintptr_t)NULL;
|
||||||
}
|
}
|
||||||
if (task == cur_cpu()->task) {
|
if (task == cur_cpu()->task) {
|
||||||
|
@ -128,7 +128,7 @@ static uintptr_t map_task_share_page(struct TaskMicroDescriptor* task, const uin
|
||||||
return vaddr;
|
return vaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t task_map_pages(struct TaskMicroDescriptor* task, const uintptr_t vaddr, const uintptr_t paddr, const int nr_pages, const int is_dev)
|
uintptr_t task_map_pages(struct Thread* task, const uintptr_t vaddr, const uintptr_t paddr, const int nr_pages, const int is_dev)
|
||||||
{
|
{
|
||||||
/* get driver codes */
|
/* get driver codes */
|
||||||
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
|
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
|
||||||
|
@ -136,9 +136,9 @@ uintptr_t task_map_pages(struct TaskMicroDescriptor* task, const uintptr_t vaddr
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
if (is_dev) {
|
if (is_dev) {
|
||||||
ret = xizi_pager.map_pages(task->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, true);
|
ret = xizi_pager.map_pages(task->memspace->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, true);
|
||||||
} else {
|
} else {
|
||||||
ret = xizi_pager.map_pages(task->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, false);
|
ret = xizi_pager.map_pages(task->memspace->pgdir.pd_addr, vaddr, paddr, nr_pages * PAGE_SIZE, false);
|
||||||
}
|
}
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
return (uintptr_t)NULL;
|
return (uintptr_t)NULL;
|
||||||
|
@ -153,16 +153,16 @@ uintptr_t task_map_pages(struct TaskMicroDescriptor* task, const uintptr_t vaddr
|
||||||
return vaddr;
|
return vaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmap_task_share_pages(struct TaskMicroDescriptor* task, const uintptr_t task_vaddr, const int nr_pages)
|
void unmap_task_share_pages(struct Thread* task, const uintptr_t task_vaddr, const int nr_pages)
|
||||||
{
|
{
|
||||||
/* get driver codes */
|
/* get driver codes */
|
||||||
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
|
struct DCacheDone* p_dcache_done = AchieveResource(&right_group.dcache_driver_tag);
|
||||||
struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag);
|
struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag);
|
||||||
|
|
||||||
xizi_pager.unmap_pages(task->pgdir.pd_addr, task_vaddr, nr_pages * PAGE_SIZE);
|
xizi_pager.unmap_pages(task->memspace->pgdir.pd_addr, task_vaddr, nr_pages * PAGE_SIZE);
|
||||||
xizi_pager.unmap_pages(task->pgdir.pd_addr, task_vaddr + (nr_pages * PAGE_SIZE), nr_pages * PAGE_SIZE);
|
xizi_pager.unmap_pages(task->memspace->pgdir.pd_addr, task_vaddr + (nr_pages * PAGE_SIZE), nr_pages * PAGE_SIZE);
|
||||||
if (task_vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) {
|
if (task_vaddr >= USER_IPC_USE_ALLOCATOR_WATERMARK) {
|
||||||
KBuddyFree(task->massive_ipc_allocator, (void*)task_vaddr);
|
KBuddyFree(task->memspace->massive_ipc_allocator, (void*)task_vaddr);
|
||||||
}
|
}
|
||||||
if (task == cur_cpu()->task) {
|
if (task == cur_cpu()->task) {
|
||||||
p_mmu_driver->TlbFlush(task_vaddr, 2 * nr_pages * PAGE_SIZE);
|
p_mmu_driver->TlbFlush(task_vaddr, 2 * nr_pages * PAGE_SIZE);
|
||||||
|
@ -173,7 +173,7 @@ void unmap_task_share_pages(struct TaskMicroDescriptor* task, const uintptr_t ta
|
||||||
}
|
}
|
||||||
|
|
||||||
static int next_session_id = 1;
|
static int next_session_id = 1;
|
||||||
struct session_backend* create_share_pages(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, const int capacity)
|
struct session_backend* create_share_pages(struct Thread* client, struct Thread* server, const int capacity)
|
||||||
{
|
{
|
||||||
struct session_backend* session_backend = (struct session_backend*)slab_alloc(SessionAllocator());
|
struct session_backend* session_backend = (struct session_backend*)slab_alloc(SessionAllocator());
|
||||||
if (UNLIKELY(session_backend == NULL)) {
|
if (UNLIKELY(session_backend == NULL)) {
|
||||||
|
@ -223,8 +223,8 @@ struct session_backend* create_share_pages(struct TaskMicroDescriptor* client, s
|
||||||
doubleListNodeInit(&session_backend->server_side.node);
|
doubleListNodeInit(&session_backend->server_side.node);
|
||||||
doubleListAddOnBack(&session_backend->server_side.node, &server->svr_sess_listhead);
|
doubleListAddOnBack(&session_backend->server_side.node, &server->svr_sess_listhead);
|
||||||
|
|
||||||
server->mem_size += true_capacity;
|
server->memspace->mem_size += true_capacity;
|
||||||
client->mem_size += true_capacity;
|
client->memspace->mem_size += true_capacity;
|
||||||
|
|
||||||
return session_backend;
|
return session_backend;
|
||||||
}
|
}
|
||||||
|
@ -248,7 +248,7 @@ int delete_share_pages(struct session_backend* session_backend)
|
||||||
if (session_backend->server_side.closed && session_backend->server != NULL) {
|
if (session_backend->server_side.closed && session_backend->server != NULL) {
|
||||||
xizi_share_page_manager.unmap_task_share_pages(session_backend->server, session_backend->server_side.buf_addr, session_backend->nr_pages);
|
xizi_share_page_manager.unmap_task_share_pages(session_backend->server, session_backend->server_side.buf_addr, session_backend->nr_pages);
|
||||||
doubleListDel(&session_backend->server_side.node);
|
doubleListDel(&session_backend->server_side.node);
|
||||||
session_backend->server->mem_size -= session_backend->nr_pages * PAGE_SIZE;
|
session_backend->server->memspace->mem_size -= session_backend->nr_pages * PAGE_SIZE;
|
||||||
session_backend->server = NULL;
|
session_backend->server = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ int delete_share_pages(struct session_backend* session_backend)
|
||||||
if (session_backend->client_side.closed && session_backend->client != NULL) {
|
if (session_backend->client_side.closed && session_backend->client != NULL) {
|
||||||
xizi_share_page_manager.unmap_task_share_pages(session_backend->client, session_backend->client_side.buf_addr, session_backend->nr_pages);
|
xizi_share_page_manager.unmap_task_share_pages(session_backend->client, session_backend->client_side.buf_addr, session_backend->nr_pages);
|
||||||
doubleListDel(&session_backend->client_side.node);
|
doubleListDel(&session_backend->client_side.node);
|
||||||
session_backend->client->mem_size -= session_backend->nr_pages * PAGE_SIZE;
|
session_backend->client->memspace->mem_size -= session_backend->nr_pages * PAGE_SIZE;
|
||||||
session_backend->client = NULL;
|
session_backend->client = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
SRC_FILES := syscall.c \
|
SRC_FILES := syscall.c \
|
||||||
sys_spawn.c \
|
sys_spawn.c \
|
||||||
sys_exec.c \
|
sys_thread.c \
|
||||||
sys_yield.c \
|
sys_yield.c \
|
||||||
sys_register_as_server.c \
|
sys_register_as_server.c \
|
||||||
sys_connect_session.c \
|
sys_connect_session.c \
|
||||||
|
|
|
@ -38,7 +38,7 @@ Modification:
|
||||||
/// @param cur_task
|
/// @param cur_task
|
||||||
/// @param session
|
/// @param session
|
||||||
/// @return
|
/// @return
|
||||||
int sys_close_session(struct TaskMicroDescriptor* cur_task, struct Session* session)
|
int sys_close_session(struct Thread* cur_task, struct Session* session)
|
||||||
{
|
{
|
||||||
assert(cur_task != NULL);
|
assert(cur_task != NULL);
|
||||||
/* check if session is available */
|
/* check if session is available */
|
||||||
|
|
|
@ -35,7 +35,7 @@ Modification:
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
struct session_backend* create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session)
|
struct session_backend* create_session_inner(struct Thread* client, struct Thread* server, int capacity, struct Session* user_session)
|
||||||
{
|
{
|
||||||
// create share pages
|
// create share pages
|
||||||
assert(server != NULL && client != NULL);
|
assert(server != NULL && client != NULL);
|
||||||
|
@ -61,7 +61,7 @@ int sys_connect_session(char* path, int capacity, struct Session* user_session)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* client = cur_cpu()->task;
|
struct Thread* client = cur_cpu()->task;
|
||||||
/// get server
|
/// get server
|
||||||
struct TraceTag server_identifier_owner;
|
struct TraceTag server_identifier_owner;
|
||||||
if (!AchieveResourceTag(&server_identifier_owner, RequireRootTag(), "softkernel/server-identifier")) {
|
if (!AchieveResourceTag(&server_identifier_owner, RequireRootTag(), "softkernel/server-identifier")) {
|
||||||
|
@ -75,7 +75,7 @@ int sys_connect_session(char* path, int capacity, struct Session* user_session)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* server = AchieveResource(&server_tag);
|
struct Thread* server = AchieveResource(&server_tag);
|
||||||
assert(server != NULL);
|
assert(server != NULL);
|
||||||
if (create_session_inner(client, server, capacity, user_session) == NULL) {
|
if (create_session_inner(client, server, capacity, user_session) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -66,7 +66,7 @@ Modification:
|
||||||
/// @param path path to elf file
|
/// @param path path to elf file
|
||||||
/// @param argv arguments giving to main
|
/// @param argv arguments giving to main
|
||||||
/// @return
|
/// @return
|
||||||
int task_exec(struct TaskMicroDescriptor* task, char* img_start, char* name, char** argv)
|
int task_exec(struct Thread* task, char* img_start, char* name, char** argv)
|
||||||
{
|
{
|
||||||
/* load img to task */
|
/* load img to task */
|
||||||
if (img_start == NULL) {
|
if (img_start == NULL) {
|
||||||
|
@ -163,8 +163,8 @@ int task_exec(struct TaskMicroDescriptor* task, char* img_start, char* name, cha
|
||||||
// init task trapframe, which stores in svc stack
|
// init task trapframe, which stores in svc stack
|
||||||
// do not go tp error_exec once we change trapframe!
|
// do not go tp error_exec once we change trapframe!
|
||||||
assert(copied_len == (argc + 1) * sizeof(uintptr_t));
|
assert(copied_len == (argc + 1) * sizeof(uintptr_t));
|
||||||
arch_trapframe_set_sp_pc(task->main_thread.trapframe, user_vspace_sp, elf.entry);
|
arch_trapframe_set_sp_pc(task->thread_context.trapframe, user_vspace_sp, elf.entry);
|
||||||
arch_set_main_params(task->main_thread.trapframe, argc, user_vspace_sp);
|
arch_set_main_params(task->thread_context.trapframe, argc, user_vspace_sp);
|
||||||
|
|
||||||
// save program name
|
// save program name
|
||||||
char* last = NULL;
|
char* last = NULL;
|
||||||
|
@ -202,7 +202,7 @@ int sys_exec(char* img_start, char* name, char** argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MmuCommonDone* p_mmu_driver = AchieveResource(&mmu_driver_tag);
|
struct MmuCommonDone* p_mmu_driver = AchieveResource(&mmu_driver_tag);
|
||||||
struct TaskMicroDescriptor* current_task = cur_cpu()->task;
|
struct Thread* current_task = cur_cpu()->task;
|
||||||
int ret = task_exec(current_task, img_start, name, argv);
|
int ret = task_exec(current_task, img_start, name, argv);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
p_mmu_driver->LoadPgdir((uintptr_t)V2P(current_task->pgdir.pd_addr));
|
p_mmu_driver->LoadPgdir((uintptr_t)V2P(current_task->pgdir.pd_addr));
|
||||||
|
|
|
@ -36,7 +36,7 @@ Modification:
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
int sys_exit(struct TaskMicroDescriptor* ptask)
|
int sys_exit(struct Thread* ptask)
|
||||||
{
|
{
|
||||||
assert(ptask != NULL);
|
assert(ptask != NULL);
|
||||||
ptask->dead = true;
|
ptask->dead = true;
|
||||||
|
|
|
@ -31,14 +31,14 @@ Modification:
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
extern int sys_exit(struct TaskMicroDescriptor* task);
|
extern int sys_exit(struct Thread* task);
|
||||||
int sys_kill(int id)
|
int sys_kill(int id)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* task = NULL;
|
struct Thread* task = NULL;
|
||||||
// check if task is a running one
|
// check if task is a running one
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_running_list_head, node)
|
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_running_list_head, node)
|
||||||
{
|
{
|
||||||
if (task->pid == id) {
|
if (task->tid == id) {
|
||||||
sys_exit(task);
|
sys_exit(task);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ int sys_kill(int id)
|
||||||
// check if task is a blocking one
|
// check if task is a blocking one
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_blocked_list_head, node)
|
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_blocked_list_head, node)
|
||||||
{
|
{
|
||||||
if (task->pid == id) {
|
if (task->tid == id) {
|
||||||
sys_exit(task);
|
sys_exit(task);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ int sys_kill(int id)
|
||||||
for (int prio = 0; prio < TASK_MAX_PRIORITY; prio++) {
|
for (int prio = 0; prio < TASK_MAX_PRIORITY; prio++) {
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[prio], node)
|
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[prio], node)
|
||||||
{
|
{
|
||||||
if (task->pid == id) {
|
if (task->tid == id) {
|
||||||
sys_exit(task);
|
sys_exit(task);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,15 @@ Modification:
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "multicores.h"
|
|
||||||
#include "kalloc.h"
|
#include "kalloc.h"
|
||||||
|
#include "multicores.h"
|
||||||
#include "share_page.h"
|
#include "share_page.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev)
|
int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
assert(cur_task != NULL);
|
assert(cur_task != NULL);
|
||||||
|
|
||||||
int true_len = ALIGNUP(len, PAGE_SIZE);
|
int true_len = ALIGNUP(len, PAGE_SIZE);
|
||||||
|
@ -64,6 +64,6 @@ int sys_mmap(uintptr_t vaddr, uintptr_t paddr, int len, int is_dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_task->mem_size += true_len;
|
cur_task->memspace->mem_size += true_len;
|
||||||
return vaddr + true_len;
|
return vaddr + true_len;
|
||||||
}
|
}
|
|
@ -44,7 +44,7 @@ static inline bool is_msg_needed(struct IpcMsg* msg)
|
||||||
|
|
||||||
int sys_poll_session(struct Session* userland_session_arr, int arr_capacity)
|
int sys_poll_session(struct Session* userland_session_arr, int arr_capacity)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
if (cur_task == NULL) {
|
if (cur_task == NULL) {
|
||||||
ERROR("%s by killed task\n");
|
ERROR("%s by killed task\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -66,7 +66,7 @@ int sys_poll_session(struct Session* userland_session_arr, int arr_capacity)
|
||||||
// update session_backend
|
// update session_backend
|
||||||
// if current session is handled
|
// if current session is handled
|
||||||
if (server_session->head != userland_session_arr[i].head) {
|
if (server_session->head != userland_session_arr[i].head) {
|
||||||
struct TaskMicroDescriptor* client = SERVER_SESSION_BACKEND(server_session)->client;
|
struct Thread* client = SERVER_SESSION_BACKEND(server_session)->client;
|
||||||
if (client->state == BLOCKED) {
|
if (client->state == BLOCKED) {
|
||||||
xizi_task_manager.task_unblock(client);
|
xizi_task_manager.task_unblock(client);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -39,7 +39,7 @@ Modification:
|
||||||
|
|
||||||
int sys_register_as_server(char* name)
|
int sys_register_as_server(char* name)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* server = cur_cpu()->task;
|
struct Thread* server = cur_cpu()->task;
|
||||||
struct TraceTag server_identifier_set_tag;
|
struct TraceTag server_identifier_set_tag;
|
||||||
if (!AchieveResourceTag(&server_identifier_set_tag, RequireRootTag(), "softkernel/server-identifier")) {
|
if (!AchieveResourceTag(&server_identifier_set_tag, RequireRootTag(), "softkernel/server-identifier")) {
|
||||||
panic("Server identifier not initialized.\b");
|
panic("Server identifier not initialized.\b");
|
||||||
|
|
|
@ -34,15 +34,15 @@ Modification:
|
||||||
#include "actracer.h"
|
#include "actracer.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
#include "kalloc.h"
|
#include "memspace.h"
|
||||||
#include "multicores.h"
|
#include "multicores.h"
|
||||||
#include "share_page.h"
|
#include "share_page.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
static struct TaskMicroDescriptor* kernel_irq_proxy;
|
static struct Thread* kernel_irq_proxy;
|
||||||
static struct {
|
static struct {
|
||||||
struct TaskMicroDescriptor* handle_task;
|
struct Thread* handle_task;
|
||||||
struct Session session;
|
struct Session session;
|
||||||
struct session_backend* p_kernel_session;
|
struct session_backend* p_kernel_session;
|
||||||
int opcode;
|
int opcode;
|
||||||
|
@ -56,7 +56,7 @@ static void send_irq_to_user(int irq_num)
|
||||||
len += sizeof(struct IpcArgInfo);
|
len += sizeof(struct IpcArgInfo);
|
||||||
|
|
||||||
/* get message space and add session tail */
|
/* get message space and add session tail */
|
||||||
void* session_kern_vaddr = P2V(xizi_pager.address_translate(&kernel_irq_proxy->pgdir, (uintptr_t)session->buf));
|
void* session_kern_vaddr = P2V(xizi_pager.address_translate(&kernel_irq_proxy->memspace->pgdir, (uintptr_t)session->buf));
|
||||||
struct IpcMsg* buf = session_kern_vaddr + session->tail;
|
struct IpcMsg* buf = session_kern_vaddr + session->tail;
|
||||||
|
|
||||||
/* check if server session is full */
|
/* check if server session is full */
|
||||||
|
@ -98,7 +98,7 @@ int user_irq_handler(int irq, void* tf, void* arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct session_backend* create_session_inner(struct TaskMicroDescriptor* client, struct TaskMicroDescriptor* server, int capacity, struct Session* user_session);
|
extern struct session_backend* create_session_inner(struct Thread* client, struct Thread* server, int capacity, struct Session* user_session);
|
||||||
/// @warning no tested.
|
/// @warning no tested.
|
||||||
|
|
||||||
static struct XiziTrapDriver* p_intr_driver = NULL;
|
static struct XiziTrapDriver* p_intr_driver = NULL;
|
||||||
|
@ -116,10 +116,16 @@ int sys_register_irq(int irq_num, int irq_opcode)
|
||||||
|
|
||||||
// init kerenl sender proxy
|
// init kerenl sender proxy
|
||||||
if (kernel_irq_proxy == NULL) {
|
if (kernel_irq_proxy == NULL) {
|
||||||
kernel_irq_proxy = xizi_task_manager.new_task_cb();
|
/// @todo handle corner cases
|
||||||
|
struct MemSpace* pmemspace = alloc_memspace();
|
||||||
|
if (pmemspace == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xizi_pager.new_pgdir(&pmemspace->pgdir);
|
||||||
|
memcpy(pmemspace->pgdir.pd_addr, kern_pgdir.pd_addr, TOPLEVLE_PAGEDIR_SIZE);
|
||||||
|
|
||||||
|
kernel_irq_proxy = xizi_task_manager.new_task_cb(pmemspace);
|
||||||
kernel_irq_proxy->state = NEVER_RUN;
|
kernel_irq_proxy->state = NEVER_RUN;
|
||||||
xizi_pager.new_pgdir(&kernel_irq_proxy->pgdir);
|
|
||||||
memcpy(kernel_irq_proxy->pgdir.pd_addr, kern_pgdir.pd_addr, TOPLEVLE_PAGEDIR_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind irq to session
|
// bind irq to session
|
||||||
|
@ -127,7 +133,7 @@ int sys_register_irq(int irq_num, int irq_opcode)
|
||||||
ERROR("irq %d is occupied.\n", irq_num);
|
ERROR("irq %d is occupied.\n", irq_num);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
irq_forward_table[irq_num].handle_task = cur_task;
|
irq_forward_table[irq_num].handle_task = cur_task;
|
||||||
irq_forward_table[irq_num].opcode = irq_opcode;
|
irq_forward_table[irq_num].opcode = irq_opcode;
|
||||||
irq_forward_table[irq_num].p_kernel_session = create_session_inner(kernel_irq_proxy, cur_task, PAGE_SIZE, &irq_forward_table[irq_num].session);
|
irq_forward_table[irq_num].p_kernel_session = create_session_inner(kernel_irq_proxy, cur_task, PAGE_SIZE, &irq_forward_table[irq_num].session);
|
||||||
|
@ -137,7 +143,7 @@ int sys_register_irq(int irq_num, int irq_opcode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_unbind_irq(struct TaskMicroDescriptor* task, int irq_num)
|
int sys_unbind_irq(struct Thread* task, int irq_num)
|
||||||
{
|
{
|
||||||
if (irq_forward_table[irq_num].handle_task != task) {
|
if (irq_forward_table[irq_num].handle_task != task) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -147,7 +153,7 @@ int sys_unbind_irq(struct TaskMicroDescriptor* task, int irq_num)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_unbind_irq_all(struct TaskMicroDescriptor* task)
|
int sys_unbind_irq_all(struct Thread* task)
|
||||||
{
|
{
|
||||||
for (int idx = 0; idx < NR_IRQS; idx++) {
|
for (int idx = 0; idx < NR_IRQS; idx++) {
|
||||||
if (irq_forward_table[idx].handle_task == task) {
|
if (irq_forward_table[idx].handle_task == task) {
|
||||||
|
|
|
@ -29,27 +29,36 @@ Modification:
|
||||||
*************************************************/
|
*************************************************/
|
||||||
#include "actracer.h"
|
#include "actracer.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include "memspace.h"
|
||||||
#include "share_page.h"
|
#include "share_page.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
extern int task_exec(struct TaskMicroDescriptor* 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)
|
int sys_spawn(char* img_start, char* name, char** argv)
|
||||||
{
|
{
|
||||||
|
// alloc a new memspace
|
||||||
|
struct MemSpace* pmemspace = alloc_memspace();
|
||||||
|
if (pmemspace == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load memspace
|
||||||
|
uintptr_t* entry = load_memspace(pmemspace, img_start);
|
||||||
|
if (NULL == entry) {
|
||||||
|
ERROR("Loading memspace from %016x failed.\n", img_start);
|
||||||
|
free_memspace(pmemspace);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// alloc a new pcb
|
// alloc a new pcb
|
||||||
struct TaskMicroDescriptor* new_task_cb = xizi_task_manager.new_task_cb();
|
struct Thread* new_task_cb = xizi_task_manager.new_task_cb(pmemspace);
|
||||||
if (UNLIKELY(!new_task_cb)) {
|
if (UNLIKELY(!new_task_cb)) {
|
||||||
ERROR("Unable to new task control block.\n");
|
ERROR("Unable to new task control block.\n");
|
||||||
|
free_memspace(pmemspace);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// init trapframe
|
assert(!IS_DOUBLE_LIST_EMPTY(&pmemspace->thread_list_guard));
|
||||||
arch_init_trapframe(new_task_cb->main_thread.trapframe, 0, 0);
|
|
||||||
if (UNLIKELY(task_exec(new_task_cb, img_start, name, argv)) < 0) {
|
|
||||||
xizi_task_manager.free_pcb(new_task_cb);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// init pcb
|
|
||||||
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);
|
||||||
}
|
}
|
|
@ -41,11 +41,11 @@ Modification:
|
||||||
extern uint8_t _binary_fs_img_start[], _binary_fs_img_end[];
|
extern uint8_t _binary_fs_img_start[], _binary_fs_img_end[];
|
||||||
|
|
||||||
#define SHOWINFO_BORDER_LINE() LOG_PRINTF("******************************************************\n");
|
#define SHOWINFO_BORDER_LINE() LOG_PRINTF("******************************************************\n");
|
||||||
#define SHOWTASK_TASK_BASE_INFO(task) LOG_PRINTF(" %-6d %-16s %-4d 0x%x(%-d)\n", task->pid, task->name, task->priority, task->mem_size >> 10, task->mem_size >> 10)
|
#define SHOWTASK_TASK_BASE_INFO(task) LOG_PRINTF(" %-6d %-16s %-4d 0x%x(%-d)\n", task->tid, task->name, task->priority, task->memspace->mem_size >> 10, task->memspace->mem_size >> 10)
|
||||||
|
|
||||||
void show_tasks(void)
|
void show_tasks(void)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* task = NULL;
|
struct Thread* task = NULL;
|
||||||
SHOWINFO_BORDER_LINE();
|
SHOWINFO_BORDER_LINE();
|
||||||
for (int i = 0; i < NR_CPU; i++) {
|
for (int i = 0; i < NR_CPU; i++) {
|
||||||
LOG_PRINTF("CPU %-2d: %s\n", i, (global_cpus[i].task == NULL ? "NULL" : global_cpus[i].task->name));
|
LOG_PRINTF("CPU %-2d: %s\n", i, (global_cpus[i].task == NULL ? "NULL" : global_cpus[i].task->name));
|
||||||
|
@ -128,7 +128,7 @@ void show_cpu(void)
|
||||||
|
|
||||||
int cpu_id = 0;
|
int cpu_id = 0;
|
||||||
|
|
||||||
struct TaskMicroDescriptor* current_task = cur_cpu()->task;
|
struct Thread* current_task = cur_cpu()->task;
|
||||||
assert(current_task != NULL);
|
assert(current_task != NULL);
|
||||||
|
|
||||||
LOG_PRINTF(" ID COMMAND USED_TICKS FREE_TICKS \n");
|
LOG_PRINTF(" ID COMMAND USED_TICKS FREE_TICKS \n");
|
||||||
|
@ -144,7 +144,7 @@ int sys_state(sys_state_option option, sys_state_info* info)
|
||||||
info->memblock_info.memblock_start = (uintptr_t)V2P(_binary_fs_img_start);
|
info->memblock_info.memblock_start = (uintptr_t)V2P(_binary_fs_img_start);
|
||||||
info->memblock_info.memblock_end = (uintptr_t)V2P(_binary_fs_img_end);
|
info->memblock_info.memblock_end = (uintptr_t)V2P(_binary_fs_img_end);
|
||||||
} else if (option == SYS_STATE_GET_HEAP_BASE) {
|
} else if (option == SYS_STATE_GET_HEAP_BASE) {
|
||||||
return cur_cpu()->task->heap_base;
|
return cur_cpu()->task->memspace->heap_base;
|
||||||
} else if (option == SYS_STATE_SET_TASK_PRIORITY) {
|
} else if (option == SYS_STATE_SET_TASK_PRIORITY) {
|
||||||
xizi_task_manager.set_cur_task_priority(info->priority);
|
xizi_task_manager.set_cur_task_priority(info->priority);
|
||||||
} else if (option == SYS_STATE_SHOW_TASKS) {
|
} else if (option == SYS_STATE_SHOW_TASKS) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ Modification:
|
||||||
|
|
||||||
int sys_yield(task_yield_reason reason)
|
int sys_yield(task_yield_reason reason)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
xizi_task_manager.task_yield_noschedule(cur_task, false);
|
xizi_task_manager.task_yield_noschedule(cur_task, false);
|
||||||
|
|
||||||
// handle ipc block
|
// handle ipc block
|
||||||
|
|
|
@ -44,6 +44,9 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u
|
||||||
case SYSCALL_SPAWN:
|
case SYSCALL_SPAWN:
|
||||||
ret = sys_spawn((char*)param1, (char*)param2, (char**)param3);
|
ret = sys_spawn((char*)param1, (char*)param2, (char**)param3);
|
||||||
break;
|
break;
|
||||||
|
case SYSCALL_THREAD:
|
||||||
|
ret = sys_thread((uintptr_t)param1, (char*)param2, (char**)param3);
|
||||||
|
break;
|
||||||
case SYSCALL_EXIT:
|
case SYSCALL_EXIT:
|
||||||
ret = sys_exit(cur_cpu()->task);
|
ret = sys_exit(cur_cpu()->task);
|
||||||
break;
|
break;
|
||||||
|
@ -62,9 +65,6 @@ int syscall(int sys_num, uintptr_t param1, uintptr_t param2, uintptr_t param3, u
|
||||||
case SYSCALL_CLOSE_SESSION:
|
case SYSCALL_CLOSE_SESSION:
|
||||||
ret = sys_close_session(cur_cpu()->task, (struct Session*)param1);
|
ret = sys_close_session(cur_cpu()->task, (struct Session*)param1);
|
||||||
break;
|
break;
|
||||||
case SYSCALL_EXEC:
|
|
||||||
ret = sys_exec((char*)param1, (char*)param2, (char**)param3);
|
|
||||||
break;
|
|
||||||
case SYSCALL_SYS_STATE:
|
case SYSCALL_SYS_STATE:
|
||||||
ret = sys_state(param1, (sys_state_info*)param2);
|
ret = sys_state(param1, (sys_state_info*)param2);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
SRC_FILES := task.c schedule.c
|
SRC_FILES := task.c schedule.c memspace.c
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* 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 memspace.c
|
||||||
|
* @brief memspace loader
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2023.08.25
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
File name: memspace.c
|
||||||
|
Description: memspace loader
|
||||||
|
Others:
|
||||||
|
History:
|
||||||
|
1. Date: 2023-08-28
|
||||||
|
Author: AIIT XUOS Lab
|
||||||
|
Modification:
|
||||||
|
1. first version
|
||||||
|
*************************************************/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "bitmap64.h"
|
||||||
|
#include "execelf.h"
|
||||||
|
#include "kalloc.h"
|
||||||
|
#include "memspace.h"
|
||||||
|
#include "pagetable.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
#define MAX_SUPPORT_PARAMS 32
|
||||||
|
|
||||||
|
struct MemSpace* alloc_memspace()
|
||||||
|
{
|
||||||
|
struct MemSpace* pmemspace = slab_alloc(&xizi_task_manager.memspace_allocator);
|
||||||
|
if (pmemspace == NULL) {
|
||||||
|
ERROR("Alloc memspace for thread failed.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap64_init(&pmemspace->thread_stack_idx_bitmap);
|
||||||
|
doubleListNodeInit(&pmemspace->thread_list_guard);
|
||||||
|
pmemspace->massive_ipc_allocator = NULL;
|
||||||
|
pmemspace->heap_base = 0;
|
||||||
|
pmemspace->mem_size = 0;
|
||||||
|
pmemspace->pgdir.pd_addr = 0;
|
||||||
|
return pmemspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_memspace(struct MemSpace* pmemspace)
|
||||||
|
{
|
||||||
|
assert(pmemspace != NULL);
|
||||||
|
|
||||||
|
/* free page table and all its allocated memories */
|
||||||
|
if (pmemspace->pgdir.pd_addr != NULL) {
|
||||||
|
xizi_pager.free_user_pgdir(&pmemspace->pgdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free ipc virt address allocator */
|
||||||
|
if (pmemspace->massive_ipc_allocator != NULL) {
|
||||||
|
KBuddyDestory(pmemspace->massive_ipc_allocator);
|
||||||
|
slab_free(&xizi_task_manager.task_buddy_allocator, (void*)pmemspace->massive_ipc_allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
slab_free(&xizi_task_manager.memspace_allocator, (void*)pmemspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @return return the entry of program
|
||||||
|
uintptr_t* load_memspace(struct MemSpace* pmemspace, char* img_start)
|
||||||
|
{
|
||||||
|
if (pmemspace == NULL) {
|
||||||
|
ERROR("Loading an empty memspace.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (img_start == NULL) {
|
||||||
|
ERROR("Empty elf file.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1. load elf header */
|
||||||
|
struct elfhdr elf;
|
||||||
|
memcpy((void*)&elf, img_start, sizeof(elf));
|
||||||
|
if (elf.magic != ELF_MAGIC) {
|
||||||
|
ERROR("Not an elf file.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a pgdir */
|
||||||
|
/* only supports first inited memspace */
|
||||||
|
assert(pmemspace->pgdir.pd_addr == NULL);
|
||||||
|
struct TopLevelPageDirectory pgdir;
|
||||||
|
pgdir.pd_addr = NULL;
|
||||||
|
if (UNLIKELY(!xizi_pager.new_pgdir(&pgdir))) {
|
||||||
|
ERROR("Create new pgdir failed.\n");
|
||||||
|
goto error_exec;
|
||||||
|
}
|
||||||
|
/* copy kernel pagetable so that interrupt and syscall wont corrupt */
|
||||||
|
memcpy(pgdir.pd_addr, kern_pgdir.pd_addr, TOPLEVLE_PAGEDIR_SIZE);
|
||||||
|
|
||||||
|
// read elf file by (header, section)
|
||||||
|
uintptr_t load_size = 0;
|
||||||
|
struct proghdr ph;
|
||||||
|
for (int sec_idx = 0, off = elf.phoff; sec_idx < elf.phnum; sec_idx++, off += sizeof(ph)) {
|
||||||
|
// load proghdr
|
||||||
|
memcpy((char*)&ph, img_start + off, sizeof(ph));
|
||||||
|
|
||||||
|
if (ph.type != ELF_PROG_LOAD)
|
||||||
|
continue;
|
||||||
|
if (ph.memsz < ph.filesz) {
|
||||||
|
ERROR("elf header mem size less than file size\n");
|
||||||
|
goto error_exec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read section
|
||||||
|
// 1. alloc space
|
||||||
|
if ((load_size = xizi_pager.resize_user_pgdir(&pgdir, load_size, ph.vaddr + ph.memsz))
|
||||||
|
!= ph.vaddr + ph.memsz) {
|
||||||
|
goto error_exec;
|
||||||
|
}
|
||||||
|
// 2. copy inode to space
|
||||||
|
assert(ph.vaddr % PAGE_SIZE == 0);
|
||||||
|
for (int addr_offset = 0; addr_offset < ph.filesz; addr_offset += PAGE_SIZE) {
|
||||||
|
uintptr_t page_paddr = xizi_pager.address_translate(&pgdir, ph.vaddr + addr_offset);
|
||||||
|
if (page_paddr == 0) {
|
||||||
|
ERROR("copy elf file to unmapped addr: %x(pgdir: %x)\n", ph.vaddr + addr_offset, pgdir.pd_addr);
|
||||||
|
goto error_exec;
|
||||||
|
}
|
||||||
|
uintptr_t read_size = (ph.filesz - addr_offset < PAGE_SIZE ? ph.filesz - addr_offset : PAGE_SIZE);
|
||||||
|
memcpy(P2V(page_paddr), img_start + (ph.off + addr_offset), read_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// elf file content now in memory
|
||||||
|
// memspace will use this page dir
|
||||||
|
pmemspace->pgdir = pgdir;
|
||||||
|
pmemspace->heap_base = ALIGNUP(load_size, PAGE_SIZE);
|
||||||
|
pmemspace->mem_size = pmemspace->heap_base;
|
||||||
|
|
||||||
|
return (uintptr_t*)elf.entry;
|
||||||
|
|
||||||
|
error_exec:
|
||||||
|
if (pgdir.pd_addr != NULL) {
|
||||||
|
xizi_pager.free_user_pgdir(&pgdir);
|
||||||
|
}
|
||||||
|
ERROR("Error loading memspace.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_error_stack_loading(struct MemSpace* pmemspace, int stack_idx, uintptr_t* stack_bottom, bool is_mapped_successful)
|
||||||
|
{
|
||||||
|
if (stack_idx != -1) {
|
||||||
|
bitmap64_free(&pmemspace->thread_stack_idx_bitmap, stack_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_bottom != NULL) {
|
||||||
|
kfree((char*)stack_bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_mapped_successful) {
|
||||||
|
xizi_pager.unmap_pages(pmemspace->pgdir.pd_addr, USER_MEM_TOP - ((stack_idx + 1) * USER_STACK_SIZE), USER_STACK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @return return thread's user stack index
|
||||||
|
struct ThreadStackPointer load_user_stack(struct MemSpace* pmemspace, char** argv)
|
||||||
|
{
|
||||||
|
/* usages of load_user_stack() must be correct */
|
||||||
|
assert(pmemspace != NULL);
|
||||||
|
assert(pmemspace->pgdir.pd_addr != NULL);
|
||||||
|
assert(argv != NULL);
|
||||||
|
|
||||||
|
struct ThreadStackPointer loaded_sp = {
|
||||||
|
.argc = 0,
|
||||||
|
.stack_idx = -1,
|
||||||
|
.user_sp = 0,
|
||||||
|
.user_stack_vaddr = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* alloc a user stack index */
|
||||||
|
int stack_idx = bitmap64_alloc(&pmemspace->thread_stack_idx_bitmap);
|
||||||
|
if (stack_idx == -1) {
|
||||||
|
ERROR("Number of threads created exceeds kernel support.\n");
|
||||||
|
handle_error_stack_loading(pmemspace, stack_idx, NULL, false);
|
||||||
|
return loaded_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory space for user stack */
|
||||||
|
uintptr_t* stack_bottom = (uintptr_t*)kalloc(USER_STACK_SIZE);
|
||||||
|
if (UNLIKELY(stack_bottom == NULL)) {
|
||||||
|
ERROR("No memory to alloc user stack.\n");
|
||||||
|
handle_error_stack_loading(pmemspace, stack_idx, stack_bottom, false);
|
||||||
|
return loaded_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map memory to user stack space in memspace*/
|
||||||
|
if (!xizi_pager.map_pages(pmemspace->pgdir.pd_addr, USER_MEM_TOP - ((stack_idx + 1) * USER_STACK_SIZE), V2P(stack_bottom), USER_STACK_SIZE, false)) {
|
||||||
|
/* this could only fail due to inner page directory's allocation failure */
|
||||||
|
ERROR("User stack map failed\n");
|
||||||
|
handle_error_stack_loading(pmemspace, stack_idx, stack_bottom, false);
|
||||||
|
return loaded_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start loading main params into user stack */
|
||||||
|
/// @warning supports only main style params
|
||||||
|
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;
|
||||||
|
uintptr_t copy_len = 0;
|
||||||
|
for (argc = 0; argv != NULL && argv[argc] != NULL; argc++) {
|
||||||
|
/// @todo handle with large number of parameters (more than 32)
|
||||||
|
|
||||||
|
// copy param to user stack
|
||||||
|
copy_len = strlen(argv[argc]) + 1;
|
||||||
|
user_vspace_sp = (user_vspace_sp - copy_len) & ~3;
|
||||||
|
uintptr_t copied_len = xizi_pager.cross_vspace_data_copy(&pmemspace->pgdir, user_vspace_sp, (uintptr_t)argv[argc], copy_len);
|
||||||
|
if (UNLIKELY(copied_len != copy_len)) {
|
||||||
|
ERROR("Something went wrong when copying params.\n");
|
||||||
|
handle_error_stack_loading(pmemspace, stack_idx, stack_bottom, true);
|
||||||
|
return loaded_sp;
|
||||||
|
}
|
||||||
|
user_stack_init[argc] = user_vspace_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
user_stack_init[argc] = 0;
|
||||||
|
copy_len = (argc + 1) * sizeof(uintptr_t);
|
||||||
|
user_vspace_sp -= copy_len;
|
||||||
|
/* this copy has no reason to fail */
|
||||||
|
uintptr_t copied_len = xizi_pager.cross_vspace_data_copy(&pmemspace->pgdir, user_vspace_sp, (uintptr_t)user_stack_init, copy_len);
|
||||||
|
assert(copied_len == copy_len);
|
||||||
|
|
||||||
|
pmemspace->mem_size += USER_STACK_SIZE;
|
||||||
|
|
||||||
|
loaded_sp.argc = argc;
|
||||||
|
loaded_sp.stack_idx = stack_idx;
|
||||||
|
loaded_sp.user_sp = user_vspace_sp;
|
||||||
|
loaded_sp.user_stack_vaddr = (uintptr_t)stack_bottom;
|
||||||
|
return loaded_sp;
|
||||||
|
}
|
|
@ -30,9 +30,9 @@ Modification:
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
|
|
||||||
struct TaskMicroDescriptor* max_priority_runnable_task(void)
|
struct Thread* max_priority_runnable_task(void)
|
||||||
{
|
{
|
||||||
static struct TaskMicroDescriptor* task = NULL;
|
static struct Thread* task = NULL;
|
||||||
static int priority = 0;
|
static int priority = 0;
|
||||||
|
|
||||||
priority = __builtin_ffs(ready_task_priority) - 1;
|
priority = __builtin_ffs(ready_task_priority) - 1;
|
||||||
|
@ -53,9 +53,9 @@ struct TaskMicroDescriptor* max_priority_runnable_task(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* round_robin_runnable_task(uint32_t priority)
|
struct Thread* round_robin_runnable_task(uint32_t priority)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* task = NULL;
|
struct Thread* task = NULL;
|
||||||
|
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[priority], node)
|
DOUBLE_LIST_FOR_EACH_ENTRY(task, &xizi_task_manager.task_list_head[priority], node)
|
||||||
{
|
{
|
||||||
|
@ -74,7 +74,7 @@ struct TaskMicroDescriptor* round_robin_runnable_task(uint32_t priority)
|
||||||
/* recover task priority */
|
/* recover task priority */
|
||||||
void recover_priority(void)
|
void recover_priority(void)
|
||||||
{
|
{
|
||||||
struct TaskMicroDescriptor* task = NULL;
|
struct Thread* task = NULL;
|
||||||
for (int i = 1; i < TASK_MAX_PRIORITY; i++) {
|
for (int i = 1; i < TASK_MAX_PRIORITY; i++) {
|
||||||
if (i == TASK_DEFAULT_PRIORITY)
|
if (i == TASK_DEFAULT_PRIORITY)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -33,7 +33,7 @@ Modification:
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "kalloc.h"
|
#include "kalloc.h"
|
||||||
#include "log.h"
|
#include "memspace.h"
|
||||||
#include "multicores.h"
|
#include "multicores.h"
|
||||||
#include "scheduler.h"
|
#include "scheduler.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
@ -42,7 +42,7 @@ Modification:
|
||||||
struct CPU global_cpus[NR_CPU];
|
struct CPU global_cpus[NR_CPU];
|
||||||
uint32_t ready_task_priority;
|
uint32_t ready_task_priority;
|
||||||
|
|
||||||
static inline void task_node_leave_list(struct TaskMicroDescriptor* task)
|
static inline void task_node_leave_list(struct Thread* task)
|
||||||
{
|
{
|
||||||
doubleListDel(&task->node);
|
doubleListDel(&task->node);
|
||||||
if (IS_DOUBLE_LIST_EMPTY(&xizi_task_manager.task_list_head[task->priority])) {
|
if (IS_DOUBLE_LIST_EMPTY(&xizi_task_manager.task_list_head[task->priority])) {
|
||||||
|
@ -50,13 +50,13 @@ static inline void task_node_leave_list(struct TaskMicroDescriptor* task)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void task_node_add_to_ready_list_head(struct TaskMicroDescriptor* task)
|
static inline void task_node_add_to_ready_list_head(struct Thread* task)
|
||||||
{
|
{
|
||||||
doubleListAddOnHead(&task->node, &xizi_task_manager.task_list_head[task->priority]);
|
doubleListAddOnHead(&task->node, &xizi_task_manager.task_list_head[task->priority]);
|
||||||
ready_task_priority |= ((uint32_t)1 << task->priority);
|
ready_task_priority |= ((uint32_t)1 << task->priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void task_node_add_to_ready_list_back(struct TaskMicroDescriptor* task)
|
static inline void task_node_add_to_ready_list_back(struct Thread* task)
|
||||||
{
|
{
|
||||||
doubleListAddOnBack(&task->node, &xizi_task_manager.task_list_head[task->priority]);
|
doubleListAddOnBack(&task->node, &xizi_task_manager.task_list_head[task->priority]);
|
||||||
ready_task_priority |= ((uint32_t)1 << task->priority);
|
ready_task_priority |= ((uint32_t)1 << task->priority);
|
||||||
|
@ -71,10 +71,11 @@ static void _task_manager_init()
|
||||||
doubleListNodeInit(&xizi_task_manager.task_blocked_list_head);
|
doubleListNodeInit(&xizi_task_manager.task_blocked_list_head);
|
||||||
doubleListNodeInit(&xizi_task_manager.task_running_list_head);
|
doubleListNodeInit(&xizi_task_manager.task_running_list_head);
|
||||||
// init task (slab) allocator
|
// init task (slab) allocator
|
||||||
slab_init(&xizi_task_manager.task_allocator, sizeof(struct TaskMicroDescriptor));
|
slab_init(&xizi_task_manager.memspace_allocator, sizeof(struct MemSpace));
|
||||||
|
slab_init(&xizi_task_manager.task_allocator, sizeof(struct Thread));
|
||||||
slab_init(&xizi_task_manager.task_buddy_allocator, sizeof(struct KBuddy));
|
slab_init(&xizi_task_manager.task_buddy_allocator, sizeof(struct KBuddy));
|
||||||
|
|
||||||
// pid pool
|
// tid pool
|
||||||
xizi_task_manager.next_pid = 0;
|
xizi_task_manager.next_pid = 0;
|
||||||
|
|
||||||
// init priority bit map
|
// init priority bit map
|
||||||
|
@ -82,22 +83,23 @@ static void _task_manager_init()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief alloc a new task without init
|
/// @brief alloc a new task without init
|
||||||
static struct TaskMicroDescriptor* _alloc_task_cb()
|
static struct Thread* _alloc_task_cb()
|
||||||
{
|
{
|
||||||
// alloc task and add it to used task list
|
// alloc task and add it to used task list
|
||||||
struct TaskMicroDescriptor* task = (struct TaskMicroDescriptor*)slab_alloc(&xizi_task_manager.task_allocator);
|
struct Thread* task = (struct Thread*)slab_alloc(&xizi_task_manager.task_allocator);
|
||||||
if (UNLIKELY(task == NULL)) {
|
if (UNLIKELY(task == NULL)) {
|
||||||
ERROR("Not enough memory\n");
|
ERROR("Not enough memory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// set pid once task is allocated
|
// set tid once task is allocated
|
||||||
memset(task, 0, sizeof(*task));
|
memset(task, 0, sizeof(*task));
|
||||||
task->pid = xizi_task_manager.next_pid++;
|
task->tid = xizi_task_manager.next_pid++;
|
||||||
|
task->thread_context.user_stack_idx = -1;
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _task_retrieve_sys_resources(struct TaskMicroDescriptor* ptask)
|
int _task_retrieve_sys_resources(struct Thread* ptask)
|
||||||
{
|
{
|
||||||
assert(ptask != NULL);
|
assert(ptask != NULL);
|
||||||
|
|
||||||
|
@ -143,7 +145,7 @@ int _task_retrieve_sys_resources(struct TaskMicroDescriptor* ptask)
|
||||||
|
|
||||||
/// @brief this function changes task list without locking, so it must be called inside a lock critical area
|
/// @brief this function changes task list without locking, so it must be called inside a lock critical area
|
||||||
/// @param task
|
/// @param task
|
||||||
static void _dealloc_task_cb(struct TaskMicroDescriptor* task)
|
static void _dealloc_task_cb(struct Thread* task)
|
||||||
{
|
{
|
||||||
if (UNLIKELY(task == NULL)) {
|
if (UNLIKELY(task == NULL)) {
|
||||||
ERROR("deallocating a NULL task\n");
|
ERROR("deallocating a NULL task\n");
|
||||||
|
@ -152,22 +154,38 @@ static void _dealloc_task_cb(struct TaskMicroDescriptor* task)
|
||||||
|
|
||||||
_task_retrieve_sys_resources(task);
|
_task_retrieve_sys_resources(task);
|
||||||
|
|
||||||
// stack is mapped in vspace, so it should be free by pgdir
|
/* free thread's user stack */
|
||||||
if (task->pgdir.pd_addr) {
|
if (task->thread_context.user_stack_idx != -1) {
|
||||||
xizi_pager.free_user_pgdir(&task->pgdir);
|
// stack is mapped in vspace, so it should be freed from pgdir
|
||||||
}
|
assert(task->thread_context.user_stack_idx >= 0 && task->thread_context.user_stack_idx < 64);
|
||||||
if (task->main_thread.stack_addr) {
|
assert(task->memspace != NULL);
|
||||||
kfree((char*)task->main_thread.stack_addr);
|
|
||||||
|
/* the stack must have be set in memspace if bitmap has been set */
|
||||||
|
assert(xizi_pager.unmap_pages(task->memspace->pgdir.pd_addr, task->thread_context.uspace_stack_addr, USER_STACK_SIZE));
|
||||||
|
bitmap64_free(&task->memspace->thread_stack_idx_bitmap, task->thread_context.user_stack_idx);
|
||||||
|
/* thread's user stack space is also allocated for kernel free space */
|
||||||
|
assert(kfree((char*)task->thread_context.ustack_kvaddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove it from used task list
|
/* free thread's kernel stack */
|
||||||
|
if (task->thread_context.kern_stack_addr) {
|
||||||
|
kfree((char*)task->thread_context.kern_stack_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* free memspace if needed to */
|
||||||
|
if (task->memspace != NULL) {
|
||||||
|
doubleListDel(&task->memspace_list_node);
|
||||||
|
/* free memspace if thread is the last one using it */
|
||||||
|
if (IS_DOUBLE_LIST_EMPTY(&task->memspace->thread_list_guard)) {
|
||||||
|
// free memspace
|
||||||
|
free_memspace(task->memspace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove thread from used task list
|
||||||
task_node_leave_list(task);
|
task_node_leave_list(task);
|
||||||
|
|
||||||
// free task back to allocator
|
// free task back to allocator
|
||||||
if (task->massive_ipc_allocator != NULL) {
|
|
||||||
KBuddyDestory(task->massive_ipc_allocator);
|
|
||||||
slab_free(&xizi_task_manager.task_buddy_allocator, (void*)task->massive_ipc_allocator);
|
|
||||||
}
|
|
||||||
slab_free(&xizi_task_manager.task_allocator, (void*)task);
|
slab_free(&xizi_task_manager.task_allocator, (void*)task);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,45 +197,56 @@ __attribute__((optimize("O0"))) void task_prepare_enter()
|
||||||
trap_return();
|
trap_return();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct TaskMicroDescriptor* _new_task_cb()
|
static struct Thread* _new_task_cb(struct MemSpace* pmemspace)
|
||||||
{
|
{
|
||||||
// alloc task space
|
// alloc task space
|
||||||
struct TaskMicroDescriptor* task = _alloc_task_cb();
|
struct Thread* task = _alloc_task_cb();
|
||||||
if (!task) {
|
if (!task) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// init vm
|
|
||||||
task->pgdir.pd_addr = NULL;
|
|
||||||
/* init basic task member */
|
/* init basic task member */
|
||||||
doubleListNodeInit(&task->cli_sess_listhead);
|
doubleListNodeInit(&task->cli_sess_listhead);
|
||||||
doubleListNodeInit(&task->svr_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 */
|
/* init main thread of task */
|
||||||
task->main_thread.task = task;
|
task->thread_context.task = task;
|
||||||
// alloc stack page for task
|
// alloc stack page for task
|
||||||
if ((void*)(task->main_thread.stack_addr = (uintptr_t)kalloc(USER_STACK_SIZE)) == NULL) {
|
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);
|
_dealloc_task_cb(task);
|
||||||
return NULL;
|
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 */
|
/* set context of main thread stack */
|
||||||
/// stack bottom
|
/// stack bottom
|
||||||
memset((void*)task->main_thread.stack_addr, 0x00, USER_STACK_SIZE);
|
memset((void*)task->thread_context.kern_stack_addr, 0x00, USER_STACK_SIZE);
|
||||||
char* sp = (char*)task->main_thread.stack_addr + USER_STACK_SIZE - 4;
|
char* sp = (char*)task->thread_context.kern_stack_addr + USER_STACK_SIZE - 4;
|
||||||
|
|
||||||
/// 1. trap frame into stack, for process to nomally return by trap_return
|
/// 1. trap frame into stack, for process to nomally return by trap_return
|
||||||
sp -= sizeof(*task->main_thread.trapframe);
|
sp -= sizeof(*task->thread_context.trapframe);
|
||||||
task->main_thread.trapframe = (struct trapframe*)sp;
|
task->thread_context.trapframe = (struct trapframe*)sp;
|
||||||
|
|
||||||
/// 2. context into stack
|
/// 2. context into stack
|
||||||
sp -= sizeof(*task->main_thread.context);
|
sp -= sizeof(*task->thread_context.context);
|
||||||
task->main_thread.context = (struct context*)sp;
|
task->thread_context.context = (struct context*)sp;
|
||||||
arch_init_context(task->main_thread.context);
|
arch_init_context(task->thread_context.context);
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _task_set_default_schedule_attr(struct TaskMicroDescriptor* task)
|
static void _task_set_default_schedule_attr(struct Thread* task)
|
||||||
{
|
{
|
||||||
task->remain_tick = TASK_CLOCK_TICK;
|
task->remain_tick = TASK_CLOCK_TICK;
|
||||||
task->maxium_tick = TASK_CLOCK_TICK * 10;
|
task->maxium_tick = TASK_CLOCK_TICK * 10;
|
||||||
|
@ -226,7 +255,7 @@ static void _task_set_default_schedule_attr(struct TaskMicroDescriptor* task)
|
||||||
task_node_add_to_ready_list_head(task);
|
task_node_add_to_ready_list_head(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void task_state_set_running(struct TaskMicroDescriptor* task)
|
static void task_state_set_running(struct Thread* task)
|
||||||
{
|
{
|
||||||
assert(task != NULL && task->state == READY);
|
assert(task != NULL && task->state == READY);
|
||||||
task->state = RUNNING;
|
task->state = RUNNING;
|
||||||
|
@ -234,12 +263,12 @@ static void task_state_set_running(struct TaskMicroDescriptor* task)
|
||||||
doubleListAddOnHead(&task->node, &xizi_task_manager.task_running_list_head);
|
doubleListAddOnHead(&task->node, &xizi_task_manager.task_running_list_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* next_task_emergency = NULL;
|
struct Thread* next_task_emergency = NULL;
|
||||||
extern void context_switch(struct context**, struct context*);
|
extern void context_switch(struct context**, struct context*);
|
||||||
static void _scheduler(struct SchedulerRightGroup right_group)
|
static void _scheduler(struct SchedulerRightGroup right_group)
|
||||||
{
|
{
|
||||||
struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag);
|
struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag);
|
||||||
struct TaskMicroDescriptor* next_task;
|
struct Thread* next_task;
|
||||||
struct CPU* cpu = cur_cpu();
|
struct CPU* cpu = cur_cpu();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -269,13 +298,14 @@ static void _scheduler(struct SchedulerRightGroup right_group)
|
||||||
/* run the chosen task */
|
/* run the chosen task */
|
||||||
task_state_set_running(next_task);
|
task_state_set_running(next_task);
|
||||||
cpu->task = next_task;
|
cpu->task = next_task;
|
||||||
p_mmu_driver->LoadPgdir((uintptr_t)V2P(next_task->pgdir.pd_addr));
|
assert(next_task->memspace->pgdir.pd_addr != NULL);
|
||||||
context_switch(&cpu->scheduler, next_task->main_thread.context);
|
p_mmu_driver->LoadPgdir((uintptr_t)V2P(next_task->memspace->pgdir.pd_addr));
|
||||||
|
context_switch(&cpu->scheduler, next_task->thread_context.context);
|
||||||
assert(next_task->state != RUNNING);
|
assert(next_task->state != RUNNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _task_yield_noschedule(struct TaskMicroDescriptor* task, bool blocking)
|
static void _task_yield_noschedule(struct Thread* task, bool blocking)
|
||||||
{
|
{
|
||||||
assert(task != NULL);
|
assert(task != NULL);
|
||||||
/// @warning only support current task yield now
|
/// @warning only support current task yield now
|
||||||
|
@ -291,7 +321,7 @@ static void _task_yield_noschedule(struct TaskMicroDescriptor* task, bool blocki
|
||||||
task_node_add_to_ready_list_back(task);
|
task_node_add_to_ready_list_back(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _task_block(struct TaskMicroDescriptor* task)
|
static void _task_block(struct Thread* task)
|
||||||
{
|
{
|
||||||
assert(task != NULL);
|
assert(task != NULL);
|
||||||
assert(task->state != RUNNING);
|
assert(task->state != RUNNING);
|
||||||
|
@ -300,7 +330,7 @@ static void _task_block(struct TaskMicroDescriptor* task)
|
||||||
doubleListAddOnHead(&task->node, &xizi_task_manager.task_blocked_list_head);
|
doubleListAddOnHead(&task->node, &xizi_task_manager.task_blocked_list_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _task_unblock(struct TaskMicroDescriptor* task)
|
static void _task_unblock(struct Thread* task)
|
||||||
{
|
{
|
||||||
assert(task != NULL);
|
assert(task != NULL);
|
||||||
assert(task->state == BLOCKED);
|
assert(task->state == BLOCKED);
|
||||||
|
@ -318,7 +348,7 @@ static void _set_cur_task_priority(int priority)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* current_task = cur_cpu()->task;
|
struct Thread* current_task = cur_cpu()->task;
|
||||||
assert(current_task != NULL && current_task->state == RUNNING);
|
assert(current_task != NULL && current_task->state == RUNNING);
|
||||||
|
|
||||||
task_node_leave_list(current_task);
|
task_node_leave_list(current_task);
|
||||||
|
|
|
@ -58,14 +58,14 @@ __attribute__((optimize("O0"))) void dabort_handler(struct trapframe* r)
|
||||||
panic("data abort exception\n");
|
panic("data abort exception\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
ERROR("dabort in user space: %s\n", cur_task->name);
|
ERROR("dabort in user space: %s\n", cur_task->name);
|
||||||
dabort_reason(r);
|
dabort_reason(r);
|
||||||
|
|
||||||
xizi_enter_kernel();
|
xizi_enter_kernel();
|
||||||
sys_exit(cur_task);
|
sys_exit(cur_task);
|
||||||
assert(cur_cpu()->task == NULL);
|
assert(cur_cpu()->task == NULL);
|
||||||
context_switch(&cur_task->main_thread.context, cur_cpu()->scheduler);
|
context_switch(&cur_task->thread_context.context, cur_cpu()->scheduler);
|
||||||
panic("dabort end should never be reashed.\n");
|
panic("dabort end should never be reashed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,13 +78,13 @@ __attribute__((optimize("O0"))) void iabort_handler(struct trapframe* r)
|
||||||
panic("kernel prefetch abort exception\n");
|
panic("kernel prefetch abort exception\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
ERROR("iabort in user space: %s\n", cur_task->name);
|
ERROR("iabort in user space: %s\n", cur_task->name);
|
||||||
iabort_reason(r);
|
iabort_reason(r);
|
||||||
|
|
||||||
xizi_enter_kernel();
|
xizi_enter_kernel();
|
||||||
sys_exit(cur_task);
|
sys_exit(cur_task);
|
||||||
assert(cur_cpu()->task == NULL);
|
assert(cur_cpu()->task == NULL);
|
||||||
context_switch(&cur_task->main_thread.context, cur_cpu()->scheduler);
|
context_switch(&cur_task->thread_context.context, cur_cpu()->scheduler);
|
||||||
panic("iabort end should never be reashed.\n");
|
panic("iabort end should never be reashed.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ int xizi_clock_handler(int irq, void* tf, void* arg)
|
||||||
if (p_clock_driver->is_timer_expired()) {
|
if (p_clock_driver->is_timer_expired()) {
|
||||||
p_clock_driver->clear_clock_intr();
|
p_clock_driver->clear_clock_intr();
|
||||||
global_tick++;
|
global_tick++;
|
||||||
struct TaskMicroDescriptor* current_task = cur_cpu()->task;
|
struct Thread* current_task = cur_cpu()->task;
|
||||||
if (current_task) {
|
if (current_task) {
|
||||||
current_task->remain_tick--;
|
current_task->remain_tick--;
|
||||||
current_task->maxium_tick--;
|
current_task->maxium_tick--;
|
||||||
|
|
|
@ -65,9 +65,9 @@ void intr_irq_dispatch(struct trapframe* tf)
|
||||||
goto intr_leave_interrupt;
|
goto intr_leave_interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TaskMicroDescriptor* current_task = cur_cpu()->task;
|
struct Thread* current_task = cur_cpu()->task;
|
||||||
assert(current_task != NULL);
|
assert(current_task != NULL);
|
||||||
current_task->main_thread.trapframe = tf;
|
current_task->thread_context.trapframe = tf;
|
||||||
|
|
||||||
int cpu = cur_cpuid();
|
int cpu = cur_cpuid();
|
||||||
assert(cpu >= 0 && cpu < NR_CPU);
|
assert(cpu >= 0 && cpu < NR_CPU);
|
||||||
|
@ -86,7 +86,7 @@ void intr_irq_dispatch(struct trapframe* tf)
|
||||||
|
|
||||||
if (cur_cpu()->task == NULL || current_task->state != RUNNING) {
|
if (cur_cpu()->task == NULL || current_task->state != RUNNING) {
|
||||||
cur_cpu()->task = NULL;
|
cur_cpu()->task = NULL;
|
||||||
context_switch(¤t_task->main_thread.context, cur_cpu()->scheduler);
|
context_switch(¤t_task->thread_context.context, cur_cpu()->scheduler);
|
||||||
}
|
}
|
||||||
assert(current_task == cur_cpu()->task);
|
assert(current_task == cur_cpu()->task);
|
||||||
|
|
||||||
|
|
|
@ -52,24 +52,21 @@ void software_irq_dispatch(struct trapframe* tf)
|
||||||
assert(p_intr_driver != NULL);
|
assert(p_intr_driver != NULL);
|
||||||
|
|
||||||
// get current task
|
// get current task
|
||||||
struct TaskMicroDescriptor* cur_task = cur_cpu()->task;
|
struct Thread* cur_task = cur_cpu()->task;
|
||||||
/// @todo: Handle dead task
|
/// @todo: Handle dead task
|
||||||
|
|
||||||
int syscall_num = -1;
|
int syscall_num = -1;
|
||||||
if (cur_task && cur_task->state != DEAD) {
|
if (cur_task && cur_task->state != DEAD) {
|
||||||
cur_task->main_thread.trapframe = tf;
|
cur_task->thread_context.trapframe = tf;
|
||||||
// call syscall
|
// call syscall
|
||||||
|
|
||||||
int ret = arch_syscall(cur_task->main_thread.trapframe, &syscall_num);
|
int ret = arch_syscall(cur_task->thread_context.trapframe, &syscall_num);
|
||||||
|
arch_set_return(tf, ret);
|
||||||
if (syscall_num != SYSCALL_EXEC) {
|
|
||||||
arch_set_return(tf, ret);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cur_cpu()->task == NULL && cur_task != NULL) || cur_task->state != RUNNING) {
|
if ((cur_cpu()->task == NULL && cur_task != NULL) || cur_task->state != RUNNING) {
|
||||||
cur_cpu()->task = NULL;
|
cur_cpu()->task = NULL;
|
||||||
context_switch(&cur_task->main_thread.context, cur_cpu()->scheduler);
|
context_switch(&cur_task->thread_context.context, cur_cpu()->scheduler);
|
||||||
}
|
}
|
||||||
if (syscall_num == SYSCALL_EXIT) {
|
if (syscall_num == SYSCALL_EXIT) {
|
||||||
panic("Exit reaches");
|
panic("Exit reaches");
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
/*
|
|
||||||
* 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: test_cache.h
|
|
||||||
* @brief: test the function of cache
|
|
||||||
* @version: 3.0
|
|
||||||
* @author: AIIT XUOS Lab
|
|
||||||
* @date: 2023/4/27
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*************************************************
|
|
||||||
File name: l1_cache.h
|
|
||||||
Description: test the function of cache
|
|
||||||
Others:
|
|
||||||
History:
|
|
||||||
1. Date: 2023-04-27
|
|
||||||
Author: AIIT XUOS Lab
|
|
||||||
Modification:
|
|
||||||
1、test the function of cache
|
|
||||||
*************************************************/
|
|
||||||
|
|
||||||
#include "irq_numbers.h"
|
|
||||||
#include "trap_common.h"
|
|
||||||
|
|
||||||
#include "cache_common_ope.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "kalloc.h"
|
|
||||||
|
|
||||||
int system_tick = 0;
|
|
||||||
extern struct ICacheDone icache_done;
|
|
||||||
extern struct DCacheDone dcache_done;
|
|
||||||
|
|
||||||
void test_cache(void)
|
|
||||||
{
|
|
||||||
int* block = (int*)kalloc(200000 * sizeof(int));
|
|
||||||
|
|
||||||
int size = 100000;
|
|
||||||
xizi_trap_driver.cpu_irq_disable();
|
|
||||||
icache_done.enable();
|
|
||||||
dcache_done.enable();
|
|
||||||
xizi_trap_driver.cpu_irq_enable();
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
LOG("start.\n");
|
|
||||||
int temp = 0;
|
|
||||||
|
|
||||||
int tick0 = system_tick;
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
block[i] = 0;
|
|
||||||
temp += block[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
int tick1 = system_tick;
|
|
||||||
LOG("tick1:%d.\n", tick1 - tick0);
|
|
||||||
|
|
||||||
temp = 0;
|
|
||||||
tick1 = system_tick;
|
|
||||||
for (int i = 0; i < size; ++i)
|
|
||||||
temp += block[i];
|
|
||||||
int tick2 = system_tick;
|
|
||||||
LOG("tick2:%d.\n", tick2 - tick1);
|
|
||||||
|
|
||||||
xizi_trap_driver.cpu_irq_disable();
|
|
||||||
dcache_done.flushall();
|
|
||||||
xizi_trap_driver.cpu_irq_enable();
|
|
||||||
LOG("ok.\n");
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue