forked from xuos/xiuos
add memory usage
This commit is contained in:
parent
968d66e5a9
commit
7b6c93d391
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <stdint.h>
|
||||
__attribute__((always_inline)) static inline uint32_t v2p(void* a) { return ((uint32_t)(a)) - KERN_MEM_BASE; }
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -30,35 +30,12 @@ Modification:
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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);
|
||||
bool DeleteResource(struct TraceTag* target, struct TraceTag* owner);
|
||||
|
||||
void debug_list_tracetree();
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1797,6 +1797,11 @@ void shellShowCpusInfo()
|
|||
show_cpu();
|
||||
}
|
||||
|
||||
void shellShowActree()
|
||||
{
|
||||
show_actree();
|
||||
}
|
||||
|
||||
#if SHELL_EXEC_UNDEF_FUNC == 1
|
||||
/**
|
||||
* @brief shell执行未定义函数
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ Modification:
|
|||
|
||||
#include "list.h"
|
||||
#include "memlayout.h"
|
||||
#include "spinlock.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
struct ThreadStackPointer load_user_stack(struct MemSpace* pmemspace, char** argv);
|
||||
|
|
|
@ -29,10 +29,12 @@ Modification:
|
|||
*************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "actracer_tag.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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);
|
|
@ -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);
|
|
@ -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);
|
||||
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;
|
||||
};
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ Modification:
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
SRC_FILES := rbtree.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue