add memory usage

This commit is contained in:
TXuian 2024-10-29 16:17:43 +08:00
parent 968d66e5a9
commit 7b6c93d391
37 changed files with 654 additions and 115 deletions

View File

@ -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()
{

View File

@ -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;

View File

@ -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

View File

@ -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; }

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -1797,6 +1797,11 @@ void shellShowCpusInfo()
show_cpu();
}
void shellShowActree()
{
show_actree();
}
#if SHELL_EXEC_UNDEF_FUNC == 1
/**
* @brief shell执行未定义函数

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
};

View File

@ -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 {

View File

@ -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);

View File

@ -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();

View File

@ -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++) {

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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)
{

View File

@ -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();

View File

@ -0,0 +1,4 @@
SRC_FILES := rbtree.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -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);
}