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"
|
#include "cortex_a9.h"
|
||||||
|
|
||||||
#define NR_CPU 1
|
#define NR_CPU 4
|
||||||
|
|
||||||
__attribute__((always_inline, optimize("O0"))) static inline uint32_t user_mode()
|
__attribute__((always_inline, optimize("O0"))) static inline uint32_t user_mode()
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,7 +129,7 @@ static bool xizi_gpt_init()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// register clock handler to intr
|
// 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->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);
|
p_intr_driver->single_irq_enable(p_clock_driver->get_clock_int(), 0, 0);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -73,4 +73,11 @@ Modification:
|
||||||
#define KERN_MEM_BASE (0x90000000) // First kernel virtual address
|
#define KERN_MEM_BASE (0x90000000) // First kernel virtual address
|
||||||
#define KERN_OFFSET (KERN_MEM_BASE - PHY_MEM_BASE)
|
#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
|
// 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_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))
|
#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__
|
#ifndef __ASSEMBLER__
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
__attribute__((always_inline)) static inline uint32_t v2p(void* a) { return ((uint32_t)(a)) - KERN_MEM_BASE; }
|
__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';
|
p_name[TRACER_NODE_NAME_LEN - 1] = '\0';
|
||||||
node->name = p_name;
|
node->name = p_name;
|
||||||
}
|
}
|
||||||
if (node->type == TRACER_OWNER) {
|
doubleListNodeInit(&node->children_guard);
|
||||||
doubleListNodeInit(&node->children_guard);
|
node->p_resource = p_resource;
|
||||||
} else {
|
|
||||||
node->p_resource = p_resource;
|
|
||||||
}
|
|
||||||
doubleListNodeInit(&node->list_node);
|
doubleListNodeInit(&node->list_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,13 +146,10 @@ bool CreateResourceTag(TraceTag* new_tag, TraceTag* owner, char* name, tracemeta
|
||||||
{
|
{
|
||||||
assert(owner != NULL);
|
assert(owner != NULL);
|
||||||
if (owner->meta == NULL) {
|
if (owner->meta == NULL) {
|
||||||
ERROR("Tracer: Empty owner\n");
|
ERROR("Tracer: Empty owner, node name: %s\n", name);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
assert(owner->meta->type == TRACER_OWNER);
|
|
||||||
if (tracer_find_node_onestep(owner->meta, name) != NULL) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// assert(owner->meta->type == TRACER_OWNER);
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -204,27 +198,37 @@ bool DeleteResource(TraceTag* target, TraceTag* owner)
|
||||||
return true;
|
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;
|
TracerNode* tmp = NULL;
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
|
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
|
||||||
{
|
{
|
||||||
if (tmp->name != NULL) {
|
if (tmp->name != NULL) {
|
||||||
DEBUG("%s ", tmp->name);
|
DEBUG_PRINTF("%s ", tmp->name);
|
||||||
} else {
|
} else {
|
||||||
DEBUG("ANON ");
|
DEBUG_PRINTF("ANON ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG("\n");
|
DEBUG_PRINTF("\n");
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(tmp, &cur_node->children_guard, list_node)
|
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()
|
void debug_list_tracetree()
|
||||||
{
|
{
|
||||||
TracerNode* ref_root = RequireRootTag()->meta;
|
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 <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "list.h"
|
#include "actracer_tag.h"
|
||||||
#include "object_allocator.h"
|
#include "object_allocator.h"
|
||||||
|
|
||||||
#define TRACER_NODE_NAME_LEN 32
|
#define TRACER_NODE_NAME_LEN 32
|
||||||
|
|
||||||
typedef enum {
|
#define GetSysObject(type, target_tag) (type*)AchieveResource(target_tag)
|
||||||
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;
|
|
||||||
|
|
||||||
struct SysTracer {
|
struct SysTracer {
|
||||||
TracerNode root_node;
|
TracerNode root_node;
|
||||||
|
@ -73,3 +50,5 @@ bool AchieveResourceTag(struct TraceTag* target, struct TraceTag* owner, char* n
|
||||||
void* AchieveResource(struct TraceTag* tag);
|
void* AchieveResource(struct TraceTag* tag);
|
||||||
bool CreateResourceTag(struct TraceTag* new_tag, struct TraceTag* owner, char* name, tracemeta_ac_type type, void* p_resource);
|
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
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -43,7 +43,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: 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
|
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
|
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
|
endif
|
||||||
|
|
|
@ -102,6 +102,11 @@ int show_cpu()
|
||||||
return syscall(SYSCALL_SYS_STATE, SYS_STATE_SHOW_CPU_INFO, 0, 0, 0);
|
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()
|
uintptr_t get_second()
|
||||||
{
|
{
|
||||||
sys_state_info info;
|
sys_state_info info;
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef enum {
|
||||||
SYS_STATE_SHOW_CPU_INFO,
|
SYS_STATE_SHOW_CPU_INFO,
|
||||||
SYS_STATE_GET_CURRENT_TICK,
|
SYS_STATE_GET_CURRENT_TICK,
|
||||||
SYS_STATE_GET_CURRENT_SECOND,
|
SYS_STATE_GET_CURRENT_SECOND,
|
||||||
|
SYS_STATE_SHOW_ACTREE,
|
||||||
} sys_state_option;
|
} sys_state_option;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -99,6 +100,7 @@ int set_priority(sys_state_info* info);
|
||||||
int show_task();
|
int show_task();
|
||||||
int show_mem();
|
int show_mem();
|
||||||
int show_cpu();
|
int show_cpu();
|
||||||
|
int show_actree();
|
||||||
|
|
||||||
uintptr_t get_second();
|
uintptr_t get_second();
|
||||||
uintptr_t get_tick();
|
uintptr_t get_tick();
|
||||||
|
|
|
@ -1797,6 +1797,11 @@ void shellShowCpusInfo()
|
||||||
show_cpu();
|
show_cpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shellShowActree()
|
||||||
|
{
|
||||||
|
show_actree();
|
||||||
|
}
|
||||||
|
|
||||||
#if SHELL_EXEC_UNDEF_FUNC == 1
|
#if SHELL_EXEC_UNDEF_FUNC == 1
|
||||||
/**
|
/**
|
||||||
* @brief shell执行未定义函数
|
* @brief shell执行未定义函数
|
||||||
|
|
|
@ -40,6 +40,7 @@ extern void shellKill(int pid);
|
||||||
extern void shellShowTasks();
|
extern void shellShowTasks();
|
||||||
extern void shellShowMemInfo();
|
extern void shellShowMemInfo();
|
||||||
extern void shellShowCpusInfo();
|
extern void shellShowCpusInfo();
|
||||||
|
extern void shellShowActree();
|
||||||
|
|
||||||
#if SHELL_EXEC_UNDEF_FUNC == 1
|
#if SHELL_EXEC_UNDEF_FUNC == 1
|
||||||
extern int shellExecute(int argc, char* argv[]);
|
extern int shellExecute(int argc, char* argv[]);
|
||||||
|
@ -118,6 +119,8 @@ const ShellCommand shellCommandList[] = {
|
||||||
showMemInfo, shellShowMemInfo, display memory info),
|
showMemInfo, shellShowMemInfo, display memory info),
|
||||||
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
|
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) | SHELL_CMD_DISABLE_RETURN,
|
||||||
showCpusInfo, shellShowCpusInfo, display cpus info),
|
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
|
#if SHELL_EXEC_UNDEF_FUNC == 1
|
||||||
SHELL_CMD_ITEM(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_DISABLE_RETURN,
|
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
|
SRC_FILES := main.c load_apps.S
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ Modification:
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "memlayout.h"
|
#include "memlayout.h"
|
||||||
#include "spinlock.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -70,7 +69,6 @@ struct KFreeList {
|
||||||
struct KBuddy {
|
struct KBuddy {
|
||||||
uintptr_t n_pages;
|
uintptr_t n_pages;
|
||||||
uintptr_t use_lock;
|
uintptr_t use_lock;
|
||||||
struct spinlock lock;
|
|
||||||
struct KFreeList free_list[MAX_BUDDY_ORDER];
|
struct KFreeList free_list[MAX_BUDDY_ORDER];
|
||||||
struct KPage* first_page;
|
struct KPage* first_page;
|
||||||
uintptr_t mem_start;
|
uintptr_t mem_start;
|
||||||
|
|
|
@ -29,13 +29,22 @@ Modification:
|
||||||
*************************************************/
|
*************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "pagetable.h"
|
#include "actracer.h"
|
||||||
|
#include "rbtree.h"
|
||||||
|
|
||||||
|
struct MemUsage {
|
||||||
|
TraceTag tag;
|
||||||
|
RbtNode* mem_block_root;
|
||||||
|
};
|
||||||
|
|
||||||
bool module_phymem_init();
|
bool module_phymem_init();
|
||||||
char* kalloc(size_t size);
|
char* kalloc(size_t size);
|
||||||
bool kfree(char* vaddr);
|
bool kfree(char* vaddr);
|
||||||
bool raw_kfree(char* paddr);
|
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);
|
char* raw_alloc(size_t size);
|
||||||
bool raw_free(char* paddr);
|
bool raw_free(char* paddr);
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ Modification:
|
||||||
#include "actracer.h"
|
#include "actracer.h"
|
||||||
#include "bitmap64.h"
|
#include "bitmap64.h"
|
||||||
#include "buddy.h"
|
#include "buddy.h"
|
||||||
|
#include "kalloc.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
struct TopLevelPageDirectory {
|
struct TopLevelPageDirectory {
|
||||||
|
@ -48,6 +49,9 @@ struct ThreadStackPointer {
|
||||||
struct MemSpace {
|
struct MemSpace {
|
||||||
/* trace node */
|
/* trace node */
|
||||||
TraceTag tag;
|
TraceTag tag;
|
||||||
|
/* mem usage info */
|
||||||
|
struct MemUsage mem_usage;
|
||||||
|
|
||||||
/* task memory resources */
|
/* task memory resources */
|
||||||
struct TopLevelPageDirectory pgdir; // [phy] vm pgtbl base address
|
struct TopLevelPageDirectory pgdir; // [phy] vm pgtbl base address
|
||||||
uintptr_t heap_base; // mem size of proc used(allocated by kernel)
|
uintptr_t heap_base; // mem size of proc used(allocated by kernel)
|
||||||
|
@ -63,7 +67,7 @@ struct MemSpace {
|
||||||
struct Thread* thread_to_notify;
|
struct Thread* thread_to_notify;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemSpace* alloc_memspace();
|
struct MemSpace* alloc_memspace(char* name);
|
||||||
void free_memspace(struct MemSpace* pmemspace);
|
void free_memspace(struct MemSpace* pmemspace);
|
||||||
uintptr_t* load_memspace(struct MemSpace* pmemspace, char* img_start);
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include "actracer_tag.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct slab_state {
|
struct slab_state {
|
||||||
|
TraceTag owner_tag;
|
||||||
struct slab_state *prev, *next;
|
struct slab_state *prev, *next;
|
||||||
uint64_t bitmap;
|
uint64_t bitmap;
|
||||||
uintptr_t refcount;
|
uintptr_t refcount;
|
||||||
|
@ -40,6 +42,7 @@ struct slab_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct slab_allocator {
|
struct slab_allocator {
|
||||||
|
|
||||||
size_t element_size;
|
size_t element_size;
|
||||||
size_t nr_elements;
|
size_t nr_elements;
|
||||||
size_t slabsize;
|
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
|
#pragma once
|
||||||
|
#include "actracer.h"
|
||||||
|
#include "ksemaphore.h"
|
||||||
|
|
||||||
#include "task.h"
|
#define TASK_MAX_PRIORITY 32
|
||||||
|
|
||||||
struct Thread* max_priority_runnable_task(void);
|
struct ScheduleNode {
|
||||||
struct Thread* round_robin_runnable_task(uint32_t priority);
|
TraceTag task_ref;
|
||||||
void recover_priority(void);
|
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_SHOW_CPU_INFO,
|
||||||
SYS_STATE_GET_CURRENT_TICK,
|
SYS_STATE_GET_CURRENT_TICK,
|
||||||
SYS_STATE_GET_CURRENT_SECOND,
|
SYS_STATE_GET_CURRENT_SECOND,
|
||||||
|
SYS_STATE_SHOW_ACTREE,
|
||||||
} sys_state_option;
|
} sys_state_option;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -31,10 +31,13 @@ Modification:
|
||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "rbtree.h"
|
||||||
#include "task.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;
|
struct TraceTag server_identifier_owner;
|
||||||
CreateResourceTag(&server_identifier_owner, _softkernel_tag, "server-identifier", TRACER_OWNER, NULL);
|
CreateResourceTag(&server_identifier_owner, _softkernel_tag, "server-identifier", TRACER_OWNER, NULL);
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ int main(void)
|
||||||
|
|
||||||
if (cpu_id == 0) {
|
if (cpu_id == 0) {
|
||||||
/* init memory management first */
|
/* init memory management first */
|
||||||
|
|
||||||
module_phymem_init(); // init buddy management system
|
module_phymem_init(); // init buddy management system
|
||||||
/* init tracer system */
|
/* init tracer system */
|
||||||
sys_tracer_init();
|
sys_tracer_init();
|
||||||
|
|
|
@ -31,6 +31,7 @@ Modification:
|
||||||
#include "buddy.h"
|
#include "buddy.h"
|
||||||
#include "kalloc.h"
|
#include "kalloc.h"
|
||||||
#include "log.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)
|
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
|
// total number of free pages
|
||||||
pbuddy->n_pages = (pbuddy->mem_end - (uintptr_t)pbuddy->mem_start) >> LEVEL4_PTE_SHIFT;
|
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
|
// init each free page list from 2^0 to 2^8
|
||||||
for (; i < MAX_BUDDY_ORDER; i++) {
|
for (; i < MAX_BUDDY_ORDER; i++) {
|
||||||
|
|
|
@ -30,6 +30,9 @@ Modification:
|
||||||
#include "kalloc.h"
|
#include "kalloc.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
|
#include "memlayout.h"
|
||||||
|
#include "pagetable.h"
|
||||||
|
|
||||||
#include "actracer.h"
|
#include "actracer.h"
|
||||||
#include "buddy.h"
|
#include "buddy.h"
|
||||||
|
|
||||||
|
@ -64,11 +67,35 @@ char* kalloc(uintptr_t size)
|
||||||
return mem_alloc;
|
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)
|
bool kfree(char* vaddr)
|
||||||
{
|
{
|
||||||
return KBuddyFree(&kern_virtmem_buddy, V2P_WO(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)
|
bool raw_kfree(char* paddr)
|
||||||
{
|
{
|
||||||
return KBuddyFree(&kern_virtmem_buddy, paddr);
|
return KBuddyFree(&kern_virtmem_buddy, paddr);
|
||||||
|
|
|
@ -32,6 +32,7 @@ Modification:
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "kalloc.h"
|
#include "kalloc.h"
|
||||||
#include "object_allocator.h"
|
#include "object_allocator.h"
|
||||||
|
#include "pagetable.h"
|
||||||
|
|
||||||
#define BITMAP_BITS_EMPTY_FULL ((uint64_t)0)
|
#define BITMAP_BITS_EMPTY_FULL ((uint64_t)0)
|
||||||
#define BITMAP_FIRST_BIT ((uint64_t)1)
|
#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 cur_size = ALIGNUP(old_size, PAGE_SIZE);
|
||||||
uintptr_t size_needed = ALIGNUP(new_size, PAGE_SIZE) - cur_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) {
|
if (new_page == NULL) {
|
||||||
ERROR("No memory\n");
|
ERROR("No memory\n");
|
||||||
return cur_size;
|
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)) {
|
if (!xizi_pager.map_pages(pmemspace, cur_size, V2P(new_page), size_needed, false)) {
|
||||||
return cur_size;
|
return cur_size;
|
||||||
}
|
}
|
||||||
CreateResourceTag(NULL, &pmemspace->tag, NULL, TRACER_MEM_FROM_BUDDY_AC_RESOURCE, V2P_WO(new_page));
|
|
||||||
|
|
||||||
return new_size;
|
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);
|
raw_free(new_paddr);
|
||||||
return -1;
|
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;
|
*paddr = (uintptr_t)new_paddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ 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) {
|
||||||
/// @todo handle corner cases
|
/// @todo handle corner cases
|
||||||
struct MemSpace* pmemspace = alloc_memspace();
|
struct MemSpace* pmemspace = alloc_memspace("KernelIrqProxy");
|
||||||
if (pmemspace == NULL) {
|
if (pmemspace == NULL) {
|
||||||
return -1;
|
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)
|
int sys_spawn(char* img_start, char* name, char** argv)
|
||||||
{
|
{
|
||||||
// alloc a new memspace
|
// alloc a new memspace
|
||||||
struct MemSpace* pmemspace = alloc_memspace();
|
struct MemSpace* pmemspace = alloc_memspace(name);
|
||||||
if (pmemspace == NULL) {
|
if (pmemspace == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ Modification:
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "actracer.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "buddy.h"
|
#include "buddy.h"
|
||||||
#include "log.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);
|
hw_current_second(&info->current_second);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SYS_STATE_SHOW_ACTREE: {
|
||||||
|
debug_list_tracetree();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SYS_STATE_TEST:
|
case SYS_STATE_TEST:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -41,7 +41,7 @@ Modification:
|
||||||
|
|
||||||
#define MAX_SUPPORT_PARAMS 32
|
#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);
|
struct MemSpace* pmemspace = slab_alloc(&xizi_task_manager.memspace_allocator);
|
||||||
if (pmemspace == NULL) {
|
if (pmemspace == NULL) {
|
||||||
|
@ -56,7 +56,18 @@ struct MemSpace* alloc_memspace()
|
||||||
pmemspace->mem_size = 0;
|
pmemspace->mem_size = 0;
|
||||||
pmemspace->pgdir.pd_addr = 0;
|
pmemspace->pgdir.pd_addr = 0;
|
||||||
pmemspace->thread_to_notify = NULL;
|
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;
|
return pmemspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,15 +80,23 @@ void free_memspace(struct MemSpace* pmemspace)
|
||||||
xizi_pager.free_user_pgdir(&pmemspace->pgdir);
|
xizi_pager.free_user_pgdir(&pmemspace->pgdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
TracerNode* tmp_node = NULL;
|
// TracerNode* tmp_node = NULL;
|
||||||
DOUBLE_LIST_FOR_EACH_ENTRY(tmp_node, &pmemspace->tag.meta->children_guard, list_node)
|
// 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);
|
// 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) {
|
// if ((uintptr_t)tmp_node->p_resource < PHY_USER_FREEMEM_BASE) {
|
||||||
kfree(P2V(tmp_node->p_resource));
|
// kfree(P2V(tmp_node->p_resource));
|
||||||
} else {
|
// } else {
|
||||||
raw_free(tmp_node->p_resource);
|
// 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 */
|
/* free ipc virt address allocator */
|
||||||
|
|
|
@ -28,7 +28,7 @@ Modification:
|
||||||
1. first version
|
1. first version
|
||||||
*************************************************/
|
*************************************************/
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "scheduler.h"
|
#include "schedule_algo.h"
|
||||||
|
|
||||||
struct Thread* max_priority_runnable_task(void)
|
struct Thread* max_priority_runnable_task(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,7 +35,7 @@ Modification:
|
||||||
#include "kalloc.h"
|
#include "kalloc.h"
|
||||||
#include "memspace.h"
|
#include "memspace.h"
|
||||||
#include "multicores.h"
|
#include "multicores.h"
|
||||||
#include "scheduler.h"
|
#include "schedule_algo.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "trap_common.h"
|
#include "trap_common.h"
|
||||||
|
@ -176,7 +176,7 @@ static void _dealloc_task_cb(struct Thread* task)
|
||||||
|
|
||||||
/* free thread's kernel stack */
|
/* free thread's kernel stack */
|
||||||
if (task->thread_context.kern_stack_addr) {
|
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 */
|
/* free memspace if needed to */
|
||||||
|
@ -235,7 +235,7 @@ static struct Thread* _new_task_cb(struct MemSpace* pmemspace)
|
||||||
/* init main thread of task */
|
/* init main thread of task */
|
||||||
task->thread_context.task = task;
|
task->thread_context.task = task;
|
||||||
// alloc stack page for 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 */
|
/* here inside, will no free memspace */
|
||||||
_dealloc_task_cb(task);
|
_dealloc_task_cb(task);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -288,7 +288,6 @@ 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 XiziTrapDriver* p_intr_driver = AchieveResource(&right_group.intr_driver_tag);
|
|
||||||
struct Thread* next_task;
|
struct Thread* next_task;
|
||||||
struct CPU* cpu = cur_cpu();
|
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