diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h index 2115c3633..01c5623bf 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/arch/arm/armv7-a/cortex-a9/core.h @@ -74,7 +74,7 @@ Modification: #include "cortex_a9.h" -#define NR_CPU 1 +#define NR_CPU 4 __attribute__((always_inline, optimize("O0"))) static inline uint32_t user_mode() { diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c b/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c index d2d0a6f14..bd8a76cea 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/hardkernel_init.c @@ -129,7 +129,7 @@ static bool xizi_gpt_init() return false; } // register clock handler to intr - struct XiziTrapDriver* p_intr_driver = (struct XiziTrapDriver*)AchieveResource(&intr_driver_tag); + struct XiziTrapDriver* p_intr_driver = GetSysObject(struct XiziTrapDriver, &intr_driver_tag); p_intr_driver->bind_irq_handler(p_clock_driver->get_clock_int(), xizi_clock_handler); p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), 0, 0); return true; diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h index 0a31e0241..1438f964c 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/imx6q-sabrelite/memlayout.h @@ -73,4 +73,11 @@ Modification: #define KERN_MEM_BASE (0x90000000) // First kernel virtual address #define KERN_OFFSET (KERN_MEM_BASE - PHY_MEM_BASE) +/* virtual and physical addr translate */ +#define V2P(a) ((uint32_t)((uint32_t)(a)-KERN_OFFSET)) +#define P2V(a) ((void*)((void*)(a) + KERN_OFFSET)) + +#define V2P_WO(x) ((x)-KERN_OFFSET) // same as V2P, but without casts +#define P2V_WO(x) ((x) + KERN_OFFSET) // same as V2P, but without casts + // clang-format on diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/include/mmu.h b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/include/mmu.h index 7f5053d19..d5136d838 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/include/mmu.h +++ b/Ubiquitous/XiZi_AIoT/hardkernel/mmu/arm/armv7-a/cortex-a9/include/mmu.h @@ -92,13 +92,6 @@ When the process switches, the flush TLB is no longer required anymore. #define CONTEXTIDR_R(val) __asm__ volatile("mrc p15, 0, %0, c13, c0, 1" : "=r"(val)) #define CONTEXTIDR_W(val) __asm__ volatile("mcr p15, 0, %0, c13, c0, 1" ::"r"(val)) -/* virtual and physical addr translate */ -#define V2P(a) ((uint32_t)((uint32_t)(a)-KERN_OFFSET)) -#define P2V(a) ((void*)((void*)(a) + KERN_OFFSET)) - -#define V2P_WO(x) ((x)-KERN_OFFSET) // same as V2P, but without casts -#define P2V_WO(x) ((x) + KERN_OFFSET) // same as V2P, but without casts - #ifndef __ASSEMBLER__ #include __attribute__((always_inline)) static inline uint32_t v2p(void* a) { return ((uint32_t)(a)) - KERN_MEM_BASE; } diff --git a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c index f74596559..ebbb85288 100644 --- a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c +++ b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.c @@ -45,11 +45,8 @@ static void tracer_init_node(TracerNode* node, char* name, tracemeta_ac_type typ p_name[TRACER_NODE_NAME_LEN - 1] = '\0'; node->name = p_name; } - if (node->type == TRACER_OWNER) { - doubleListNodeInit(&node->children_guard); - } else { - node->p_resource = p_resource; - } + doubleListNodeInit(&node->children_guard); + node->p_resource = p_resource; doubleListNodeInit(&node->list_node); } @@ -149,13 +146,10 @@ bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta { assert(owner != NULL); if (owner->meta == NULL) { - ERROR("Tracer: Empty owner\n"); - return false; - } - assert(owner->meta->type == TRACER_OWNER); - if (tracer_find_node_onestep(owner->meta, name) != NULL) { + ERROR("Tracer: Empty owner, node name: %s\n", name); return false; } + // assert(owner->meta->type == TRACER_OWNER); TracerNode* new_node = (TracerNode*)slab_alloc(&sys_tracer.node_allocator); if (new_node == NULL) { @@ -204,27 +198,37 @@ bool DeleteResource(TraceTag* target, TraceTag* owner) return true; } -void debug_list_tracetree_inner(TracerNode* cur_node) +#define debug_print_blanks(n) \ + for (int __i = 0; __i < n; __i++) { \ + DEBUG_PRINTF(" "); \ + } + +void debug_list_tracetree_inner(TracerNode* cur_node, int nr_blanks) { - DEBUG("[%s] ", cur_node->name); + debug_print_blanks(nr_blanks); + if (cur_node->name == NULL) { + DEBUG_PRINTF("[ANON %d] ", cur_node->type); + } else { + DEBUG_PRINTF("[%s %d] ", cur_node->name, cur_node->type); + } TracerNode* tmp = NULL; DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node) { if (tmp->name != NULL) { - DEBUG("%s ", tmp->name); + DEBUG_PRINTF("%s ", tmp->name); } else { - DEBUG("ANON "); + DEBUG_PRINTF("ANON "); } } - DEBUG("\n"); + DEBUG_PRINTF("\n"); DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node) { - debug_list_tracetree_inner(tmp); + debug_list_tracetree_inner(tmp, nr_blanks + 1); } } void debug_list_tracetree() { TracerNode* ref_root = RequireRootTag()->meta; - debug_list_tracetree_inner(ref_root); + debug_list_tracetree_inner(ref_root, 0); } \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.h b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.h index 06f819c6a..a2a9f3e0d 100644 --- a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.h +++ b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer.h @@ -30,35 +30,12 @@ Modification: #include #include -#include "list.h" +#include "actracer_tag.h" #include "object_allocator.h" #define TRACER_NODE_NAME_LEN 32 -typedef enum { - TRACER_INVALID = 0, - TRACER_OWNER, - TRACER_HARDKERNEL_AC_RESOURCE, - TRACER_TASK_DESCRIPTOR_AC_RESOURCE, - TRACER_SERVER_IDENTITY_AC_RESOURCE, - TRACER_MEM_FROM_BUDDY_AC_RESOURCE, -} tracemeta_ac_type; - -typedef struct TracerNode { - tracemeta_ac_type type; - char* name; - union { - struct double_list_node children_guard; - void* p_resource; - }; - struct TracerNode* parent; - struct double_list_node list_node; -} TracerNode; - -/// @brief tag for other module to reference trace meta -typedef struct TraceTag { - TracerNode* meta; -} TraceTag; +#define GetSysObject(type, target_tag) (type*)AchieveResource(target_tag) struct SysTracer { TracerNode root_node; @@ -72,4 +49,6 @@ TraceTag* const RequireRootTag(); bool AchieveResourceTag(struct TraceTag* target, struct TraceTag* owner, char* name); void* AchieveResource(struct TraceTag* tag); bool CreateResourceTag(struct TraceTag* new_tag, struct TraceTag* owner, char* name, tracemeta_ac_type type, void* p_resource); -bool DeleteResource(struct TraceTag* target, struct TraceTag* owner); \ No newline at end of file +bool DeleteResource(struct TraceTag* target, struct TraceTag* owner); + +void debug_list_tracetree(); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_tag.h b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_tag.h new file mode 100644 index 000000000..cdfea18a9 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/kernel_actracer/actracer_tag.h @@ -0,0 +1,26 @@ +#pragma once +#include "list.h" + +typedef enum { + TRACER_INVALID = 0, + TRACER_OWNER, + TRACER_HARDKERNEL_AC_RESOURCE, + TRACER_TASK_DESCRIPTOR_AC_RESOURCE, + TRACER_SERVER_IDENTITY_AC_RESOURCE, + TRACER_MEM_FROM_BUDDY_AC_RESOURCE, + TRACER_SYSOBJECT, +} tracemeta_ac_type; + +typedef struct TracerNode { + tracemeta_ac_type type; + char* name; + void* p_resource; + struct TracerNode* parent; + struct double_list_node list_node; + struct double_list_node children_guard; +} TracerNode; + +/// @brief tag for other module to reference trace meta +typedef struct TraceTag { + TracerNode* meta; +} TraceTag; \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/Makefile b/Ubiquitous/XiZi_AIoT/services/Makefile index b3a5f2c41..7f6bc5fb9 100644 --- a/Ubiquitous/XiZi_AIoT/services/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/Makefile @@ -1,5 +1,5 @@ -SRC_DIR := fs shell lib boards drivers semaphore drivers tools net app +SRC_DIR := fs shell lib boards drivers semaphore tools app include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/app/Makefile b/Ubiquitous/XiZi_AIoT/services/app/Makefile index fb0d3838d..da69f6587 100644 --- a/Ubiquitous/XiZi_AIoT/services/app/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/app/Makefile @@ -43,7 +43,7 @@ INC_DIR = -I$(KERNEL_ROOT)/services/shell/letter-shell \ -I$(KERNEL_ROOT)/services/app ifeq ($(BOARD), imx6q-sabrelite) -all: test_fault simple_client simple_server shell fs_server semaphore_server test_sleep test_semaphore test_ipc_null test_thread test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server test_net lwip readme.txt | bin +all: test_fault simple_client simple_server shell fs_server semaphore_server test_sleep test_semaphore test_ipc_null test_thread test_irq_hdlr test_irq_block test_irq_send eth_driver epit_server readme.txt | bin else all: test_fault simple_client simple_server shell fs_server semaphore_server test_sleep test_ipc_null test_thread test_semaphore test_net lwip readme.txt eth_hal | bin endif diff --git a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c index 403d16e61..d9ffcdf22 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c +++ b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.c @@ -102,6 +102,11 @@ int show_cpu() return syscall(SYSCALL_SYS_STATE, SYS_STATE_SHOW_CPU_INFO, 0, 0, 0); } +int show_actree() +{ + return syscall(SYSCALL_SYS_STATE, SYS_STATE_SHOW_ACTREE, 0, 0, 0); +} + uintptr_t get_second() { sys_state_info info; diff --git a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h index de683f9cd..ca6e495a7 100644 --- a/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h +++ b/Ubiquitous/XiZi_AIoT/services/lib/usyscall/usyscall.h @@ -47,6 +47,7 @@ typedef enum { SYS_STATE_SHOW_CPU_INFO, SYS_STATE_GET_CURRENT_TICK, SYS_STATE_GET_CURRENT_SECOND, + SYS_STATE_SHOW_ACTREE, } sys_state_option; typedef enum { @@ -99,6 +100,7 @@ int set_priority(sys_state_info* info); int show_task(); int show_mem(); int show_cpu(); +int show_actree(); uintptr_t get_second(); uintptr_t get_tick(); diff --git a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c index 34b99616e..dc34c4b73 100644 --- a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c +++ b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell.c @@ -1797,6 +1797,11 @@ void shellShowCpusInfo() show_cpu(); } +void shellShowActree() +{ + show_actree(); +} + #if SHELL_EXEC_UNDEF_FUNC == 1 /** * @brief shell执行未定义函数 diff --git a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c index 762abed40..848555729 100644 --- a/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c +++ b/Ubiquitous/XiZi_AIoT/services/shell/letter-shell/shell_cmd_list.c @@ -40,6 +40,7 @@ extern void shellKill(int pid); extern void shellShowTasks(); extern void shellShowMemInfo(); extern void shellShowCpusInfo(); +extern void shellShowActree(); #if SHELL_EXEC_UNDEF_FUNC == 1 extern int shellExecute(int argc, char* argv[]); @@ -118,6 +119,8 @@ const ShellCommand shellCommandList[] = { showMemInfo, shellShowMemInfo, display memory info), SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, showCpusInfo, shellShowCpusInfo, display cpus info), + SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN, + showActree, shellShowActree, display actracer tree), #if SHELL_EXEC_UNDEF_FUNC == 1 SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_DISABLE_RETURN, diff --git a/Ubiquitous/XiZi_AIoT/softkernel/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/Makefile index 1464fe7b9..ba0bc8da0 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/Makefile +++ b/Ubiquitous/XiZi_AIoT/softkernel/Makefile @@ -1,4 +1,4 @@ -SRC_DIR := init memory trap task syscall +SRC_DIR := init memory trap task syscall tools SRC_FILES := main.c load_apps.S diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h b/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h index 4b73e7cd4..65f796af6 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/buddy.h @@ -31,7 +31,6 @@ Modification: #include "list.h" #include "memlayout.h" -#include "spinlock.h" #include #include @@ -70,7 +69,6 @@ struct KFreeList { struct KBuddy { uintptr_t n_pages; uintptr_t use_lock; - struct spinlock lock; struct KFreeList free_list[MAX_BUDDY_ORDER]; struct KPage* first_page; uintptr_t mem_start; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/kalloc.h b/Ubiquitous/XiZi_AIoT/softkernel/include/kalloc.h index 66ec4cddd..cdec72f3b 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/kalloc.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/kalloc.h @@ -29,13 +29,22 @@ Modification: *************************************************/ #pragma once -#include "pagetable.h" +#include "actracer.h" +#include "rbtree.h" + +struct MemUsage { + TraceTag tag; + RbtNode* mem_block_root; +}; bool module_phymem_init(); char* kalloc(size_t size); bool kfree(char* vaddr); bool raw_kfree(char* paddr); +void* kalloc_by_ownership(TraceTag owner, uintptr_t size); +bool kfree_by_ownership(TraceTag owner, void* vaddr); + char* raw_alloc(size_t size); bool raw_free(char* paddr); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/memspace.h b/Ubiquitous/XiZi_AIoT/softkernel/include/memspace.h index 44cc9575c..c71b258ab 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/memspace.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/memspace.h @@ -32,6 +32,7 @@ Modification: #include "actracer.h" #include "bitmap64.h" #include "buddy.h" +#include "kalloc.h" #include "list.h" struct TopLevelPageDirectory { @@ -48,6 +49,9 @@ struct ThreadStackPointer { struct MemSpace { /* trace node */ TraceTag tag; + /* mem usage info */ + struct MemUsage mem_usage; + /* task memory resources */ struct TopLevelPageDirectory pgdir; // [phy] vm pgtbl base address uintptr_t heap_base; // mem size of proc used(allocated by kernel) @@ -63,7 +67,7 @@ struct MemSpace { struct Thread* thread_to_notify; }; -struct MemSpace* alloc_memspace(); +struct MemSpace* alloc_memspace(char* name); 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); \ No newline at end of file +struct ThreadStackPointer load_user_stack(struct MemSpace* pmemspace, char** argv); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/object_allocator.h b/Ubiquitous/XiZi_AIoT/softkernel/include/object_allocator.h index a5865422a..997ec6c3e 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/object_allocator.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/object_allocator.h @@ -29,10 +29,12 @@ Modification: *************************************************/ #pragma once +#include "actracer_tag.h" #include #include struct slab_state { + TraceTag owner_tag; struct slab_state *prev, *next; uint64_t bitmap; uintptr_t refcount; @@ -40,6 +42,7 @@ struct slab_state { }; struct slab_allocator { + size_t element_size; size_t nr_elements; size_t slabsize; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/rbtree.h b/Ubiquitous/XiZi_AIoT/softkernel/include/rbtree.h new file mode 100644 index 000000000..251bfb71f --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/rbtree.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "actracer.h" + +// CLRS +// Insertion and Deletion in a Red Black Tree +enum rbt_type { + RED, + BLACK +}; + +typedef struct RbtNode { + uintptr_t key; + void* data; + struct RbtNode* left; + struct RbtNode* right; + struct RbtNode* parent; + enum rbt_type color; +} RbtNode; + +struct RbtNode* rbt_insert(struct RbtNode* T, uintptr_t key, void* data); +struct RbtNode* rbt_delete(struct RbtNode* T, struct RbtNode* z); +struct RbtNode* rbt_search(struct RbtNode* root, int x); + +void preorder(struct RbtNode* root); +void levelorder(struct RbtNode* root); + +void module_rbt_factory_init(TraceTag* _softkernel_tag); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/schedule_algo.h b/Ubiquitous/XiZi_AIoT/softkernel/include/schedule_algo.h new file mode 100644 index 000000000..933731a5b --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/schedule_algo.h @@ -0,0 +1,36 @@ +/* + * 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 scheduler.h + * @brief scheduler algorithm declaration + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2023.08.25 + */ + +/************************************************* +File name: scheduler.h +Description: scheduler algorithm declaration +Others: +History: +1. Date: 2023-08-28 +Author: AIIT XUOS Lab +Modification: +1. first version +*************************************************/ +#pragma once + +#include "task.h" + +struct Thread* max_priority_runnable_task(void); +struct Thread* round_robin_runnable_task(uint32_t priority); +void recover_priority(void); \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/scheduler.h b/Ubiquitous/XiZi_AIoT/softkernel/include/scheduler.h index 933731a5b..fbb3d03a9 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/scheduler.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/scheduler.h @@ -1,36 +1,21 @@ -/* - * 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 scheduler.h - * @brief scheduler algorithm declaration - * @version 3.0 - * @author AIIT XUOS Lab - * @date 2023.08.25 - */ -/************************************************* -File name: scheduler.h -Description: scheduler algorithm declaration -Others: -History: -1. Date: 2023-08-28 -Author: AIIT XUOS Lab -Modification: -1. first version -*************************************************/ #pragma once +#include "actracer.h" +#include "ksemaphore.h" -#include "task.h" +#define TASK_MAX_PRIORITY 32 -struct Thread* max_priority_runnable_task(void); -struct Thread* round_robin_runnable_task(uint32_t priority); -void recover_priority(void); \ No newline at end of file +struct ScheduleNode { + TraceTag task_ref; + struct double_list_node list_node; +}; + +struct Scheduler { + TraceTag tag; + + 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_blocked_list_head; + struct double_list_node task_sleep_list_head; + struct XiziSemaphorePool semaphore_pool; +}; \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h b/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h index f2c0265d4..7d5da2bce 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h +++ b/Ubiquitous/XiZi_AIoT/softkernel/include/syscall.h @@ -67,6 +67,7 @@ typedef enum { SYS_STATE_SHOW_CPU_INFO, SYS_STATE_GET_CURRENT_TICK, SYS_STATE_GET_CURRENT_SECOND, + SYS_STATE_SHOW_ACTREE, } sys_state_option; typedef enum { diff --git a/Ubiquitous/XiZi_AIoT/softkernel/init/softkernel_init.c b/Ubiquitous/XiZi_AIoT/softkernel/init/softkernel_init.c index 53e3d4291..4b371857f 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/init/softkernel_init.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/init/softkernel_init.c @@ -31,10 +31,13 @@ Modification: #include "assert.h" #include "log.h" +#include "rbtree.h" #include "task.h" -bool softkernel_init(struct TraceTag* _hardkernel_tag, struct TraceTag* _softkernel_tag) +bool softkernel_init(TraceTag* _hardkernel_tag, struct TraceTag* _softkernel_tag) { + module_rbt_factory_init(_softkernel_tag); + struct TraceTag server_identifier_owner; CreateResourceTag(&server_identifier_owner, _softkernel_tag, "server-identifier", TRACER_OWNER, NULL); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/main.c b/Ubiquitous/XiZi_AIoT/softkernel/main.c index d19f63d67..2528623e1 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/main.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/main.c @@ -59,6 +59,7 @@ int main(void) if (cpu_id == 0) { /* init memory management first */ + module_phymem_init(); // init buddy management system /* init tracer system */ sys_tracer_init(); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c index 97817851a..295889175 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/buddy.c @@ -31,6 +31,7 @@ Modification: #include "buddy.h" #include "kalloc.h" #include "log.h" +#include "pagetable.h" static void _buddy_split_page(struct KPage* page, uintptr_t low_order, uintptr_t high_order, struct KFreeList* list) { @@ -161,7 +162,8 @@ bool KBuddyInit(struct KBuddy* pbuddy, uintptr_t mem_start, uintptr_t mem_end) // total number of free pages pbuddy->n_pages = (pbuddy->mem_end - (uintptr_t)pbuddy->mem_start) >> LEVEL4_PTE_SHIFT; - memset(pbuddy->pages, 0, pbuddy->n_pages); + memset(pbuddy->pages, 0, pbuddy->n_pages * sizeof(struct KPage)); + // memset(pbuddy->pages, 0, pbuddy->n_pages); // init each free page list from 2^0 to 2^8 for (; i < MAX_BUDDY_ORDER; i++) { diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c index 4bed55c1d..7233430fb 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/kalloc.c @@ -30,6 +30,9 @@ Modification: #include "kalloc.h" #include "assert.h" +#include "memlayout.h" +#include "pagetable.h" + #include "actracer.h" #include "buddy.h" @@ -64,11 +67,35 @@ char* kalloc(uintptr_t size) return mem_alloc; } +void* kalloc_by_ownership(TraceTag owner, uintptr_t size) +{ + void* new_mem = kalloc(size); + if (!new_mem) { + return NULL; + } + + struct MemUsage* usage = GetSysObject(struct MemUsage, &owner); + usage->mem_block_root = rbt_insert(usage->mem_block_root, (uintptr_t)new_mem, NULL); + // DEBUG("%p %p %p %p\n", usage, usage->mem_block_root, usage->tag, new_mem); + return new_mem; +} + bool kfree(char* vaddr) { return KBuddyFree(&kern_virtmem_buddy, V2P_WO(vaddr)); } +bool kfree_by_ownership(TraceTag owner, void* vaddr) +{ + struct MemUsage* usage = GetSysObject(struct MemUsage, &owner); + // DEBUG("%p %p %p %p\n", usage, usage->mem_block_root, usage->tag, vaddr); + RbtNode* node = rbt_search(usage->mem_block_root, (uintptr_t)vaddr); + assert(NULL != node); + usage->mem_block_root = rbt_delete(usage->mem_block_root, node); + + return kfree(vaddr); +} + bool raw_kfree(char* paddr) { return KBuddyFree(&kern_virtmem_buddy, paddr); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/object_allocator.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/object_allocator.c index b79e52ac6..f26094144 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/object_allocator.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/object_allocator.c @@ -32,6 +32,7 @@ Modification: #include "assert.h" #include "kalloc.h" #include "object_allocator.h" +#include "pagetable.h" #define BITMAP_BITS_EMPTY_FULL ((uint64_t)0) #define BITMAP_FIRST_BIT ((uint64_t)1) diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c index 53404786f..3c24e73f4 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/pagetable.c @@ -160,7 +160,8 @@ static uintptr_t _resize_user_pgdir(struct MemSpace* pmemspace, uintptr_t old_si uintptr_t cur_size = ALIGNUP(old_size, PAGE_SIZE); uintptr_t size_needed = ALIGNUP(new_size, PAGE_SIZE) - cur_size; - char* new_page = kalloc(size_needed); + // char* new_page = kalloc(size_needed); + char* new_page = kalloc_by_ownership(pmemspace->mem_usage.tag, size_needed); if (new_page == NULL) { ERROR("No memory\n"); return cur_size; @@ -169,7 +170,6 @@ static uintptr_t _resize_user_pgdir(struct MemSpace* pmemspace, uintptr_t old_si if (!xizi_pager.map_pages(pmemspace, cur_size, V2P(new_page), size_needed, false)) { return cur_size; } - CreateResourceTag(NULL, &pmemspace->tag, NULL, TRACER_MEM_FROM_BUDDY_AC_RESOURCE, V2P_WO(new_page)); return new_size; } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c index becf0b9d7..28a2bbde5 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_mmap.c @@ -62,7 +62,7 @@ int sys_mmap(uintptr_t* vaddr, uintptr_t* paddr, int len, int is_dev) raw_free(new_paddr); return -1; } - CreateResourceTag(NULL, &cur_task->memspace->tag, NULL, TRACER_MEM_FROM_BUDDY_AC_RESOURCE, new_paddr); + CreateResourceTag(NULL, &cur_task->memspace->tag, "ANON_MEMORY", TRACER_MEM_FROM_BUDDY_AC_RESOURCE, new_paddr); *paddr = (uintptr_t)new_paddr; } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c index 38a19bcff..6d10f6e03 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_register_irq.c @@ -117,7 +117,7 @@ int sys_register_irq(int irq_num, int irq_opcode) // init kerenl sender proxy if (kernel_irq_proxy == NULL) { /// @todo handle corner cases - struct MemSpace* pmemspace = alloc_memspace(); + struct MemSpace* pmemspace = alloc_memspace("KernelIrqProxy"); if (pmemspace == NULL) { return -1; } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c index fa5994a01..2e4ae052a 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_spawn.c @@ -38,7 +38,7 @@ extern int sys_new_thread(struct MemSpace* pmemspace, struct Thread* task, uintp int sys_spawn(char* img_start, char* name, char** argv) { // alloc a new memspace - struct MemSpace* pmemspace = alloc_memspace(); + struct MemSpace* pmemspace = alloc_memspace(name); if (pmemspace == NULL) { return -1; } diff --git a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c index 53406e3e2..6f97f1d1c 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/syscall/sys_state.c @@ -30,6 +30,7 @@ Modification: #include #include +#include "actracer.h" #include "assert.h" #include "buddy.h" #include "log.h" @@ -187,6 +188,10 @@ int sys_state(sys_state_option option, sys_state_info* info) hw_current_second(&info->current_second); break; } + case SYS_STATE_SHOW_ACTREE: { + debug_list_tracetree(); + break; + } case SYS_STATE_TEST: default: break; diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c b/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c index 3fce45d05..2f5b227b5 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/memspace.c @@ -41,7 +41,7 @@ Modification: #define MAX_SUPPORT_PARAMS 32 -struct MemSpace* alloc_memspace() +struct MemSpace* alloc_memspace(char* name) { struct MemSpace* pmemspace = slab_alloc(&xizi_task_manager.memspace_allocator); if (pmemspace == NULL) { @@ -56,7 +56,18 @@ struct MemSpace* alloc_memspace() pmemspace->mem_size = 0; pmemspace->pgdir.pd_addr = 0; pmemspace->thread_to_notify = NULL; - CreateResourceTag(&pmemspace->tag, &xizi_task_manager.tag, NULL, TRACER_OWNER, (void*)pmemspace); + if (!CreateResourceTag(&pmemspace->tag, &xizi_task_manager.tag, name, TRACER_OWNER, (void*)pmemspace)) { + DEBUG("Register MemSpace %s failed\n", name); + slab_free(&xizi_task_manager.memspace_allocator, (void*)pmemspace); + return NULL; + } + + pmemspace->mem_usage.mem_block_root = NULL; + if (!CreateResourceTag(&pmemspace->mem_usage.tag, &pmemspace->tag, "MemUsage", TRACER_SYSOBJECT, (void*)&pmemspace->mem_usage)) { + DEBUG("Register MemUsage %s failed\n", name); + slab_free(&xizi_task_manager.memspace_allocator, (void*)pmemspace); + return NULL; + } return pmemspace; } @@ -69,15 +80,23 @@ void free_memspace(struct MemSpace* pmemspace) xizi_pager.free_user_pgdir(&pmemspace->pgdir); } - TracerNode* tmp_node = NULL; - DOUBLE_LIST_FOR_EACH_ENTRY(tmp_node, &pmemspace->tag.meta->children_guard, list_node) - { - assert((uintptr_t)tmp_node->p_resource >= PHY_MEM_BASE && (uintptr_t)tmp_node->p_resource < PHY_MEM_STOP); - if ((uintptr_t)tmp_node->p_resource < PHY_USER_FREEMEM_BASE) { - kfree(P2V(tmp_node->p_resource)); - } else { - raw_free(tmp_node->p_resource); - } + // TracerNode* tmp_node = NULL; + // DOUBLE_LIST_FOR_EACH_ENTRY(tmp_node, &pmemspace->tag.meta->children_guard, list_node) + // { + // assert((uintptr_t)tmp_node->p_resource >= PHY_MEM_BASE && (uintptr_t)tmp_node->p_resource < PHY_MEM_STOP); + // if ((uintptr_t)tmp_node->p_resource < PHY_USER_FREEMEM_BASE) { + // kfree(P2V(tmp_node->p_resource)); + // } else { + // raw_free(tmp_node->p_resource); + // } + // } + + // delete space + RbtNode* rbt_node = pmemspace->mem_usage.mem_block_root; + while (rbt_node != NULL) { + assert((uintptr_t)V2P(rbt_node->key) >= PHY_MEM_BASE && (uintptr_t)V2P(rbt_node->key) < PHY_MEM_STOP); + kfree_by_ownership(pmemspace->mem_usage.tag, (void*)rbt_node->key); + rbt_node = pmemspace->mem_usage.mem_block_root; } /* free ipc virt address allocator */ diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c b/Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c index 9df773558..f9f3b4ab8 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/schedule.c @@ -28,7 +28,7 @@ Modification: 1. first version *************************************************/ #include "log.h" -#include "scheduler.h" +#include "schedule_algo.h" struct Thread* max_priority_runnable_task(void) { diff --git a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c index b0d80b581..a80721069 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/task/task.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/task/task.c @@ -35,7 +35,7 @@ Modification: #include "kalloc.h" #include "memspace.h" #include "multicores.h" -#include "scheduler.h" +#include "schedule_algo.h" #include "syscall.h" #include "task.h" #include "trap_common.h" @@ -176,7 +176,7 @@ static void _dealloc_task_cb(struct Thread* task) /* free thread's kernel stack */ if (task->thread_context.kern_stack_addr) { - kfree((char*)task->thread_context.kern_stack_addr); + kfree_by_ownership(task->memspace->mem_usage.tag, (char*)task->thread_context.kern_stack_addr); } /* free memspace if needed to */ @@ -235,7 +235,7 @@ static struct Thread* _new_task_cb(struct MemSpace* pmemspace) /* init main thread of task */ task->thread_context.task = task; // alloc stack page for task - if ((void*)(task->thread_context.kern_stack_addr = (uintptr_t)kalloc(USER_STACK_SIZE)) == NULL) { + if ((void*)(task->thread_context.kern_stack_addr = (uintptr_t)kalloc_by_ownership(pmemspace->mem_usage.tag, USER_STACK_SIZE)) == NULL) { /* here inside, will no free memspace */ _dealloc_task_cb(task); return NULL; @@ -288,7 +288,6 @@ extern void context_switch(struct context**, struct context*); static void _scheduler(struct SchedulerRightGroup right_group) { struct MmuCommonDone* p_mmu_driver = AchieveResource(&right_group.mmu_driver_tag); - struct XiziTrapDriver* p_intr_driver = AchieveResource(&right_group.intr_driver_tag); struct Thread* next_task; struct CPU* cpu = cur_cpu(); diff --git a/Ubiquitous/XiZi_AIoT/softkernel/tools/Makefile b/Ubiquitous/XiZi_AIoT/softkernel/tools/Makefile new file mode 100644 index 000000000..5d2513c10 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/tools/Makefile @@ -0,0 +1,4 @@ + +SRC_FILES := rbtree.c + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/softkernel/tools/rbtree.c b/Ubiquitous/XiZi_AIoT/softkernel/tools/rbtree.c new file mode 100644 index 000000000..31e1fd683 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/softkernel/tools/rbtree.c @@ -0,0 +1,387 @@ +#include "rbtree.h" +#include "log.h" +#include "object_allocator.h" + +struct RbtFactory { + TraceTag tag; + struct slab_allocator queue_ele_allocator; + struct slab_allocator rbtnode_ele_allocator; +}; + +struct Queue { + struct RbtNode* key; + struct Queue* next; +}; + +static struct RbtFactory rbt_factory; + +void module_rbt_factory_init(TraceTag* _softkernel_tag) +{ + CreateResourceTag(&rbt_factory.tag, _softkernel_tag, "GlobalRbtFactory", TRACER_SYSOBJECT, &rbt_factory); + slab_init(&rbt_factory.queue_ele_allocator, sizeof(struct Queue)); + slab_init(&rbt_factory.rbtnode_ele_allocator, sizeof(struct RbtNode)); +} + +struct Queue* front = NULL; +struct Queue* rear = NULL; + +struct RbtNode* pfront() +{ + struct RbtNode* key; + key = front->key; + return key; +} + +int isempty() +{ + if (front == NULL) + return 1; + + else + return 0; +} + +void dequeue() +{ + if (isempty()) + return; + + struct Queue* temp = front; + front = front->next; + slab_free(&rbt_factory.queue_ele_allocator, (void*)temp); +} + +void enqueue(struct RbtNode* key) +{ + struct Queue* temp = (struct Queue*)slab_alloc(&rbt_factory.queue_ele_allocator); + temp->key = key; + temp->next = NULL; + + if (front == NULL && rear == NULL) { + front = rear = temp; + return; + } + + rear->next = temp; + rear = temp; +} + +void levelorder(struct RbtNode* root) +{ + if (root == NULL) + return; + + enqueue(root); + + while (!isempty()) { + struct RbtNode* current = pfront(); + DEBUG("%d ", current->key); + + if (current->left != NULL) + enqueue(current->left); + + if (current->right != NULL) + enqueue(current->right); + + dequeue(); + } +} + +void LeftRotate(struct RbtNode** T, struct RbtNode** x) +{ + struct RbtNode* y = (*x)->right; + (*x)->right = y->left; + + if (y->left != NULL) + y->left->parent = *x; + + y->parent = (*x)->parent; + + if ((*x)->parent == NULL) + *T = y; + + else if (*x == (*x)->parent->left) + (*x)->parent->left = y; + + else + (*x)->parent->right = y; + + y->left = *x; + + (*x)->parent = y; +} +void RightRotate(struct RbtNode** T, struct RbtNode** x) +{ + struct RbtNode* y = (*x)->left; + (*x)->left = y->right; + + if (y->right != NULL) + y->right->parent = *x; + + y->parent = (*x)->parent; + + if ((*x)->parent == NULL) + *T = y; + + else if ((*x) == (*x)->parent->left) + (*x)->parent->left = y; + + else + (*x)->parent->right = y; + + y->right = *x; + (*x)->parent = y; +} + +void RB_insert_fixup(struct RbtNode** T, struct RbtNode** z) +{ + struct RbtNode* grandparent = NULL; + struct RbtNode* parentpt = NULL; + + while (((*z) != *T) && ((*z)->color != BLACK) && ((*z)->parent->color == RED)) { + parentpt = (*z)->parent; + grandparent = (*z)->parent->parent; + + if (parentpt == grandparent->left) { + struct RbtNode* uncle = grandparent->right; + + if (uncle != NULL && uncle->color == RED) { + grandparent->color = RED; + parentpt->color = BLACK; + uncle->color = BLACK; + *z = grandparent; + } + + else { + if ((*z) == parentpt->right) { + LeftRotate(T, &parentpt); + (*z) = parentpt; + parentpt = (*z)->parent; + } + + RightRotate(T, &grandparent); + parentpt->color = BLACK; + grandparent->color = RED; + (*z) = parentpt; + } + } + + else { + struct RbtNode* uncle = grandparent->left; + + if (uncle != NULL && uncle->color == RED) { + grandparent->color = RED; + parentpt->color = BLACK; + uncle->color = BLACK; + (*z) = grandparent; + } + + else { + if ((*z) == parentpt->left) { + RightRotate(T, &parentpt); + (*z) = parentpt; + parentpt = (*z)->parent; + } + + LeftRotate(T, &grandparent); + parentpt->color = BLACK; + grandparent->color = RED; + (*z) = parentpt; + } + } + } + (*T)->color = BLACK; +} + +struct RbtNode* rbt_insert(struct RbtNode* T, uintptr_t key, void* data) +{ + struct RbtNode* z = (struct RbtNode*)slab_alloc(&rbt_factory.rbtnode_ele_allocator); + z->key = key; + z->data = data; + z->left = NULL; + z->right = NULL; + z->parent = NULL; + z->color = RED; + + struct RbtNode* y = NULL; + struct RbtNode* x = T; // root + + while (x != NULL) { + y = x; + if (z->key < x->key) + x = x->left; + + else + x = x->right; + } + z->parent = y; + + if (y == NULL) + T = z; + + else if (z->key < y->key) + y->left = z; + + else + y->right = z; + + RB_insert_fixup(&T, &z); + + return T; +} + +void preorder(struct RbtNode* root) +{ + if (root == NULL) + return; + + DEBUG("%d ", root->key); + preorder(root->left); + preorder(root->right); +} + +struct RbtNode* Tree_minimum(struct RbtNode* RbtNode) +{ + while (RbtNode->left != NULL) + RbtNode = RbtNode->left; + + return RbtNode; +} + +void RB_delete_fixup(struct RbtNode** T, struct RbtNode** x) +{ + while ((*x) != *T && (*x)->color == BLACK) { + if ((*x) == (*x)->parent->left) { + struct RbtNode* w = (*x)->parent->right; + + if (w->color == RED) { + w->color = BLACK; + (*x)->parent->color = BLACK; + LeftRotate(T, &((*x)->parent)); + w = (*x)->parent->right; + } + + if (w->left->color == BLACK && w->right->color == BLACK) { + w->color = RED; + (*x) = (*x)->parent; + } + + else { + if (w->right->color == BLACK) { + w->left->color = BLACK; + w->color = RED; + RightRotate(T, &w); + w = (*x)->parent->right; + } + + w->color = (*x)->parent->color; + (*x)->parent->color = BLACK; + w->right->color = BLACK; + LeftRotate(T, &((*x)->parent)); + (*x) = *T; + } + } + + else { + struct RbtNode* w = (*x)->parent->left; + + if (w->color == RED) { + w->color = BLACK; + (*x)->parent->color = BLACK; + RightRotate(T, &((*x)->parent)); + w = (*x)->parent->left; + } + + if (w->right->color == BLACK && w->left->color == BLACK) { + w->color = RED; + (*x) = (*x)->parent; + } + + else { + if (w->left->color == BLACK) { + w->right->color = BLACK; + w->color = RED; + LeftRotate(T, &w); + w = (*x)->parent->left; + } + + w->color = (*x)->parent->color; + (*x)->parent->color = BLACK; + w->left->color = BLACK; + RightRotate(T, &((*x)->parent)); + (*x) = *T; + } + } + } + (*x)->color = BLACK; +} + +void RB_transplat(struct RbtNode** T, struct RbtNode** u, struct RbtNode** v) +{ + if ((*u)->parent == NULL) + *T = *v; + + else if ((*u) == (*u)->parent->left) + (*u)->parent->left = *v; + else + (*u)->parent->right = *v; + + if ((*v) != NULL) + (*v)->parent = (*u)->parent; +} + +struct RbtNode* rbt_delete(struct RbtNode* T, struct RbtNode* z) +{ + struct RbtNode* y = z; + enum rbt_type yoc; + yoc = z->color; // y's original color + + struct RbtNode* x; + + if (z->left == NULL) { + x = z->right; + RB_transplat(&T, &z, &(z->right)); + } + + else if (z->right == NULL) { + x = z->left; + RB_transplat(&T, &z, &(z->left)); + } + + else { + y = Tree_minimum(z->right); + yoc = y->color; + x = y->right; + + if (y->parent == z) + x->parent = y; + + else { + RB_transplat(&T, &y, &(y->right)); + y->right = z->right; + y->right->parent = y; + } + + RB_transplat(&T, &z, &y); + y->left = z->left; + y->left->parent = y; + y->color = z->color; + } + + if (yoc == BLACK) + RB_delete_fixup(&T, &x); + + slab_free(&rbt_factory.rbtnode_ele_allocator, (void*)z); + return T; +} + +struct RbtNode* rbt_search(struct RbtNode* root, int x) +{ + if (root == NULL || root->key == x) + return root; + + if (root->key > x) + return rbt_search(root->left, x); + else + return rbt_search(root->right, x); +} \ No newline at end of file