new branch for shit
This commit is contained in:
parent
798b3b0454
commit
48388bbf01
|
@ -1,16 +1,20 @@
|
|||
cmake_minimum_required(VERSION 2.8.4)
|
||||
project(secX)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c11")
|
||||
|
||||
file(GLOB_RECURSE hal_src ./hal/*.h ./hal/*.c ./common/*.h ./common/*.c)
|
||||
file(GLOB_RECURSE kernel_src ./kernel/*.h ./kernel/*.c ./common/*.h ./common/*.c)
|
||||
file(GLOB_RECURSE test_src ./test/*.h ./test/*.c ./common/*.h ./common/*.c)
|
||||
include_directories(inc)
|
||||
|
||||
file(GLOB_RECURSE SOURCE_FILES ./*.h ./*.c)
|
||||
file(GLOB_RECURSE TestFiles ./test/*.c ./lib/*.c)
|
||||
#KERNEL + HAL
|
||||
include_directories(kernel/inc)
|
||||
include_directories(hal/inc)
|
||||
add_executable(kernel ${kernel_src} ${hal_src})
|
||||
|
||||
add_executable(Workspace ${SOURCE_FILES})
|
||||
|
||||
#include_directories(test/include)
|
||||
# KERNEL + TESTS
|
||||
#include_directories(test/inc)
|
||||
#include_directories(kernel/inc)
|
||||
#add_definitions(-DTDBG)
|
||||
#add_executable(Test ${TestFiles})
|
||||
#add_executable(tests ${test_src} ${kernel_src})
|
||||
|
|
25
Makefile
25
Makefile
|
@ -1,11 +1,11 @@
|
|||
AS = nasm
|
||||
CC = clang
|
||||
LD = clang
|
||||
DAS = llvm-objdump
|
||||
AS := nasm
|
||||
CC := clang
|
||||
LD := clang
|
||||
DAS := llvm-objdump
|
||||
|
||||
INCLUDE_DIR = include
|
||||
MK = mk
|
||||
OUT = out
|
||||
INC_COMMON := inc
|
||||
MK := mk
|
||||
OUT := out
|
||||
|
||||
C_IGNORED_WARNINGS = -Wno-cast-align \
|
||||
-Wno-padded
|
||||
|
@ -19,6 +19,8 @@ C_FLAGS = -xc\
|
|||
-Werror \
|
||||
$(C_IGNORED_WARNINGS) \
|
||||
-ffreestanding \
|
||||
-fno-builtin \
|
||||
-nostdlib \
|
||||
-fno-pic \
|
||||
-mcmodel=kernel \
|
||||
-fno-stack-protector \
|
||||
|
@ -28,15 +30,16 @@ C_FLAGS = -xc\
|
|||
-mno-sse2 \
|
||||
-mno-sse3 \
|
||||
-mno-3dnow \
|
||||
-target x86_64-elf \
|
||||
-I$(INCLUDE_DIR)
|
||||
-target x86_64-pc-none-elf \
|
||||
-I$(INC_COMMON)
|
||||
|
||||
AS_FLAGS = -w+all \
|
||||
-w+error \
|
||||
-f elf64 \
|
||||
-F dwarf \
|
||||
-g \
|
||||
$(addprefix -I, $(INCLUDE_DIR)/)
|
||||
-I$(INC_COMMON) \
|
||||
$(INC_$(d))
|
||||
|
||||
LD_FLAGS = -fuse-ld=lld \
|
||||
-nostdlib \
|
||||
|
@ -66,4 +69,4 @@ DUMP = $(DAS) $(DUMP_FLAGS) $< > $@
|
|||
PREP = $(CC) $(PREP_FLAGS) $< > $@
|
||||
GDEP = $(CC) $(GDEP_FLAGS) -MF $(addsuffix .d, $@) $< > /dev/null
|
||||
|
||||
include Rules.top
|
||||
include Rules.top
|
||||
|
|
|
@ -8,10 +8,10 @@ dir := hal
|
|||
include $(dir)/Rules.mk
|
||||
dir := kernel
|
||||
include $(dir)/Rules.mk
|
||||
dir := lib
|
||||
include $(dir)/Rules.mk
|
||||
dir := mk
|
||||
include $(dir)/Rules.mk
|
||||
dir := common
|
||||
include $(dir)/Rules.mk
|
||||
|
||||
LD_SCRIPT := $(OUT)/$(MK)/linker.ld
|
||||
TGT := $(OUT)/secxkrnl.elf
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
include $(MK)/prologue.mk
|
||||
|
||||
SRC_$(d) := $(d)/common.c
|
||||
|
||||
include $(MK)/stdrules.mk
|
||||
|
||||
include $(MK)/epilogue.mk
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
void
|
||||
mem_cpy(void *src, void *dst, uint64 size)
|
||||
{
|
||||
if (src == NULL || dst == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
char *cSrc = (char *) src;
|
||||
char *cDst = (char *) dst;
|
||||
while (size--)
|
||||
{
|
||||
*(cDst++) = *(cSrc++);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mem_set(void *src, uint8 val, uint64 size)
|
||||
{
|
||||
if (src == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (size--)
|
||||
{
|
||||
*(uint8 *) src = val;
|
||||
src = (void *) ((uintptr) src + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mem_mv(void *src, void *dst, uint64 size)
|
||||
{
|
||||
if (src == NULL || dst == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (src >= dst)
|
||||
{
|
||||
mem_cpy(src, dst, size);
|
||||
return;
|
||||
}
|
||||
src = (void *) ((uintptr) src + size - 1);
|
||||
dst = (void *) ((uintptr) dst + size - 1);
|
||||
while (size--)
|
||||
{
|
||||
*(char *) dst = *(char *) src;
|
||||
dst = (void *) ((uintptr) dst - 1);
|
||||
src = (void *) ((uintptr) src - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Random Generator
|
||||
//
|
||||
static uint32 seed = 1;
|
||||
static uint32 max = 16777215;
|
||||
|
||||
uint32
|
||||
lb_rand(void)
|
||||
{
|
||||
seed = seed * 1103512986 + 29865;
|
||||
return (unsigned int) (seed / 65536) % (max + 1);
|
||||
}
|
||||
|
||||
void
|
||||
lb_srand(uint32 _seed)
|
||||
{
|
||||
seed = _seed;
|
||||
}
|
||||
|
||||
void
|
||||
lb_mrand(uint32 _max)
|
||||
{
|
||||
max = _max;
|
||||
}
|
||||
|
||||
//
|
||||
// String Library
|
||||
//
|
||||
|
||||
uint64
|
||||
str_len(char const *str)
|
||||
{
|
||||
uint64 length = 0;
|
||||
if (str == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (*str != 0)
|
||||
{
|
||||
str++;
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
uint64
|
||||
str_cmp(char const *str1, char const *str2)
|
||||
{
|
||||
if (str1 == NULL || str2 == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint64 length = str_len(str1);
|
||||
if (length != str_len(str2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (length--)
|
||||
{
|
||||
if (*(str1 + length) != *(str2 + length))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#include ""
|
||||
|
||||
int32_t KABI ke_interlocked_exchange_32(int32_t *target, int32_t val)
|
||||
{
|
||||
return hal_interlocked_exchange_32(target, val);
|
||||
}
|
||||
|
||||
int32_t KABI ke_interlocked_increment_32(int32_t *target, int32_t increment)
|
||||
{
|
||||
return hal_interlocked_increment_32(target, increment);
|
||||
}
|
||||
|
||||
int32_t KABI ke_interlocked_compare_exchange_32(int32_t *target, int32_t compare, int32_t val)
|
||||
{
|
||||
return hal_interlocked_compare_exchange_32(target, compare, val);
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
#define ASM_FILE
|
||||
#include "multiboot2.h"
|
||||
|
||||
%define GET_PADDR(x) ((x) - KERNEL_IMAGE_VADDR + KERNEL_IMAGE_PADDR)
|
||||
%define BOCHS_BREAK xchg bx,bx
|
||||
|
||||
extern hal_main
|
||||
global hal_main_32
|
||||
|
||||
section .multiboot_header
|
||||
bits 32
|
||||
MULTIBOOT_ARCH equ 0
|
||||
MULTIBOOT_CHECK_SUM equ (0xFFFFFFFF - (MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_HEADER_SIZE + MULTIBOOT_ARCH) + 1)
|
||||
MULTIBOOT_REQ_LOADERNAME equ 2
|
||||
MULTIBOOT_REQ_MMAP equ 6
|
||||
MULTIBOOT_REQ_ACPI_RSDP equ 15
|
||||
;====================
|
||||
;header tag
|
||||
align MULTIBOOT_HEADER_ALIGN
|
||||
multiboot_header_tag:
|
||||
dd MULTIBOOT2_HEADER_MAGIC
|
||||
dd MULTIBOOT_ARCH
|
||||
dd MULTIBOOT_HEADER_SIZE
|
||||
dd MULTIBOOT_CHECK_SUM
|
||||
;====================
|
||||
;INFO_REQUEST_TAG
|
||||
align MULTIBOOT_INFO_ALIGN
|
||||
multiboot_info_tag:
|
||||
dw 0x1 ; type=1
|
||||
dw 0x0 ; flag=0
|
||||
dd MULTIBOOT_INFO_TAG_SIZE
|
||||
dd MULTIBOOT_REQ_LOADERNAME
|
||||
dd MULTIBOOT_REQ_MMAP
|
||||
MULTIBOOT_INFO_TAG_SIZE equ ($ - multiboot_info_tag)
|
||||
;====================
|
||||
;MODULE ALIGNMENT TAG
|
||||
align MULTIBOOT_INFO_ALIGN
|
||||
dw 0x6; type=6
|
||||
dw 0x0; flag=0
|
||||
dd 0x8
|
||||
;====================
|
||||
align MULTIBOOT_INFO_ALIGN
|
||||
;End_tag
|
||||
dw 0x0
|
||||
dw 0x0
|
||||
dd 0x8
|
||||
;====================
|
||||
MULTIBOOT_HEADER_SIZE equ ($ - multiboot_header_tag)
|
||||
|
||||
|
||||
section .text
|
||||
bits 32
|
||||
align KERNEL_PAGE_SIZE
|
||||
hal_main_32:
|
||||
cli
|
||||
cld
|
||||
cmp eax,MULTIBOOT2_BOOTLOADER_MAGIC
|
||||
je .loaded_by_grub
|
||||
hlt
|
||||
|
||||
.loaded_by_grub:
|
||||
; save multiboot_info*
|
||||
mov esi,ebx
|
||||
call halp_check_long_mode
|
||||
cmp eax,1
|
||||
je .init_long_mode
|
||||
hlt
|
||||
|
||||
.init_long_mode:
|
||||
; disable paging first
|
||||
mov eax, cr0 ; Set the A-register to control register 0.
|
||||
and eax, 0x7FFFFFFF ; Clear the PG-bit, which is bit 31.
|
||||
mov cr0, eax ; Set control register 0 to the A-register.
|
||||
|
||||
; identity map the first 4GB
|
||||
; ATTRIBUTE = READ/WRITE + SU
|
||||
mov eax, GET_PADDR(_pml4)
|
||||
mov dword [eax], GET_PADDR(_pdpt) + 11b
|
||||
|
||||
; write values for pdpt
|
||||
mov ecx, 10000011b
|
||||
|
||||
mov eax, GET_PADDR(_pdpt)
|
||||
mov dword [eax], ecx
|
||||
|
||||
add eax,8
|
||||
add ecx,0x40000000 ;1G
|
||||
mov dword [eax], ecx
|
||||
|
||||
add eax,8
|
||||
add ecx,0x40000000 ;1G
|
||||
mov dword [eax], ecx
|
||||
|
||||
add eax,8
|
||||
add ecx,0x40000000 ;1G
|
||||
mov dword [eax], ecx
|
||||
|
||||
BOCHS_BREAK
|
||||
|
||||
; enable PAE
|
||||
mov eax, cr4 ; Set the A-register to control register 4.
|
||||
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
|
||||
mov cr4, eax ; Set control register 4 to the A-register.
|
||||
|
||||
; enable long mode
|
||||
mov ecx, 0xC0000080 ; Set the C-register to 0xC0000080, which is the EFER MSR.
|
||||
rdmsr ; Read from the model-specific register.
|
||||
or eax, 1 << 8 ; Set the LM-bit which is the 9th bit (bit 8).
|
||||
wrmsr ; Write to the model-specific register.
|
||||
|
||||
; let cr3 point at page table
|
||||
mov eax, GET_PADDR(_pml4)
|
||||
mov cr3, eax
|
||||
|
||||
; enable paging, enter compatibility mode
|
||||
mov eax, cr0 ; Set the A-register to control register 0.
|
||||
or eax, 1 << 31 ; Set the PG-bit, which is bit 31.
|
||||
mov cr0, eax ; Set control register 0 to the A-register.
|
||||
|
||||
; enter long mode
|
||||
lgdt [GET_PADDR(_gdt.ptr)]
|
||||
jmp _gdt.code:GET_PADDR(halp_entry_64)
|
||||
hlt
|
||||
|
||||
halp_check_long_mode:
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 1 << 21
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
push ecx
|
||||
popfd
|
||||
xor eax, ecx
|
||||
jz .not_supported
|
||||
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
|
||||
cpuid ; CPU identification.
|
||||
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
|
||||
jb .not_supported ; It is less, there is no long mode.
|
||||
mov eax, 0x80000001 ; Set the A-register to 0x80000001.
|
||||
cpuid ; CPU identification.
|
||||
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
|
||||
jz .not_supported ; They aren't, there is no long mode.
|
||||
mov eax,1
|
||||
jmp .end
|
||||
.not_supported:
|
||||
xor eax,eax
|
||||
.end:
|
||||
mov esp,ebp
|
||||
pop ebp
|
||||
ret
|
||||
|
||||
section .text
|
||||
bits 64
|
||||
halp_entry_64:
|
||||
; note that we are still at the identity mapping
|
||||
mov ax,_gdt.data
|
||||
mov ds,ax
|
||||
mov es,ax
|
||||
mov fs,ax
|
||||
mov gs,ax
|
||||
mov ss,ax
|
||||
|
||||
mov rsp, GET_PADDR(_stack)
|
||||
mov rdi, rsi ; multiboot_info*
|
||||
call hal_write_initial_page_table
|
||||
test rax,rax
|
||||
jne .end
|
||||
call hal_main
|
||||
.end:
|
||||
hlt
|
||||
|
||||
section .data
|
||||
bits 64
|
||||
align KERNEL_PAGE_SIZE
|
||||
times KERNEL_PAGE_SIZE db 0
|
||||
_stack:
|
||||
|
||||
_pml4:
|
||||
align KERNEL_PAGE_SIZE
|
||||
times KERNEL_PAGE_SIZE db 0
|
||||
_pdpt:
|
||||
align KERNEL_PAGE_SIZE
|
||||
times KERNEL_PAGE_SIZE db 0
|
||||
_gdt: ; Global Descriptor Table (long mode).
|
||||
.null: equ $ - _gdt ; The null descriptor.
|
||||
dw 0 ; Limit (low).
|
||||
dw 0 ; Base (low).
|
||||
db 0 ; Base (middle)
|
||||
db 0 ; Access.
|
||||
db 0 ; Granularity.
|
||||
db 0 ; Base (high).
|
||||
.code: equ $ - _gdt ; The code descriptor.
|
||||
dw 0 ; Limit (low).
|
||||
dw 0 ; Base (low).
|
||||
db 0 ; Base (middle)
|
||||
db 10011010b ; Access (exec/read).
|
||||
db 00100000b ; Granularity.
|
||||
db 0 ; Base (high).
|
||||
.data: equ $ - _gdt ; The data descriptor.
|
||||
dw 0 ; Limit (low).
|
||||
dw 0 ; Base (low).
|
||||
db 0 ; Base (middle)
|
||||
db 10010010b ; Access (read/write).
|
||||
db 00000000b ; Granularity.
|
||||
db 0 ; Base (high).
|
||||
.ptr:
|
||||
; GDT PTR
|
||||
dw $ - _gdt - 1 ; Limit.
|
||||
dq GET_PADDR(_gdt) ; Base.
|
92
hal/boot.c
92
hal/boot.c
|
@ -1,47 +1,51 @@
|
|||
#include "hal/print.h"
|
||||
#include "hal/mem.h"
|
||||
#include "hal/intr.h"
|
||||
#include "hal/cpu.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
#include "hal/boot.h"
|
||||
#include "status.h"
|
||||
#include "print.h"
|
||||
#include "mem.h"
|
||||
#include "intr.h"
|
||||
#include "cpu.h"
|
||||
#include "call.h"
|
||||
#include "hal_export.h"
|
||||
|
||||
static void SXAPI halp_obtain_cpu_info(struct boot_info *hal_info)
|
||||
//static void
|
||||
//halp_obtain_cpu_info(struct boot_info *hal_info)
|
||||
//{
|
||||
// if (hal_info == NULL)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// uint32 eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
// hal_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
// mem_cpy(&ebx, &hal_info->cpu_vd_str[0], sizeof(uint32));
|
||||
// mem_cpy(&edx, &hal_info->cpu_vd_str[4], sizeof(uint32));
|
||||
// mem_cpy(&ecx, &hal_info->cpu_vd_str[8], sizeof(uint32));
|
||||
// hal_info->cpu_vd_str[12] = 0;
|
||||
//}
|
||||
|
||||
void HABI
|
||||
hal_main(void *m_info);
|
||||
|
||||
void HABI
|
||||
hal_main(void *m_info)
|
||||
{
|
||||
if (hal_info == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint32 eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
hal_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
lb_mem_copy(&ebx, &hal_info->cpu_vd_str[0], sizeof(uint32));
|
||||
lb_mem_copy(&edx, &hal_info->cpu_vd_str[4], sizeof(uint32));
|
||||
lb_mem_copy(&ecx, &hal_info->cpu_vd_str[8], sizeof(uint32));
|
||||
hal_info->cpu_vd_str[12] = 0;
|
||||
}
|
||||
|
||||
sx_status SXAPI hal_init(void *m_info)
|
||||
{
|
||||
if (m_info == NULL || (uint64) m_info & lb_bit_field_mask(0, 2))
|
||||
{
|
||||
return STATUS_FAIL;
|
||||
}
|
||||
|
||||
// init HAL infrastructures
|
||||
hal_print_init();
|
||||
hal_mem_init();
|
||||
|
||||
|
||||
struct boot_info *boot_info = halloc(sizeof(struct boot_info));
|
||||
|
||||
// obtain cpu info
|
||||
halp_obtain_cpu_info(boot_info);
|
||||
|
||||
// init interrupt
|
||||
if (hal_interrupt_init() != 0)
|
||||
{
|
||||
return STATUS_FAIL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
if (m_info == NULL || (uint64) m_info & bit_field_mask(0, 2))
|
||||
{
|
||||
hal_halt_cpu();
|
||||
}
|
||||
|
||||
// init HAL infrastructures
|
||||
hal_print_init();
|
||||
hal_mem_init();
|
||||
|
||||
|
||||
struct boot_info *boot_info = halloc(sizeof(struct boot_info));
|
||||
|
||||
// // obtain cpu info
|
||||
// halp_obtain_cpu_info(boot_info);
|
||||
|
||||
// init interrupt
|
||||
if (hal_interrupt_init() != 0)
|
||||
{
|
||||
hal_halt_cpu();
|
||||
}
|
||||
|
||||
ke_main(boot_info);
|
||||
}
|
||||
|
|
|
@ -85,10 +85,10 @@ mov eax, esi
|
|||
ret
|
||||
|
||||
; ============================
|
||||
; int32 KAPI hal_interlocked_compare_exchange_32(int32 *dst, int32 compare, int32 val);
|
||||
; int32 KAPI hal_interlocked_compare_exchange_32(int32 *dst, int32 test_node_compare, int32 val);
|
||||
global hal_interlocked_compare_exchange_32
|
||||
hal_interlocked_compare_exchange_32:
|
||||
mov eax, esi; eax = compare
|
||||
mov eax, esi; eax = test_node_compare
|
||||
lock cmpxchg dword [rdi], edx ; edx = val, rdi = ptr to dst
|
||||
ret
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define HAL_CORE_COUNT 1
|
||||
|
||||
|
||||
struct STRUCT_PACKED hal_gdt_ptr
|
||||
{
|
||||
uint16 limit;
|
||||
uint64 base;
|
||||
};
|
||||
|
||||
struct STRUCT_PACKED hal_idt_ptr
|
||||
{
|
||||
uint16 limit;
|
||||
uint64 base;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* CPU Instructions
|
||||
*/
|
||||
void HABI hal_cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx);
|
||||
|
||||
void HABI hal_halt_cpu(void);
|
||||
|
||||
void HABI hal_enable_interrupt(void);
|
||||
|
||||
void HABI hal_disable_interrupt(void);
|
||||
|
||||
|
||||
/**
|
||||
* IO Port Operations
|
||||
*/
|
||||
|
||||
int8 HABI hal_read_port_8(uint16 port);
|
||||
|
||||
int16 HABI hal_read_port_16(uint16 port);
|
||||
|
||||
int32 HABI hal_read_port_32(uint16 port);
|
||||
|
||||
void HABI hal_write_port_8(uint16 port, uint8 data);
|
||||
|
||||
void HABI hal_write_port_16(uint16 port, uint16 data);
|
||||
|
||||
void HABI hal_write_port_32(uint16 port, uint32 data);
|
||||
|
||||
|
||||
/**
|
||||
* CPU Structure Operations
|
||||
*/
|
||||
|
||||
void HABI hal_flush_gdt(struct hal_gdt_ptr *gdt_ptr, uint64 code_slct, uint64 data_slct);
|
||||
|
||||
void HABI hal_flush_tlb(void);
|
||||
|
||||
void HABI hal_flush_idt(struct hal_idt_ptr *idt_ptr);
|
||||
|
||||
void HABI hal_read_idt(struct hal_idt_ptr **idt_ptr);
|
||||
|
||||
/**
|
||||
* Control Register Operations
|
||||
*/
|
||||
#define MSR_IA32_APIC_BASE 0x1B
|
||||
|
||||
void HABI hal_read_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||
|
||||
void HABI hal_write_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||
|
||||
void HABI hal_write_cr3(uint64 base);
|
||||
|
||||
uint64 HABI hal_read_cr3(void);
|
||||
|
||||
void HABI hal_write_cr8(uint64 pri);
|
||||
|
||||
uint64 HABI hal_read_cr8(void);
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
#include "common.h"
|
||||
|
||||
#define HABI KABI
|
||||
|
||||
/**
|
||||
* ASM Functions
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* CPU Instructions
|
||||
*/
|
||||
void HABI hal_cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx);
|
||||
|
||||
void HABI hal_halt_cpu(void);
|
||||
|
||||
void HABI hal_enable_interrupt(void);
|
||||
|
||||
void HABI hal_disable_interrupt(void);
|
||||
|
||||
/**
|
||||
* IO Port Operations
|
||||
*/
|
||||
|
||||
int8 HABI hal_read_port_8(uint16 port);
|
||||
|
||||
int16 HABI hal_read_port_16(uint16 port);
|
||||
|
||||
int32 HABI hal_read_port_32(uint16 port);
|
||||
|
||||
void HABI hal_write_port_8(uint16 port, uint8 data);
|
||||
|
||||
void HABI hal_write_port_16(uint16 port, uint16 data);
|
||||
|
||||
void HABI hal_write_port_32(uint16 port, uint32 data);
|
||||
|
||||
|
||||
/**
|
||||
* CPU Structure Operations
|
||||
*/
|
||||
void HABI hal_flush_gdt(struct hal_gdt_ptr *gdt_ptr, uint64 code_slct, uint64 data_slct);
|
||||
|
||||
void HABI hal_flush_tlb(void);
|
||||
|
||||
void HABI hal_flush_idt(struct hal_idt_ptr *idt_ptr);
|
||||
|
||||
void HABI hal_read_idt(struct hal_idt_ptr **idt_ptr);
|
||||
|
||||
/**
|
||||
* Control Register Operations
|
||||
*/
|
||||
#define MSR_IA32_APIC_BASE 0x1B
|
||||
|
||||
void HABI hal_read_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||
|
||||
void HABI hal_write_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||
|
||||
void HABI hal_write_cr3(uint64 base);
|
||||
|
||||
uint64 HABI hal_read_cr3(void);
|
||||
|
||||
void HABI hal_write_cr8(uint64 pri);
|
||||
|
||||
uint64 HABI hal_read_cr8(void);
|
||||
|
||||
|
||||
#define HAL_CORE_COUNT 1
|
||||
|
||||
|
||||
struct STRUCT_PACKED hal_gdt_ptr
|
||||
{
|
||||
uint16 limit;
|
||||
uint64 base;
|
||||
};
|
||||
|
||||
struct STRUCT_PACKED hal_idt_ptr
|
||||
{
|
||||
uint16 limit;
|
||||
uint64 base;
|
||||
};
|
805
hal/intr.c
805
hal/intr.c
|
@ -1,453 +1,474 @@
|
|||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/intr.h"
|
||||
#include "hal/cpu.h"
|
||||
#include "hal/intr.h"
|
||||
#include "hal/print.h"
|
||||
#include "hal/mem.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
#include "common.h"
|
||||
#include "intr.h"
|
||||
#include "cpu.h"
|
||||
#include "intr.h"
|
||||
#include "print.h"
|
||||
#include "mem.h"
|
||||
#include "hal_export.h"
|
||||
|
||||
static uint8 _idts[HAL_CORE_COUNT][IDT_ENTRY_NUM * IDT_ENTRY_SIZE];
|
||||
static struct hal_idt_ptr _idt_ptrs[HAL_CORE_COUNT];
|
||||
static intr_handler _intr_handler_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
|
||||
static intr_handler_fp _intr_handler_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
|
||||
static void *_intr_handler_context_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
|
||||
static exc_handler _exc_handler_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
|
||||
static exc_handler_fp _exc_handler_table[HAL_CORE_COUNT][IDT_ENTRY_NUM];
|
||||
|
||||
k_irql SXAPI hal_set_irql(k_irql irql)
|
||||
uint32
|
||||
hal_set_irql(uint32 irql)
|
||||
{
|
||||
UNREFERENCED(irql)
|
||||
hal_assert(FALSE, "Unimplemented function called.");
|
||||
return 0;
|
||||
UNREFERENCED(irql)
|
||||
hal_assert(FALSE, "Unimplemented function called.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
k_irql SXAPI hal_get_irql(void)
|
||||
uint32
|
||||
hal_get_irql(void)
|
||||
{
|
||||
hal_assert(FALSE, "Unimplemented function called.");
|
||||
return 0;
|
||||
hal_assert(FALSE, "Unimplemented function called.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SXAPI hal_write_gate(void *const gate,
|
||||
uint64 const offset,
|
||||
uint32 const selector,
|
||||
uint32 const attr)
|
||||
void
|
||||
hal_write_gate(void *const gate, uint64 const offset, uint32 const selector, uint32 const attr)
|
||||
{
|
||||
((uint8 *) gate)[0] = (uint8) (offset & 0xFF);
|
||||
((uint8 *) gate)[1] = (uint8) ((offset >> 8) & 0xFF);
|
||||
((uint8 *) gate)[2] = (uint8) (selector & 0xFF);
|
||||
((uint8 *) gate)[3] = (uint8) ((selector >> 8) & 0xFF);
|
||||
((uint8 *) gate)[4] = (uint8) (attr & 0xFF);
|
||||
((uint8 *) gate)[5] = (uint8) ((attr >> 8) & 0xFF);
|
||||
((uint8 *) gate)[6] = (uint8) ((offset >> 16) & 0xFF);
|
||||
((uint8 *) gate)[7] = (uint8) ((offset >> 24) & 0xFF);
|
||||
((uint8 *) gate)[8] = (uint8) ((offset >> 32) & 0xFF);
|
||||
((uint8 *) gate)[9] = (uint8) ((offset >> 40) & 0xFF);
|
||||
((uint8 *) gate)[10] = (uint8) ((offset >> 48) & 0xFF);
|
||||
((uint8 *) gate)[11] = (uint8) ((offset >> 56) & 0xFF);
|
||||
((uint8 *) gate)[12] = 0;
|
||||
((uint8 *) gate)[13] = 0;
|
||||
((uint8 *) gate)[14] = 0;
|
||||
((uint8 *) gate)[15] = 0;
|
||||
((uint8 *) gate)[0] = (uint8) (offset & 0xFF);
|
||||
((uint8 *) gate)[1] = (uint8) ((offset >> 8) & 0xFF);
|
||||
((uint8 *) gate)[2] = (uint8) (selector & 0xFF);
|
||||
((uint8 *) gate)[3] = (uint8) ((selector >> 8) & 0xFF);
|
||||
((uint8 *) gate)[4] = (uint8) (attr & 0xFF);
|
||||
((uint8 *) gate)[5] = (uint8) ((attr >> 8) & 0xFF);
|
||||
((uint8 *) gate)[6] = (uint8) ((offset >> 16) & 0xFF);
|
||||
((uint8 *) gate)[7] = (uint8) ((offset >> 24) & 0xFF);
|
||||
((uint8 *) gate)[8] = (uint8) ((offset >> 32) & 0xFF);
|
||||
((uint8 *) gate)[9] = (uint8) ((offset >> 40) & 0xFF);
|
||||
((uint8 *) gate)[10] = (uint8) ((offset >> 48) & 0xFF);
|
||||
((uint8 *) gate)[11] = (uint8) ((offset >> 56) & 0xFF);
|
||||
((uint8 *) gate)[12] = 0;
|
||||
((uint8 *) gate)[13] = 0;
|
||||
((uint8 *) gate)[14] = 0;
|
||||
((uint8 *) gate)[15] = 0;
|
||||
}
|
||||
|
||||
void SXAPI hal_set_interrupt_handler(uint64 index,
|
||||
void (*handler)(void))
|
||||
void
|
||||
hal_set_interrupt_handler(uint64 index, void (*handler)(void))
|
||||
{
|
||||
if (index < IDT_ENTRY_NUM)
|
||||
{
|
||||
hal_write_gate(_idts[hal_get_core_id()] + 16 * index, (uintptr) handler, seg_selector(1, 0),
|
||||
GATE_DPL_0 | GATE_PRESENT | GATE_TYPE_INTERRUPT);
|
||||
}
|
||||
if (index < IDT_ENTRY_NUM)
|
||||
{
|
||||
hal_write_gate(_idts[hal_get_core_id()] + 16 * index, (uintptr) handler, seg_selector(1, 0),
|
||||
GATE_DPL_0 | GATE_PRESENT | GATE_TYPE_INTERRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI hal_issue_interrupt(uint32 target_core, uint32 vector)
|
||||
void KABI
|
||||
hal_issue_intr(uint32 target_core, uint32 vector)
|
||||
{
|
||||
UNREFERENCED(target_core);
|
||||
UNREFERENCED(vector);
|
||||
hal_assert(FALSE, "Unimplemented function called.");
|
||||
UNREFERENCED(target_core);
|
||||
UNREFERENCED(vector);
|
||||
hal_assert(FALSE, "Unimplemented function called.");
|
||||
}
|
||||
|
||||
void SXAPI hal_register_interrupt_handler(uint32 coreid, uint32 index, intr_handler handler, void *context)
|
||||
void
|
||||
hal_reg_intr(uint32 index, intr_handler_fp handler)
|
||||
{
|
||||
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
|
||||
{
|
||||
_intr_handler_table[coreid][index] = handler;
|
||||
_intr_handler_context_table[coreid][index] = context;
|
||||
}
|
||||
// TODO: FIX CONTEXT
|
||||
|
||||
if (index < IDT_ENTRY_NUM && hal_get_core_id() < HAL_CORE_COUNT)
|
||||
{
|
||||
_intr_handler_table[hal_get_core_id()][index] = handler;
|
||||
_intr_handler_context_table[hal_get_core_id()][index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI hal_deregister_interrupt_handler(uint32 coreid, uint32 index)
|
||||
void
|
||||
hal_dereg_intr(uint32 index)
|
||||
{
|
||||
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
|
||||
{
|
||||
_intr_handler_table[coreid][index] = NULL;
|
||||
}
|
||||
// TODO: FIX CONTEXT
|
||||
if (index < IDT_ENTRY_NUM && hal_get_core_id() < HAL_CORE_COUNT)
|
||||
{
|
||||
_intr_handler_table[hal_get_core_id()][index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI hal_register_exception_handler(uint32 coreid, uint32 index, exc_handler handler)
|
||||
|
||||
void
|
||||
hal_reg_exc(uint32 index, exc_handler_fp handler)
|
||||
{
|
||||
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
|
||||
{
|
||||
_exc_handler_table[coreid][index] = handler;
|
||||
}
|
||||
if (index < IDT_ENTRY_NUM && hal_get_core_id() < HAL_CORE_COUNT)
|
||||
{
|
||||
_exc_handler_table[hal_get_core_id()][index] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI hal_deregister_exception_handler(uint32 coreid, uint32 index)
|
||||
|
||||
void
|
||||
hal_dereg_exc(uint32 index)
|
||||
{
|
||||
if (index < IDT_ENTRY_NUM && coreid < HAL_CORE_COUNT)
|
||||
{
|
||||
_exc_handler_table[coreid][index] = NULL;
|
||||
}
|
||||
if (index < IDT_ENTRY_NUM && hal_get_core_id() < HAL_CORE_COUNT)
|
||||
{
|
||||
_exc_handler_table[hal_get_core_id()][index] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI hal_interrupt_dispatcher(uint64 int_vec, hal_interrupt_context_t *context)
|
||||
void KABI
|
||||
hal_halt(void)
|
||||
{
|
||||
uint32 coreid = hal_get_core_id();
|
||||
if (_intr_handler_table[int_vec] == NULL)
|
||||
{
|
||||
hal_printf("Unhandled interrupt %d at 0x%X.\n", int_vec, context->rip);
|
||||
}
|
||||
else
|
||||
{
|
||||
_intr_handler_table[coreid][int_vec](context, _intr_handler_context_table[coreid][int_vec]);
|
||||
}
|
||||
hal_halt_cpu();
|
||||
}
|
||||
|
||||
void SXAPI hal_exception_dispatcher(uint64 exc_vec, hal_interrupt_context_t *context, uint64 errorcode)
|
||||
void HABI
|
||||
hal_interrupt_dispatcher(uint64 int_vec, hal_interrupt_context_t *context)
|
||||
{
|
||||
uint32 coreid = hal_get_core_id();
|
||||
if (_exc_handler_table[exc_vec] == NULL)
|
||||
{
|
||||
hal_printf("Unhandled exception %d at 0x%X.\n", exc_vec, context->rip);
|
||||
}
|
||||
else
|
||||
{
|
||||
_exc_handler_table[coreid][exc_vec](context->rip, context->rsp, errorcode);
|
||||
}
|
||||
uint32 coreid = hal_get_core_id();
|
||||
if (_intr_handler_table[int_vec] == NULL)
|
||||
{
|
||||
hal_printf("Unhandled interrupt %d at 0x%X.\n", int_vec, context->rip);
|
||||
}
|
||||
else
|
||||
{
|
||||
_intr_handler_table[coreid][int_vec](context->rip, context->rsp, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void SXAPI halp_populate_idt(void)
|
||||
void HABI
|
||||
hal_exception_dispatcher(uint64 exc_vec, hal_interrupt_context_t *context, uint32 errorcode)
|
||||
{
|
||||
hal_set_interrupt_handler(0, hal_interrupt_handler_0);
|
||||
hal_set_interrupt_handler(1, hal_interrupt_handler_1);
|
||||
hal_set_interrupt_handler(2, hal_interrupt_handler_2);
|
||||
hal_set_interrupt_handler(3, hal_interrupt_handler_3);
|
||||
hal_set_interrupt_handler(4, hal_interrupt_handler_4);
|
||||
hal_set_interrupt_handler(5, hal_interrupt_handler_5);
|
||||
hal_set_interrupt_handler(6, hal_interrupt_handler_6);
|
||||
hal_set_interrupt_handler(7, hal_interrupt_handler_7);
|
||||
hal_set_interrupt_handler(8, hal_interrupt_handler_8);
|
||||
hal_set_interrupt_handler(9, hal_interrupt_handler_9);
|
||||
hal_set_interrupt_handler(10, hal_interrupt_handler_10);
|
||||
hal_set_interrupt_handler(11, hal_interrupt_handler_11);
|
||||
hal_set_interrupt_handler(12, hal_interrupt_handler_12);
|
||||
hal_set_interrupt_handler(13, hal_interrupt_handler_13);
|
||||
hal_set_interrupt_handler(14, hal_interrupt_handler_14);
|
||||
hal_set_interrupt_handler(15, hal_interrupt_handler_15);
|
||||
hal_set_interrupt_handler(16, hal_interrupt_handler_16);
|
||||
hal_set_interrupt_handler(17, hal_interrupt_handler_17);
|
||||
hal_set_interrupt_handler(18, hal_interrupt_handler_18);
|
||||
hal_set_interrupt_handler(19, hal_interrupt_handler_19);
|
||||
hal_set_interrupt_handler(20, hal_interrupt_handler_20);
|
||||
hal_set_interrupt_handler(21, hal_interrupt_handler_21);
|
||||
hal_set_interrupt_handler(22, hal_interrupt_handler_22);
|
||||
hal_set_interrupt_handler(23, hal_interrupt_handler_23);
|
||||
hal_set_interrupt_handler(24, hal_interrupt_handler_24);
|
||||
hal_set_interrupt_handler(25, hal_interrupt_handler_25);
|
||||
hal_set_interrupt_handler(26, hal_interrupt_handler_26);
|
||||
hal_set_interrupt_handler(27, hal_interrupt_handler_27);
|
||||
hal_set_interrupt_handler(28, hal_interrupt_handler_28);
|
||||
hal_set_interrupt_handler(29, hal_interrupt_handler_29);
|
||||
hal_set_interrupt_handler(30, hal_interrupt_handler_30);
|
||||
hal_set_interrupt_handler(31, hal_interrupt_handler_31);
|
||||
hal_set_interrupt_handler(32, hal_interrupt_handler_32);
|
||||
hal_set_interrupt_handler(33, hal_interrupt_handler_33);
|
||||
hal_set_interrupt_handler(34, hal_interrupt_handler_34);
|
||||
hal_set_interrupt_handler(35, hal_interrupt_handler_35);
|
||||
hal_set_interrupt_handler(36, hal_interrupt_handler_36);
|
||||
hal_set_interrupt_handler(37, hal_interrupt_handler_37);
|
||||
hal_set_interrupt_handler(38, hal_interrupt_handler_38);
|
||||
hal_set_interrupt_handler(39, hal_interrupt_handler_39);
|
||||
hal_set_interrupt_handler(40, hal_interrupt_handler_40);
|
||||
hal_set_interrupt_handler(41, hal_interrupt_handler_41);
|
||||
hal_set_interrupt_handler(42, hal_interrupt_handler_42);
|
||||
hal_set_interrupt_handler(43, hal_interrupt_handler_43);
|
||||
hal_set_interrupt_handler(44, hal_interrupt_handler_44);
|
||||
hal_set_interrupt_handler(45, hal_interrupt_handler_45);
|
||||
hal_set_interrupt_handler(46, hal_interrupt_handler_46);
|
||||
hal_set_interrupt_handler(47, hal_interrupt_handler_47);
|
||||
hal_set_interrupt_handler(48, hal_interrupt_handler_48);
|
||||
hal_set_interrupt_handler(49, hal_interrupt_handler_49);
|
||||
hal_set_interrupt_handler(50, hal_interrupt_handler_50);
|
||||
hal_set_interrupt_handler(51, hal_interrupt_handler_51);
|
||||
hal_set_interrupt_handler(52, hal_interrupt_handler_52);
|
||||
hal_set_interrupt_handler(53, hal_interrupt_handler_53);
|
||||
hal_set_interrupt_handler(54, hal_interrupt_handler_54);
|
||||
hal_set_interrupt_handler(55, hal_interrupt_handler_55);
|
||||
hal_set_interrupt_handler(56, hal_interrupt_handler_56);
|
||||
hal_set_interrupt_handler(57, hal_interrupt_handler_57);
|
||||
hal_set_interrupt_handler(58, hal_interrupt_handler_58);
|
||||
hal_set_interrupt_handler(59, hal_interrupt_handler_59);
|
||||
hal_set_interrupt_handler(60, hal_interrupt_handler_60);
|
||||
hal_set_interrupt_handler(61, hal_interrupt_handler_61);
|
||||
hal_set_interrupt_handler(62, hal_interrupt_handler_62);
|
||||
hal_set_interrupt_handler(63, hal_interrupt_handler_63);
|
||||
hal_set_interrupt_handler(64, hal_interrupt_handler_64);
|
||||
hal_set_interrupt_handler(65, hal_interrupt_handler_65);
|
||||
hal_set_interrupt_handler(66, hal_interrupt_handler_66);
|
||||
hal_set_interrupt_handler(67, hal_interrupt_handler_67);
|
||||
hal_set_interrupt_handler(68, hal_interrupt_handler_68);
|
||||
hal_set_interrupt_handler(69, hal_interrupt_handler_69);
|
||||
hal_set_interrupt_handler(70, hal_interrupt_handler_70);
|
||||
hal_set_interrupt_handler(71, hal_interrupt_handler_71);
|
||||
hal_set_interrupt_handler(72, hal_interrupt_handler_72);
|
||||
hal_set_interrupt_handler(73, hal_interrupt_handler_73);
|
||||
hal_set_interrupt_handler(74, hal_interrupt_handler_74);
|
||||
hal_set_interrupt_handler(75, hal_interrupt_handler_75);
|
||||
hal_set_interrupt_handler(76, hal_interrupt_handler_76);
|
||||
hal_set_interrupt_handler(77, hal_interrupt_handler_77);
|
||||
hal_set_interrupt_handler(78, hal_interrupt_handler_78);
|
||||
hal_set_interrupt_handler(79, hal_interrupt_handler_79);
|
||||
hal_set_interrupt_handler(80, hal_interrupt_handler_80);
|
||||
hal_set_interrupt_handler(81, hal_interrupt_handler_81);
|
||||
hal_set_interrupt_handler(82, hal_interrupt_handler_82);
|
||||
hal_set_interrupt_handler(83, hal_interrupt_handler_83);
|
||||
hal_set_interrupt_handler(84, hal_interrupt_handler_84);
|
||||
hal_set_interrupt_handler(85, hal_interrupt_handler_85);
|
||||
hal_set_interrupt_handler(86, hal_interrupt_handler_86);
|
||||
hal_set_interrupt_handler(87, hal_interrupt_handler_87);
|
||||
hal_set_interrupt_handler(88, hal_interrupt_handler_88);
|
||||
hal_set_interrupt_handler(89, hal_interrupt_handler_89);
|
||||
hal_set_interrupt_handler(90, hal_interrupt_handler_90);
|
||||
hal_set_interrupt_handler(91, hal_interrupt_handler_91);
|
||||
hal_set_interrupt_handler(92, hal_interrupt_handler_92);
|
||||
hal_set_interrupt_handler(93, hal_interrupt_handler_93);
|
||||
hal_set_interrupt_handler(94, hal_interrupt_handler_94);
|
||||
hal_set_interrupt_handler(95, hal_interrupt_handler_95);
|
||||
hal_set_interrupt_handler(96, hal_interrupt_handler_96);
|
||||
hal_set_interrupt_handler(97, hal_interrupt_handler_97);
|
||||
hal_set_interrupt_handler(98, hal_interrupt_handler_98);
|
||||
hal_set_interrupt_handler(99, hal_interrupt_handler_99);
|
||||
hal_set_interrupt_handler(100, hal_interrupt_handler_100);
|
||||
hal_set_interrupt_handler(101, hal_interrupt_handler_101);
|
||||
hal_set_interrupt_handler(102, hal_interrupt_handler_102);
|
||||
hal_set_interrupt_handler(103, hal_interrupt_handler_103);
|
||||
hal_set_interrupt_handler(104, hal_interrupt_handler_104);
|
||||
hal_set_interrupt_handler(105, hal_interrupt_handler_105);
|
||||
hal_set_interrupt_handler(106, hal_interrupt_handler_106);
|
||||
hal_set_interrupt_handler(107, hal_interrupt_handler_107);
|
||||
hal_set_interrupt_handler(108, hal_interrupt_handler_108);
|
||||
hal_set_interrupt_handler(109, hal_interrupt_handler_109);
|
||||
hal_set_interrupt_handler(110, hal_interrupt_handler_110);
|
||||
hal_set_interrupt_handler(111, hal_interrupt_handler_111);
|
||||
hal_set_interrupt_handler(112, hal_interrupt_handler_112);
|
||||
hal_set_interrupt_handler(113, hal_interrupt_handler_113);
|
||||
hal_set_interrupt_handler(114, hal_interrupt_handler_114);
|
||||
hal_set_interrupt_handler(115, hal_interrupt_handler_115);
|
||||
hal_set_interrupt_handler(116, hal_interrupt_handler_116);
|
||||
hal_set_interrupt_handler(117, hal_interrupt_handler_117);
|
||||
hal_set_interrupt_handler(118, hal_interrupt_handler_118);
|
||||
hal_set_interrupt_handler(119, hal_interrupt_handler_119);
|
||||
hal_set_interrupt_handler(120, hal_interrupt_handler_120);
|
||||
hal_set_interrupt_handler(121, hal_interrupt_handler_121);
|
||||
hal_set_interrupt_handler(122, hal_interrupt_handler_122);
|
||||
hal_set_interrupt_handler(123, hal_interrupt_handler_123);
|
||||
hal_set_interrupt_handler(124, hal_interrupt_handler_124);
|
||||
hal_set_interrupt_handler(125, hal_interrupt_handler_125);
|
||||
hal_set_interrupt_handler(126, hal_interrupt_handler_126);
|
||||
hal_set_interrupt_handler(127, hal_interrupt_handler_127);
|
||||
hal_set_interrupt_handler(128, hal_interrupt_handler_128);
|
||||
hal_set_interrupt_handler(129, hal_interrupt_handler_129);
|
||||
hal_set_interrupt_handler(130, hal_interrupt_handler_130);
|
||||
hal_set_interrupt_handler(131, hal_interrupt_handler_131);
|
||||
hal_set_interrupt_handler(132, hal_interrupt_handler_132);
|
||||
hal_set_interrupt_handler(133, hal_interrupt_handler_133);
|
||||
hal_set_interrupt_handler(134, hal_interrupt_handler_134);
|
||||
hal_set_interrupt_handler(135, hal_interrupt_handler_135);
|
||||
hal_set_interrupt_handler(136, hal_interrupt_handler_136);
|
||||
hal_set_interrupt_handler(137, hal_interrupt_handler_137);
|
||||
hal_set_interrupt_handler(138, hal_interrupt_handler_138);
|
||||
hal_set_interrupt_handler(139, hal_interrupt_handler_139);
|
||||
hal_set_interrupt_handler(140, hal_interrupt_handler_140);
|
||||
hal_set_interrupt_handler(141, hal_interrupt_handler_141);
|
||||
hal_set_interrupt_handler(142, hal_interrupt_handler_142);
|
||||
hal_set_interrupt_handler(143, hal_interrupt_handler_143);
|
||||
hal_set_interrupt_handler(144, hal_interrupt_handler_144);
|
||||
hal_set_interrupt_handler(145, hal_interrupt_handler_145);
|
||||
hal_set_interrupt_handler(146, hal_interrupt_handler_146);
|
||||
hal_set_interrupt_handler(147, hal_interrupt_handler_147);
|
||||
hal_set_interrupt_handler(148, hal_interrupt_handler_148);
|
||||
hal_set_interrupt_handler(149, hal_interrupt_handler_149);
|
||||
hal_set_interrupt_handler(150, hal_interrupt_handler_150);
|
||||
hal_set_interrupt_handler(151, hal_interrupt_handler_151);
|
||||
hal_set_interrupt_handler(152, hal_interrupt_handler_152);
|
||||
hal_set_interrupt_handler(153, hal_interrupt_handler_153);
|
||||
hal_set_interrupt_handler(154, hal_interrupt_handler_154);
|
||||
hal_set_interrupt_handler(155, hal_interrupt_handler_155);
|
||||
hal_set_interrupt_handler(156, hal_interrupt_handler_156);
|
||||
hal_set_interrupt_handler(157, hal_interrupt_handler_157);
|
||||
hal_set_interrupt_handler(158, hal_interrupt_handler_158);
|
||||
hal_set_interrupt_handler(159, hal_interrupt_handler_159);
|
||||
hal_set_interrupt_handler(160, hal_interrupt_handler_160);
|
||||
hal_set_interrupt_handler(161, hal_interrupt_handler_161);
|
||||
hal_set_interrupt_handler(162, hal_interrupt_handler_162);
|
||||
hal_set_interrupt_handler(163, hal_interrupt_handler_163);
|
||||
hal_set_interrupt_handler(164, hal_interrupt_handler_164);
|
||||
hal_set_interrupt_handler(165, hal_interrupt_handler_165);
|
||||
hal_set_interrupt_handler(166, hal_interrupt_handler_166);
|
||||
hal_set_interrupt_handler(167, hal_interrupt_handler_167);
|
||||
hal_set_interrupt_handler(168, hal_interrupt_handler_168);
|
||||
hal_set_interrupt_handler(169, hal_interrupt_handler_169);
|
||||
hal_set_interrupt_handler(170, hal_interrupt_handler_170);
|
||||
hal_set_interrupt_handler(171, hal_interrupt_handler_171);
|
||||
hal_set_interrupt_handler(172, hal_interrupt_handler_172);
|
||||
hal_set_interrupt_handler(173, hal_interrupt_handler_173);
|
||||
hal_set_interrupt_handler(174, hal_interrupt_handler_174);
|
||||
hal_set_interrupt_handler(175, hal_interrupt_handler_175);
|
||||
hal_set_interrupt_handler(176, hal_interrupt_handler_176);
|
||||
hal_set_interrupt_handler(177, hal_interrupt_handler_177);
|
||||
hal_set_interrupt_handler(178, hal_interrupt_handler_178);
|
||||
hal_set_interrupt_handler(179, hal_interrupt_handler_179);
|
||||
hal_set_interrupt_handler(180, hal_interrupt_handler_180);
|
||||
hal_set_interrupt_handler(181, hal_interrupt_handler_181);
|
||||
hal_set_interrupt_handler(182, hal_interrupt_handler_182);
|
||||
hal_set_interrupt_handler(183, hal_interrupt_handler_183);
|
||||
hal_set_interrupt_handler(184, hal_interrupt_handler_184);
|
||||
hal_set_interrupt_handler(185, hal_interrupt_handler_185);
|
||||
hal_set_interrupt_handler(186, hal_interrupt_handler_186);
|
||||
hal_set_interrupt_handler(187, hal_interrupt_handler_187);
|
||||
hal_set_interrupt_handler(188, hal_interrupt_handler_188);
|
||||
hal_set_interrupt_handler(189, hal_interrupt_handler_189);
|
||||
hal_set_interrupt_handler(190, hal_interrupt_handler_190);
|
||||
hal_set_interrupt_handler(191, hal_interrupt_handler_191);
|
||||
hal_set_interrupt_handler(192, hal_interrupt_handler_192);
|
||||
hal_set_interrupt_handler(193, hal_interrupt_handler_193);
|
||||
hal_set_interrupt_handler(194, hal_interrupt_handler_194);
|
||||
hal_set_interrupt_handler(195, hal_interrupt_handler_195);
|
||||
hal_set_interrupt_handler(196, hal_interrupt_handler_196);
|
||||
hal_set_interrupt_handler(197, hal_interrupt_handler_197);
|
||||
hal_set_interrupt_handler(198, hal_interrupt_handler_198);
|
||||
hal_set_interrupt_handler(199, hal_interrupt_handler_199);
|
||||
hal_set_interrupt_handler(200, hal_interrupt_handler_200);
|
||||
hal_set_interrupt_handler(201, hal_interrupt_handler_201);
|
||||
hal_set_interrupt_handler(202, hal_interrupt_handler_202);
|
||||
hal_set_interrupt_handler(203, hal_interrupt_handler_203);
|
||||
hal_set_interrupt_handler(204, hal_interrupt_handler_204);
|
||||
hal_set_interrupt_handler(205, hal_interrupt_handler_205);
|
||||
hal_set_interrupt_handler(206, hal_interrupt_handler_206);
|
||||
hal_set_interrupt_handler(207, hal_interrupt_handler_207);
|
||||
hal_set_interrupt_handler(208, hal_interrupt_handler_208);
|
||||
hal_set_interrupt_handler(209, hal_interrupt_handler_209);
|
||||
hal_set_interrupt_handler(210, hal_interrupt_handler_210);
|
||||
hal_set_interrupt_handler(211, hal_interrupt_handler_211);
|
||||
hal_set_interrupt_handler(212, hal_interrupt_handler_212);
|
||||
hal_set_interrupt_handler(213, hal_interrupt_handler_213);
|
||||
hal_set_interrupt_handler(214, hal_interrupt_handler_214);
|
||||
hal_set_interrupt_handler(215, hal_interrupt_handler_215);
|
||||
hal_set_interrupt_handler(216, hal_interrupt_handler_216);
|
||||
hal_set_interrupt_handler(217, hal_interrupt_handler_217);
|
||||
hal_set_interrupt_handler(218, hal_interrupt_handler_218);
|
||||
hal_set_interrupt_handler(219, hal_interrupt_handler_219);
|
||||
hal_set_interrupt_handler(220, hal_interrupt_handler_220);
|
||||
hal_set_interrupt_handler(221, hal_interrupt_handler_221);
|
||||
hal_set_interrupt_handler(222, hal_interrupt_handler_222);
|
||||
hal_set_interrupt_handler(223, hal_interrupt_handler_223);
|
||||
hal_set_interrupt_handler(224, hal_interrupt_handler_224);
|
||||
hal_set_interrupt_handler(225, hal_interrupt_handler_225);
|
||||
hal_set_interrupt_handler(226, hal_interrupt_handler_226);
|
||||
hal_set_interrupt_handler(227, hal_interrupt_handler_227);
|
||||
hal_set_interrupt_handler(228, hal_interrupt_handler_228);
|
||||
hal_set_interrupt_handler(229, hal_interrupt_handler_229);
|
||||
hal_set_interrupt_handler(230, hal_interrupt_handler_230);
|
||||
hal_set_interrupt_handler(231, hal_interrupt_handler_231);
|
||||
hal_set_interrupt_handler(232, hal_interrupt_handler_232);
|
||||
hal_set_interrupt_handler(233, hal_interrupt_handler_233);
|
||||
hal_set_interrupt_handler(234, hal_interrupt_handler_234);
|
||||
hal_set_interrupt_handler(235, hal_interrupt_handler_235);
|
||||
hal_set_interrupt_handler(236, hal_interrupt_handler_236);
|
||||
hal_set_interrupt_handler(237, hal_interrupt_handler_237);
|
||||
hal_set_interrupt_handler(238, hal_interrupt_handler_238);
|
||||
hal_set_interrupt_handler(239, hal_interrupt_handler_239);
|
||||
hal_set_interrupt_handler(240, hal_interrupt_handler_240);
|
||||
hal_set_interrupt_handler(241, hal_interrupt_handler_241);
|
||||
hal_set_interrupt_handler(242, hal_interrupt_handler_242);
|
||||
hal_set_interrupt_handler(243, hal_interrupt_handler_243);
|
||||
hal_set_interrupt_handler(244, hal_interrupt_handler_244);
|
||||
hal_set_interrupt_handler(245, hal_interrupt_handler_245);
|
||||
hal_set_interrupt_handler(246, hal_interrupt_handler_246);
|
||||
hal_set_interrupt_handler(247, hal_interrupt_handler_247);
|
||||
hal_set_interrupt_handler(248, hal_interrupt_handler_248);
|
||||
hal_set_interrupt_handler(249, hal_interrupt_handler_249);
|
||||
hal_set_interrupt_handler(250, hal_interrupt_handler_250);
|
||||
hal_set_interrupt_handler(251, hal_interrupt_handler_251);
|
||||
hal_set_interrupt_handler(252, hal_interrupt_handler_252);
|
||||
hal_set_interrupt_handler(253, hal_interrupt_handler_253);
|
||||
hal_set_interrupt_handler(254, hal_interrupt_handler_254);
|
||||
hal_set_interrupt_handler(255, hal_interrupt_handler_255);
|
||||
uint32 coreid = hal_get_core_id();
|
||||
if (_exc_handler_table[exc_vec] == NULL)
|
||||
{
|
||||
hal_printf("Unhandled exception %d at 0x%X.\n", exc_vec, context->rip);
|
||||
}
|
||||
else
|
||||
{
|
||||
_exc_handler_table[coreid][exc_vec](context->rip, context->rsp, errorcode);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 SXAPI hal_get_core_id(void)
|
||||
static void
|
||||
halp_populate_idt(void)
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
hal_set_interrupt_handler(0, hal_interrupt_handler_0);
|
||||
hal_set_interrupt_handler(1, hal_interrupt_handler_1);
|
||||
hal_set_interrupt_handler(2, hal_interrupt_handler_2);
|
||||
hal_set_interrupt_handler(3, hal_interrupt_handler_3);
|
||||
hal_set_interrupt_handler(4, hal_interrupt_handler_4);
|
||||
hal_set_interrupt_handler(5, hal_interrupt_handler_5);
|
||||
hal_set_interrupt_handler(6, hal_interrupt_handler_6);
|
||||
hal_set_interrupt_handler(7, hal_interrupt_handler_7);
|
||||
hal_set_interrupt_handler(8, hal_interrupt_handler_8);
|
||||
hal_set_interrupt_handler(9, hal_interrupt_handler_9);
|
||||
hal_set_interrupt_handler(10, hal_interrupt_handler_10);
|
||||
hal_set_interrupt_handler(11, hal_interrupt_handler_11);
|
||||
hal_set_interrupt_handler(12, hal_interrupt_handler_12);
|
||||
hal_set_interrupt_handler(13, hal_interrupt_handler_13);
|
||||
hal_set_interrupt_handler(14, hal_interrupt_handler_14);
|
||||
hal_set_interrupt_handler(15, hal_interrupt_handler_15);
|
||||
hal_set_interrupt_handler(16, hal_interrupt_handler_16);
|
||||
hal_set_interrupt_handler(17, hal_interrupt_handler_17);
|
||||
hal_set_interrupt_handler(18, hal_interrupt_handler_18);
|
||||
hal_set_interrupt_handler(19, hal_interrupt_handler_19);
|
||||
hal_set_interrupt_handler(20, hal_interrupt_handler_20);
|
||||
hal_set_interrupt_handler(21, hal_interrupt_handler_21);
|
||||
hal_set_interrupt_handler(22, hal_interrupt_handler_22);
|
||||
hal_set_interrupt_handler(23, hal_interrupt_handler_23);
|
||||
hal_set_interrupt_handler(24, hal_interrupt_handler_24);
|
||||
hal_set_interrupt_handler(25, hal_interrupt_handler_25);
|
||||
hal_set_interrupt_handler(26, hal_interrupt_handler_26);
|
||||
hal_set_interrupt_handler(27, hal_interrupt_handler_27);
|
||||
hal_set_interrupt_handler(28, hal_interrupt_handler_28);
|
||||
hal_set_interrupt_handler(29, hal_interrupt_handler_29);
|
||||
hal_set_interrupt_handler(30, hal_interrupt_handler_30);
|
||||
hal_set_interrupt_handler(31, hal_interrupt_handler_31);
|
||||
hal_set_interrupt_handler(32, hal_interrupt_handler_32);
|
||||
hal_set_interrupt_handler(33, hal_interrupt_handler_33);
|
||||
hal_set_interrupt_handler(34, hal_interrupt_handler_34);
|
||||
hal_set_interrupt_handler(35, hal_interrupt_handler_35);
|
||||
hal_set_interrupt_handler(36, hal_interrupt_handler_36);
|
||||
hal_set_interrupt_handler(37, hal_interrupt_handler_37);
|
||||
hal_set_interrupt_handler(38, hal_interrupt_handler_38);
|
||||
hal_set_interrupt_handler(39, hal_interrupt_handler_39);
|
||||
hal_set_interrupt_handler(40, hal_interrupt_handler_40);
|
||||
hal_set_interrupt_handler(41, hal_interrupt_handler_41);
|
||||
hal_set_interrupt_handler(42, hal_interrupt_handler_42);
|
||||
hal_set_interrupt_handler(43, hal_interrupt_handler_43);
|
||||
hal_set_interrupt_handler(44, hal_interrupt_handler_44);
|
||||
hal_set_interrupt_handler(45, hal_interrupt_handler_45);
|
||||
hal_set_interrupt_handler(46, hal_interrupt_handler_46);
|
||||
hal_set_interrupt_handler(47, hal_interrupt_handler_47);
|
||||
hal_set_interrupt_handler(48, hal_interrupt_handler_48);
|
||||
hal_set_interrupt_handler(49, hal_interrupt_handler_49);
|
||||
hal_set_interrupt_handler(50, hal_interrupt_handler_50);
|
||||
hal_set_interrupt_handler(51, hal_interrupt_handler_51);
|
||||
hal_set_interrupt_handler(52, hal_interrupt_handler_52);
|
||||
hal_set_interrupt_handler(53, hal_interrupt_handler_53);
|
||||
hal_set_interrupt_handler(54, hal_interrupt_handler_54);
|
||||
hal_set_interrupt_handler(55, hal_interrupt_handler_55);
|
||||
hal_set_interrupt_handler(56, hal_interrupt_handler_56);
|
||||
hal_set_interrupt_handler(57, hal_interrupt_handler_57);
|
||||
hal_set_interrupt_handler(58, hal_interrupt_handler_58);
|
||||
hal_set_interrupt_handler(59, hal_interrupt_handler_59);
|
||||
hal_set_interrupt_handler(60, hal_interrupt_handler_60);
|
||||
hal_set_interrupt_handler(61, hal_interrupt_handler_61);
|
||||
hal_set_interrupt_handler(62, hal_interrupt_handler_62);
|
||||
hal_set_interrupt_handler(63, hal_interrupt_handler_63);
|
||||
hal_set_interrupt_handler(64, hal_interrupt_handler_64);
|
||||
hal_set_interrupt_handler(65, hal_interrupt_handler_65);
|
||||
hal_set_interrupt_handler(66, hal_interrupt_handler_66);
|
||||
hal_set_interrupt_handler(67, hal_interrupt_handler_67);
|
||||
hal_set_interrupt_handler(68, hal_interrupt_handler_68);
|
||||
hal_set_interrupt_handler(69, hal_interrupt_handler_69);
|
||||
hal_set_interrupt_handler(70, hal_interrupt_handler_70);
|
||||
hal_set_interrupt_handler(71, hal_interrupt_handler_71);
|
||||
hal_set_interrupt_handler(72, hal_interrupt_handler_72);
|
||||
hal_set_interrupt_handler(73, hal_interrupt_handler_73);
|
||||
hal_set_interrupt_handler(74, hal_interrupt_handler_74);
|
||||
hal_set_interrupt_handler(75, hal_interrupt_handler_75);
|
||||
hal_set_interrupt_handler(76, hal_interrupt_handler_76);
|
||||
hal_set_interrupt_handler(77, hal_interrupt_handler_77);
|
||||
hal_set_interrupt_handler(78, hal_interrupt_handler_78);
|
||||
hal_set_interrupt_handler(79, hal_interrupt_handler_79);
|
||||
hal_set_interrupt_handler(80, hal_interrupt_handler_80);
|
||||
hal_set_interrupt_handler(81, hal_interrupt_handler_81);
|
||||
hal_set_interrupt_handler(82, hal_interrupt_handler_82);
|
||||
hal_set_interrupt_handler(83, hal_interrupt_handler_83);
|
||||
hal_set_interrupt_handler(84, hal_interrupt_handler_84);
|
||||
hal_set_interrupt_handler(85, hal_interrupt_handler_85);
|
||||
hal_set_interrupt_handler(86, hal_interrupt_handler_86);
|
||||
hal_set_interrupt_handler(87, hal_interrupt_handler_87);
|
||||
hal_set_interrupt_handler(88, hal_interrupt_handler_88);
|
||||
hal_set_interrupt_handler(89, hal_interrupt_handler_89);
|
||||
hal_set_interrupt_handler(90, hal_interrupt_handler_90);
|
||||
hal_set_interrupt_handler(91, hal_interrupt_handler_91);
|
||||
hal_set_interrupt_handler(92, hal_interrupt_handler_92);
|
||||
hal_set_interrupt_handler(93, hal_interrupt_handler_93);
|
||||
hal_set_interrupt_handler(94, hal_interrupt_handler_94);
|
||||
hal_set_interrupt_handler(95, hal_interrupt_handler_95);
|
||||
hal_set_interrupt_handler(96, hal_interrupt_handler_96);
|
||||
hal_set_interrupt_handler(97, hal_interrupt_handler_97);
|
||||
hal_set_interrupt_handler(98, hal_interrupt_handler_98);
|
||||
hal_set_interrupt_handler(99, hal_interrupt_handler_99);
|
||||
hal_set_interrupt_handler(100, hal_interrupt_handler_100);
|
||||
hal_set_interrupt_handler(101, hal_interrupt_handler_101);
|
||||
hal_set_interrupt_handler(102, hal_interrupt_handler_102);
|
||||
hal_set_interrupt_handler(103, hal_interrupt_handler_103);
|
||||
hal_set_interrupt_handler(104, hal_interrupt_handler_104);
|
||||
hal_set_interrupt_handler(105, hal_interrupt_handler_105);
|
||||
hal_set_interrupt_handler(106, hal_interrupt_handler_106);
|
||||
hal_set_interrupt_handler(107, hal_interrupt_handler_107);
|
||||
hal_set_interrupt_handler(108, hal_interrupt_handler_108);
|
||||
hal_set_interrupt_handler(109, hal_interrupt_handler_109);
|
||||
hal_set_interrupt_handler(110, hal_interrupt_handler_110);
|
||||
hal_set_interrupt_handler(111, hal_interrupt_handler_111);
|
||||
hal_set_interrupt_handler(112, hal_interrupt_handler_112);
|
||||
hal_set_interrupt_handler(113, hal_interrupt_handler_113);
|
||||
hal_set_interrupt_handler(114, hal_interrupt_handler_114);
|
||||
hal_set_interrupt_handler(115, hal_interrupt_handler_115);
|
||||
hal_set_interrupt_handler(116, hal_interrupt_handler_116);
|
||||
hal_set_interrupt_handler(117, hal_interrupt_handler_117);
|
||||
hal_set_interrupt_handler(118, hal_interrupt_handler_118);
|
||||
hal_set_interrupt_handler(119, hal_interrupt_handler_119);
|
||||
hal_set_interrupt_handler(120, hal_interrupt_handler_120);
|
||||
hal_set_interrupt_handler(121, hal_interrupt_handler_121);
|
||||
hal_set_interrupt_handler(122, hal_interrupt_handler_122);
|
||||
hal_set_interrupt_handler(123, hal_interrupt_handler_123);
|
||||
hal_set_interrupt_handler(124, hal_interrupt_handler_124);
|
||||
hal_set_interrupt_handler(125, hal_interrupt_handler_125);
|
||||
hal_set_interrupt_handler(126, hal_interrupt_handler_126);
|
||||
hal_set_interrupt_handler(127, hal_interrupt_handler_127);
|
||||
hal_set_interrupt_handler(128, hal_interrupt_handler_128);
|
||||
hal_set_interrupt_handler(129, hal_interrupt_handler_129);
|
||||
hal_set_interrupt_handler(130, hal_interrupt_handler_130);
|
||||
hal_set_interrupt_handler(131, hal_interrupt_handler_131);
|
||||
hal_set_interrupt_handler(132, hal_interrupt_handler_132);
|
||||
hal_set_interrupt_handler(133, hal_interrupt_handler_133);
|
||||
hal_set_interrupt_handler(134, hal_interrupt_handler_134);
|
||||
hal_set_interrupt_handler(135, hal_interrupt_handler_135);
|
||||
hal_set_interrupt_handler(136, hal_interrupt_handler_136);
|
||||
hal_set_interrupt_handler(137, hal_interrupt_handler_137);
|
||||
hal_set_interrupt_handler(138, hal_interrupt_handler_138);
|
||||
hal_set_interrupt_handler(139, hal_interrupt_handler_139);
|
||||
hal_set_interrupt_handler(140, hal_interrupt_handler_140);
|
||||
hal_set_interrupt_handler(141, hal_interrupt_handler_141);
|
||||
hal_set_interrupt_handler(142, hal_interrupt_handler_142);
|
||||
hal_set_interrupt_handler(143, hal_interrupt_handler_143);
|
||||
hal_set_interrupt_handler(144, hal_interrupt_handler_144);
|
||||
hal_set_interrupt_handler(145, hal_interrupt_handler_145);
|
||||
hal_set_interrupt_handler(146, hal_interrupt_handler_146);
|
||||
hal_set_interrupt_handler(147, hal_interrupt_handler_147);
|
||||
hal_set_interrupt_handler(148, hal_interrupt_handler_148);
|
||||
hal_set_interrupt_handler(149, hal_interrupt_handler_149);
|
||||
hal_set_interrupt_handler(150, hal_interrupt_handler_150);
|
||||
hal_set_interrupt_handler(151, hal_interrupt_handler_151);
|
||||
hal_set_interrupt_handler(152, hal_interrupt_handler_152);
|
||||
hal_set_interrupt_handler(153, hal_interrupt_handler_153);
|
||||
hal_set_interrupt_handler(154, hal_interrupt_handler_154);
|
||||
hal_set_interrupt_handler(155, hal_interrupt_handler_155);
|
||||
hal_set_interrupt_handler(156, hal_interrupt_handler_156);
|
||||
hal_set_interrupt_handler(157, hal_interrupt_handler_157);
|
||||
hal_set_interrupt_handler(158, hal_interrupt_handler_158);
|
||||
hal_set_interrupt_handler(159, hal_interrupt_handler_159);
|
||||
hal_set_interrupt_handler(160, hal_interrupt_handler_160);
|
||||
hal_set_interrupt_handler(161, hal_interrupt_handler_161);
|
||||
hal_set_interrupt_handler(162, hal_interrupt_handler_162);
|
||||
hal_set_interrupt_handler(163, hal_interrupt_handler_163);
|
||||
hal_set_interrupt_handler(164, hal_interrupt_handler_164);
|
||||
hal_set_interrupt_handler(165, hal_interrupt_handler_165);
|
||||
hal_set_interrupt_handler(166, hal_interrupt_handler_166);
|
||||
hal_set_interrupt_handler(167, hal_interrupt_handler_167);
|
||||
hal_set_interrupt_handler(168, hal_interrupt_handler_168);
|
||||
hal_set_interrupt_handler(169, hal_interrupt_handler_169);
|
||||
hal_set_interrupt_handler(170, hal_interrupt_handler_170);
|
||||
hal_set_interrupt_handler(171, hal_interrupt_handler_171);
|
||||
hal_set_interrupt_handler(172, hal_interrupt_handler_172);
|
||||
hal_set_interrupt_handler(173, hal_interrupt_handler_173);
|
||||
hal_set_interrupt_handler(174, hal_interrupt_handler_174);
|
||||
hal_set_interrupt_handler(175, hal_interrupt_handler_175);
|
||||
hal_set_interrupt_handler(176, hal_interrupt_handler_176);
|
||||
hal_set_interrupt_handler(177, hal_interrupt_handler_177);
|
||||
hal_set_interrupt_handler(178, hal_interrupt_handler_178);
|
||||
hal_set_interrupt_handler(179, hal_interrupt_handler_179);
|
||||
hal_set_interrupt_handler(180, hal_interrupt_handler_180);
|
||||
hal_set_interrupt_handler(181, hal_interrupt_handler_181);
|
||||
hal_set_interrupt_handler(182, hal_interrupt_handler_182);
|
||||
hal_set_interrupt_handler(183, hal_interrupt_handler_183);
|
||||
hal_set_interrupt_handler(184, hal_interrupt_handler_184);
|
||||
hal_set_interrupt_handler(185, hal_interrupt_handler_185);
|
||||
hal_set_interrupt_handler(186, hal_interrupt_handler_186);
|
||||
hal_set_interrupt_handler(187, hal_interrupt_handler_187);
|
||||
hal_set_interrupt_handler(188, hal_interrupt_handler_188);
|
||||
hal_set_interrupt_handler(189, hal_interrupt_handler_189);
|
||||
hal_set_interrupt_handler(190, hal_interrupt_handler_190);
|
||||
hal_set_interrupt_handler(191, hal_interrupt_handler_191);
|
||||
hal_set_interrupt_handler(192, hal_interrupt_handler_192);
|
||||
hal_set_interrupt_handler(193, hal_interrupt_handler_193);
|
||||
hal_set_interrupt_handler(194, hal_interrupt_handler_194);
|
||||
hal_set_interrupt_handler(195, hal_interrupt_handler_195);
|
||||
hal_set_interrupt_handler(196, hal_interrupt_handler_196);
|
||||
hal_set_interrupt_handler(197, hal_interrupt_handler_197);
|
||||
hal_set_interrupt_handler(198, hal_interrupt_handler_198);
|
||||
hal_set_interrupt_handler(199, hal_interrupt_handler_199);
|
||||
hal_set_interrupt_handler(200, hal_interrupt_handler_200);
|
||||
hal_set_interrupt_handler(201, hal_interrupt_handler_201);
|
||||
hal_set_interrupt_handler(202, hal_interrupt_handler_202);
|
||||
hal_set_interrupt_handler(203, hal_interrupt_handler_203);
|
||||
hal_set_interrupt_handler(204, hal_interrupt_handler_204);
|
||||
hal_set_interrupt_handler(205, hal_interrupt_handler_205);
|
||||
hal_set_interrupt_handler(206, hal_interrupt_handler_206);
|
||||
hal_set_interrupt_handler(207, hal_interrupt_handler_207);
|
||||
hal_set_interrupt_handler(208, hal_interrupt_handler_208);
|
||||
hal_set_interrupt_handler(209, hal_interrupt_handler_209);
|
||||
hal_set_interrupt_handler(210, hal_interrupt_handler_210);
|
||||
hal_set_interrupt_handler(211, hal_interrupt_handler_211);
|
||||
hal_set_interrupt_handler(212, hal_interrupt_handler_212);
|
||||
hal_set_interrupt_handler(213, hal_interrupt_handler_213);
|
||||
hal_set_interrupt_handler(214, hal_interrupt_handler_214);
|
||||
hal_set_interrupt_handler(215, hal_interrupt_handler_215);
|
||||
hal_set_interrupt_handler(216, hal_interrupt_handler_216);
|
||||
hal_set_interrupt_handler(217, hal_interrupt_handler_217);
|
||||
hal_set_interrupt_handler(218, hal_interrupt_handler_218);
|
||||
hal_set_interrupt_handler(219, hal_interrupt_handler_219);
|
||||
hal_set_interrupt_handler(220, hal_interrupt_handler_220);
|
||||
hal_set_interrupt_handler(221, hal_interrupt_handler_221);
|
||||
hal_set_interrupt_handler(222, hal_interrupt_handler_222);
|
||||
hal_set_interrupt_handler(223, hal_interrupt_handler_223);
|
||||
hal_set_interrupt_handler(224, hal_interrupt_handler_224);
|
||||
hal_set_interrupt_handler(225, hal_interrupt_handler_225);
|
||||
hal_set_interrupt_handler(226, hal_interrupt_handler_226);
|
||||
hal_set_interrupt_handler(227, hal_interrupt_handler_227);
|
||||
hal_set_interrupt_handler(228, hal_interrupt_handler_228);
|
||||
hal_set_interrupt_handler(229, hal_interrupt_handler_229);
|
||||
hal_set_interrupt_handler(230, hal_interrupt_handler_230);
|
||||
hal_set_interrupt_handler(231, hal_interrupt_handler_231);
|
||||
hal_set_interrupt_handler(232, hal_interrupt_handler_232);
|
||||
hal_set_interrupt_handler(233, hal_interrupt_handler_233);
|
||||
hal_set_interrupt_handler(234, hal_interrupt_handler_234);
|
||||
hal_set_interrupt_handler(235, hal_interrupt_handler_235);
|
||||
hal_set_interrupt_handler(236, hal_interrupt_handler_236);
|
||||
hal_set_interrupt_handler(237, hal_interrupt_handler_237);
|
||||
hal_set_interrupt_handler(238, hal_interrupt_handler_238);
|
||||
hal_set_interrupt_handler(239, hal_interrupt_handler_239);
|
||||
hal_set_interrupt_handler(240, hal_interrupt_handler_240);
|
||||
hal_set_interrupt_handler(241, hal_interrupt_handler_241);
|
||||
hal_set_interrupt_handler(242, hal_interrupt_handler_242);
|
||||
hal_set_interrupt_handler(243, hal_interrupt_handler_243);
|
||||
hal_set_interrupt_handler(244, hal_interrupt_handler_244);
|
||||
hal_set_interrupt_handler(245, hal_interrupt_handler_245);
|
||||
hal_set_interrupt_handler(246, hal_interrupt_handler_246);
|
||||
hal_set_interrupt_handler(247, hal_interrupt_handler_247);
|
||||
hal_set_interrupt_handler(248, hal_interrupt_handler_248);
|
||||
hal_set_interrupt_handler(249, hal_interrupt_handler_249);
|
||||
hal_set_interrupt_handler(250, hal_interrupt_handler_250);
|
||||
hal_set_interrupt_handler(251, hal_interrupt_handler_251);
|
||||
hal_set_interrupt_handler(252, hal_interrupt_handler_252);
|
||||
hal_set_interrupt_handler(253, hal_interrupt_handler_253);
|
||||
hal_set_interrupt_handler(254, hal_interrupt_handler_254);
|
||||
hal_set_interrupt_handler(255, hal_interrupt_handler_255);
|
||||
}
|
||||
|
||||
int32 SXAPI hal_interrupt_init(void)
|
||||
uint32
|
||||
hal_get_core_id(void)
|
||||
{
|
||||
uint32 coreid = hal_get_core_id();
|
||||
uint32 eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
eax = 1;
|
||||
hal_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
if (!(edx & lb_bit_mask(9)))
|
||||
{
|
||||
hal_printf("ERROR: APIC not supported by CPU.\n");
|
||||
return 1;
|
||||
}
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get idt ptr ready
|
||||
_idt_ptrs[coreid].base = (uint64) &_idts[coreid];
|
||||
_idt_ptrs[coreid].limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1;
|
||||
int32
|
||||
hal_interrupt_init(void)
|
||||
{
|
||||
uint32 coreid = hal_get_core_id();
|
||||
uint32 eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
eax = 1;
|
||||
hal_cpuid(&eax, &ebx, &ecx, &edx);
|
||||
if (!(edx & bit_mask(9)))
|
||||
{
|
||||
hal_printf("ERROR: APIC not supported by CPU.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// clear dispatch table
|
||||
for (uint64 i = 0; i < IDT_ENTRY_NUM; i++)
|
||||
{
|
||||
_intr_handler_table[coreid][i] = NULL;
|
||||
_exc_handler_table[coreid][i] = NULL;
|
||||
_intr_handler_context_table[coreid][i] = NULL;
|
||||
}
|
||||
// get idt ptr ready
|
||||
_idt_ptrs[coreid].base = (uint64) &_idts[coreid];
|
||||
_idt_ptrs[coreid].limit = IDT_ENTRY_NUM * IDT_ENTRY_SIZE - 1;
|
||||
|
||||
// hook asm interrupt handlers
|
||||
halp_populate_idt();
|
||||
// clear dispatch table
|
||||
for (uint64 i = 0; i < IDT_ENTRY_NUM; i++)
|
||||
{
|
||||
_intr_handler_table[coreid][i] = NULL;
|
||||
_exc_handler_table[coreid][i] = NULL;
|
||||
_intr_handler_context_table[coreid][i] = NULL;
|
||||
}
|
||||
|
||||
hal_flush_idt(&_idt_ptrs[coreid]);
|
||||
// hook asm interrupt handlers
|
||||
halp_populate_idt();
|
||||
|
||||
// disable PIC
|
||||
hal_write_port_8(0xa1, 0xff);
|
||||
hal_write_port_8(0x21, 0xff);
|
||||
hal_flush_idt(&_idt_ptrs[coreid]);
|
||||
|
||||
uint64 apic_base_reg = 0;
|
||||
uint64 apic_base = 0;
|
||||
ecx = MSR_IA32_APIC_BASE;
|
||||
hal_read_msr(&ecx, &edx, &eax);
|
||||
apic_base_reg = ((uint64) edx << 32) + (uint64) eax;
|
||||
apic_base = apic_base_reg & lb_bit_field_mask(12, 35);
|
||||
UNREFERENCED(apic_base);
|
||||
// disable PIC
|
||||
hal_write_port_8(0xa1, 0xff);
|
||||
hal_write_port_8(0x21, 0xff);
|
||||
|
||||
//hal_printf("APIC Base: 0x%X\n", apic_base);
|
||||
//hal_printf("APIC Enabled: %s\n", apic_base_reg & bit_mask_64(11) ? "Yes" : "No");
|
||||
//hal_printf("BSP: %s\n", apic_base_reg & bit_mask_64(8) ? "Yes" : "No");
|
||||
//hal_printf("APIC Spour: 0x%X\n", *(uint32 *) ((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET));
|
||||
uint64 apic_base_reg = 0;
|
||||
uint64 apic_base = 0;
|
||||
ecx = MSR_IA32_APIC_BASE;
|
||||
hal_read_msr(&ecx, &edx, &eax);
|
||||
apic_base_reg = ((uint64) edx << 32) + (uint64) eax;
|
||||
apic_base = apic_base_reg & bit_field_mask(12, 35);
|
||||
UNREFERENCED(apic_base);
|
||||
|
||||
// hardware enable APIC
|
||||
ecx = MSR_IA32_APIC_BASE;
|
||||
eax = (uint32) ((apic_base_reg & lb_bit_field_mask(0, 31)) | lb_bit_mask(11));
|
||||
hal_write_msr(&ecx, &edx, &eax);
|
||||
//hal_printf("APIC Base: 0x%X\n", apic_base);
|
||||
//hal_printf("APIC Enabled: %s\n", apic_base_reg & bit_mask_64(11) ? "Yes" : "No");
|
||||
//hal_printf("BSP: %s\n", apic_base_reg & bit_mask_64(8) ? "Yes" : "No");
|
||||
//hal_printf("APIC Spour: 0x%X\n", *(uint32 *) ((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET));
|
||||
|
||||
// software enable APIC
|
||||
// hal_write_mem_32((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET, *(uint32 *) (apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET) | (uint32)lb_bit_mask(8));
|
||||
// hardware enable APIC
|
||||
ecx = MSR_IA32_APIC_BASE;
|
||||
eax = (uint32) ((apic_base_reg & bit_field_mask(0, 31)) | bit_mask(11));
|
||||
hal_write_msr(&ecx, &edx, &eax);
|
||||
|
||||
// software enable APIC
|
||||
// hal_write_mem_32((char *) apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET, *(uint32 *) (apic_base + APIC_SPURIOUS_INT_VEC_REG_OFFSET) | (uint32)bit_mask(8));
|
||||
|
||||
// hal_issue_interrupt(1, 255);
|
||||
// hal_enable_interrupt();
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
285
hal/mem.c
285
hal/mem.c
|
@ -1,24 +1,23 @@
|
|||
|
||||
#include "type.h"
|
||||
#include "hal/mem.h"
|
||||
#include "hal/cpu.h"
|
||||
#include "lib/salloc.h"
|
||||
#include "hal/intr.h"
|
||||
#include "status.h"
|
||||
#include "common.h"
|
||||
#include "cpu.h"
|
||||
#include "mem.h"
|
||||
#include "intr.h"
|
||||
#include "hal_export.h"
|
||||
|
||||
static uint8 _gdts[HAL_CORE_COUNT][GDT_ENTRY_NUM * GDT_ENTRY_SIZE];
|
||||
static struct hal_gdt_ptr _gdt_ptrs[HAL_CORE_COUNT];
|
||||
|
||||
#define KERNEL_HEAP_SIZE 8192
|
||||
#define HAL_HEAP_SIZE 8192
|
||||
static uint32 hal_heap_used;
|
||||
static char hal_heap[HAL_HEAP_SIZE];
|
||||
|
||||
static char kernel_heap[KERNEL_HEAP_SIZE];
|
||||
|
||||
sx_status SXAPI hal_write_initial_page_table(void *multiboot_info)
|
||||
uint32 hal_write_initial_page_table(void *multiboot_info)
|
||||
{
|
||||
UNREFERENCED(multiboot_info);
|
||||
UNREFERENCED(multiboot_info);
|
||||
|
||||
/*
|
||||
// still identity mapping
|
||||
/*
|
||||
// still identity mapping
|
||||
uint32 pt_num = 0;
|
||||
uint32 pd_num = 0;
|
||||
uint32 pdpt_num = 0;
|
||||
|
@ -29,164 +28,182 @@ sx_status SXAPI hal_write_initial_page_table(void *multiboot_info)
|
|||
// see multiboot boot info header
|
||||
uint32 m_size = *(uint32 *)multiboot_info;
|
||||
|
||||
// how many pages do we need to hold the entries
|
||||
// how many pages do we need to hold the entries
|
||||
// 512 page table entries per 4k page
|
||||
pt_num = (1 + (uint32)((k_size + m_size - 1) / KERNEL_PAGE_SIZE)) / 512;
|
||||
pd_num = 1 + (pt_num - 1) / 512;
|
||||
pdpt_num = 1 + (pd_num - 1) / 512;
|
||||
pml4_num = 1 + (pdpt_num - 1) / 512;
|
||||
pt_num = (1 + (uint32)((k_size + m_size - 1) / KERNEL_PAGE_SIZE)) / 512;
|
||||
pd_num = 1 + (pt_num - 1) / 512;
|
||||
pdpt_num = 1 + (pd_num - 1) / 512;
|
||||
pml4_num = 1 + (pdpt_num - 1) / 512;
|
||||
|
||||
// calculate the # of page tables
|
||||
// calculate the # of page tables
|
||||
if ((((uintptr)(pt_end) - (uintptr)(pt_base)) / KERNEL_PAGE_SIZE) < (pt_num + pd_num + pdpt_num + pml4_num))
|
||||
{
|
||||
return STATUS_FAIL;
|
||||
}
|
||||
|
||||
// map kernel first
|
||||
KERNEL_IMAGE_VADDR = ;
|
||||
// map kernel first
|
||||
KERNEL_IMAGE_VADDR = ;
|
||||
|
||||
// map kernel dynamic
|
||||
KERNEL_DYNAMIC_SIZE = ;
|
||||
// map kernel dynamic
|
||||
KERNEL_DYNAMIC_SIZE = ;
|
||||
|
||||
// map recursive page tables
|
||||
hal_write_pml4(pt_base, (uintptr)pt_base, PML4_PRESENT | PML4_WRITE);
|
||||
*/
|
||||
hal_write_pml4(pt_base, (uintptr)pt_base, PML4_PRESENT | PML4_WRITE);
|
||||
*/
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SXAPI hal_write_pt(void *const base, uintptr const p_addr, uint64 const attr)
|
||||
void
|
||||
hal_write_pt(void *const base, uintptr const p_addr, uint64 const attr)
|
||||
{
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 entry = (p_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 entry = (p_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
}
|
||||
|
||||
void SXAPI hal_write_pd(void *const base, uintptr const pt_addr, uint64 const attr)
|
||||
void
|
||||
hal_write_pd(void *const base, uintptr const pt_addr, uint64 const attr)
|
||||
{
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 entry = (pt_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 entry = (pt_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
}
|
||||
|
||||
void SXAPI hal_write_pdpt(void *const base, uintptr const pd_addr, uint64 const attr)
|
||||
void
|
||||
hal_write_pdpt(void *const base, uintptr const pd_addr, uint64 const attr)
|
||||
{
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 entry = (pd_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 entry = (pd_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
}
|
||||
|
||||
void SXAPI hal_write_pml4(void *const base, uintptr const pdpt_addr, uint64 const attr)
|
||||
void
|
||||
hal_write_pml4(void *const base, uintptr const pdpt_addr, uint64 const attr)
|
||||
{
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 const entry = (pdpt_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
if (base == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 const entry = (pdpt_addr & 0xFFFFFFFFFF000) | attr;
|
||||
((uint8 *) base)[0] = (uint8) (entry & 0xFF);
|
||||
((uint8 *) base)[1] = (uint8) ((entry >> 8) & 0xFF);
|
||||
((uint8 *) base)[2] = (uint8) ((entry >> 16) & 0xFF);
|
||||
((uint8 *) base)[3] = (uint8) ((entry >> 24) & 0xFF);
|
||||
((uint8 *) base)[4] = (uint8) ((entry >> 32) & 0xFF);
|
||||
((uint8 *) base)[5] = (uint8) ((entry >> 40) & 0xFF);
|
||||
((uint8 *) base)[6] = (uint8) ((entry >> 48) & 0xFF);
|
||||
((uint8 *) base)[7] = (uint8) ((entry >> 56) & 0xFF);
|
||||
}
|
||||
|
||||
void SXAPI hal_write_segment_descriptor(void *const gdt, uint32 const base, uint32 const limit,
|
||||
uint64 const attr)
|
||||
void
|
||||
hal_write_segment_descriptor(void *const gdt, uint32 const base, uint32 const limit, uint64 const attr)
|
||||
{
|
||||
if (gdt == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 const seg_desc = (((uint64) base & 0xFFFF) << 16) | ((((uint64) base >> 16) & 0xFF) << 32) |
|
||||
((((uint64) base >> 24) & 0xFF) << 56) | ((uint64) limit & 0xFFFF) |
|
||||
((((uint64) limit >> 16) & 0xF) << 48) | attr;
|
||||
((uint8 *) gdt)[0] = (uint8) (seg_desc & 0xFF);
|
||||
((uint8 *) gdt)[1] = (uint8) ((seg_desc >> 8) & 0xFF);
|
||||
((uint8 *) gdt)[2] = (uint8) ((seg_desc >> 16) & 0xFF);
|
||||
((uint8 *) gdt)[3] = (uint8) ((seg_desc >> 24) & 0xFF);
|
||||
((uint8 *) gdt)[4] = (uint8) ((seg_desc >> 32) & 0xFF);
|
||||
((uint8 *) gdt)[5] = (uint8) ((seg_desc >> 40) & 0xFF);
|
||||
((uint8 *) gdt)[6] = (uint8) ((seg_desc >> 48) & 0xFF);
|
||||
((uint8 *) gdt)[7] = (uint8) ((seg_desc >> 56) & 0xFF);
|
||||
if (gdt == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
uint64 const seg_desc = (((uint64) base & 0xFFFF) << 16) | ((((uint64) base >> 16) & 0xFF) << 32) |
|
||||
((((uint64) base >> 24) & 0xFF) << 56) | ((uint64) limit & 0xFFFF) |
|
||||
((((uint64) limit >> 16) & 0xF) << 48) | attr;
|
||||
((uint8 *) gdt)[0] = (uint8) (seg_desc & 0xFF);
|
||||
((uint8 *) gdt)[1] = (uint8) ((seg_desc >> 8) & 0xFF);
|
||||
((uint8 *) gdt)[2] = (uint8) ((seg_desc >> 16) & 0xFF);
|
||||
((uint8 *) gdt)[3] = (uint8) ((seg_desc >> 24) & 0xFF);
|
||||
((uint8 *) gdt)[4] = (uint8) ((seg_desc >> 32) & 0xFF);
|
||||
((uint8 *) gdt)[5] = (uint8) ((seg_desc >> 40) & 0xFF);
|
||||
((uint8 *) gdt)[6] = (uint8) ((seg_desc >> 48) & 0xFF);
|
||||
((uint8 *) gdt)[7] = (uint8) ((seg_desc >> 56) & 0xFF);
|
||||
}
|
||||
|
||||
void *SXAPI halloc(uint32 size)
|
||||
static
|
||||
void _hal_init_gdt(void)
|
||||
{
|
||||
return lb_salloc(kernel_heap, size);
|
||||
uint32 coreid = hal_get_core_id();
|
||||
// get gdt ready
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][0], 0, 0, 0);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][8], 0, 0,
|
||||
SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][16], 0, 0,
|
||||
SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][24], 0, 0,
|
||||
SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][32], 0, 0,
|
||||
SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW);
|
||||
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][40], 0, 0xFFFFF,
|
||||
SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][48], 0, 0xFFFFF,
|
||||
SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_DATA_RW);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][56], 0, 0xFFFFF,
|
||||
SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][64], 0, 0xFFFFF,
|
||||
SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_DATA_RW);
|
||||
_gdt_ptrs[coreid].base = (uint64) &_gdts[coreid];
|
||||
_gdt_ptrs[coreid].limit = GDT_ENTRY_NUM * GDT_ENTRY_SIZE - 1;
|
||||
hal_flush_gdt(&_gdt_ptrs[coreid], seg_selector(1, 0), seg_selector(2, 0));
|
||||
}
|
||||
|
||||
void SXAPI hfree(void *ptr)
|
||||
void
|
||||
hal_mem_init()
|
||||
{
|
||||
lb_sfree(kernel_heap, ptr);
|
||||
_hal_init_gdt();
|
||||
hal_heap_used = 0;
|
||||
}
|
||||
|
||||
static void SXAPI _hal_init_gdt(void)
|
||||
void *
|
||||
halloc(uint32 size)
|
||||
{
|
||||
uint32 coreid = hal_get_core_id();
|
||||
// get gdt ready
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][0], 0, 0, 0);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][8], 0, 0,
|
||||
SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][16], 0, 0,
|
||||
SEG_DPL_0 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][24], 0, 0,
|
||||
SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][32], 0, 0,
|
||||
SEG_DPL_3 | SEG_CODE_DATA | SEG_PRESENT | SEG_LONG | SEG_TYPE_DATA_RW);
|
||||
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][40], 0, 0xFFFFF,
|
||||
SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][48], 0, 0xFFFFF,
|
||||
SEG_DPL_0 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_DATA_RW);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][56], 0, 0xFFFFF,
|
||||
SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_CODE_X);
|
||||
hal_write_segment_descriptor((void *) &_gdts[coreid][64], 0, 0xFFFFF,
|
||||
SEG_DPL_3 | SEG_GRANULARITY | SEG_CODE_DATA | SEG_PRESENT | SEG_32_BITS |
|
||||
SEG_TYPE_DATA_RW);
|
||||
_gdt_ptrs[coreid].base = (uint64) &_gdts[coreid];
|
||||
_gdt_ptrs[coreid].limit = GDT_ENTRY_NUM * GDT_ENTRY_SIZE - 1;
|
||||
hal_flush_gdt(&_gdt_ptrs[coreid], seg_selector(1, 0), seg_selector(2, 0));
|
||||
void* ret;
|
||||
ret = NULL;
|
||||
if(hal_heap_used + size < HAL_HEAP_SIZE)
|
||||
{
|
||||
ret = (void*)((uintptr)hal_heap + hal_heap_used);
|
||||
hal_heap_used += size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SXAPI hal_mem_init()
|
||||
void
|
||||
hfree(void *ptr)
|
||||
{
|
||||
_hal_init_gdt();
|
||||
lb_salloc_init(kernel_heap, KERNEL_HEAP_SIZE);
|
||||
/**
|
||||
* Do nothing for now since salloc not available in HAL
|
||||
*/
|
||||
UNREFERENCED(ptr);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
#ifndef HAL_MEM_H
|
||||
#define HAL_MEM_H
|
||||
#pragma once
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/mem.h"
|
||||
#include "status.h"
|
||||
#include "common.h"
|
||||
#include "mem.h"
|
||||
#include "kernel/status.h"
|
||||
|
||||
/**
|
||||
Global Descriptors Table Definitions
|
||||
|
@ -74,31 +73,39 @@
|
|||
#define PD_ENTRY_NUM(vaddr) (((vaddr) >> 21) & 0x1FF)
|
||||
#define PT_ENTRY_NUM(vaddr) (((vaddr) >> 12) & 0x1FF)
|
||||
|
||||
static inline uint32 SXAPI seg_selector(uint32 index, uint32 rpl)
|
||||
static inline uint32 seg_selector(uint32 index, uint32 rpl)
|
||||
{
|
||||
return (index << 3) + rpl;
|
||||
return (index << 3) + rpl;
|
||||
}
|
||||
|
||||
void SXAPI hal_write_segment_descriptor(void *const gdt, uint32 const base, uint32 const limit, uint64 const attr);
|
||||
void
|
||||
hal_write_segment_descriptor(void *gdt, uint32 base, uint32 limit, uint64 attr);
|
||||
|
||||
void SXAPI hal_write_pml4(void *const base, uintptr const pdpt_addr, uint64 const attr);
|
||||
void
|
||||
hal_write_pml4(void *base, uintptr pdpt_addr, uint64 attr);
|
||||
|
||||
void SXAPI hal_write_pdpt(void *const base, uintptr const pd_addr, uint64 const attr);
|
||||
void
|
||||
hal_write_pdpt(void *base, uintptr pd_addr, uint64 attr);
|
||||
|
||||
void SXAPI hal_write_pd(void *const base, uintptr const pt_addr, uint64 const attr);
|
||||
void
|
||||
hal_write_pd(void *base, uintptr pt_addr, uint64 attr);
|
||||
|
||||
void SXAPI hal_write_pt(void *const base, uintptr const p_addr, uint64 const attr);
|
||||
void
|
||||
hal_write_pt(void *base, uintptr p_addr, uint64 attr);
|
||||
|
||||
sx_status SXAPI hal_write_initial_page_table(void *multiboot_info);
|
||||
k_status
|
||||
hal_write_initial_page_table(void *multiboot_info);
|
||||
|
||||
/**
|
||||
Function Defn
|
||||
**/
|
||||
|
||||
void *SXAPI halloc(uint32 size);
|
||||
void *
|
||||
halloc(uint32 size);
|
||||
|
||||
void SXAPI hfree(void *ptr);
|
||||
void
|
||||
hfree(void *ptr);
|
||||
|
||||
void SXAPI hal_mem_init(void);
|
||||
void
|
||||
hal_mem_init(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,388 @@
|
|||
/* multiboot2.h - Multiboot 2 header file. */
|
||||
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Kernel memory layout
|
||||
*/
|
||||
#define KERNEL_IMAGE_PADDR (0x1000000)
|
||||
#define KERNEL_PAGE_SIZE (0x1000)
|
||||
|
||||
#define KERNEL_SPACE_VADDR (0xFFFF800000000000)
|
||||
#define KERNEL_RESERVED_VADDR KERNEL_SPACE_VADDR
|
||||
#define KERNEL_RESERVED_SIZE (0x00007F0000000000)
|
||||
#define KERNEL_PAGE_TABLE_VADDR (0xFFFFFF0000000000)
|
||||
#define KERNEL_PAGE_TABLE_SIZE (0x0000008000000000)
|
||||
#define KERNEL_DYNAMIC_VADDR (0xFFFFFF8000000000)
|
||||
#define KERNEL_DYNAMIC_SIZE (0x0000007F80000000)
|
||||
#define KERNEL_IMAGE_VADDR (0xFFFFFFFF80000000)
|
||||
#define KERNEL_IMAGE_SIZE (0x0000000080000000)
|
||||
|
||||
/* How many bytes from the start of the file we search for the header. */
|
||||
#define MULTIBOOT_SEARCH 32768
|
||||
#define MULTIBOOT_HEADER_ALIGN 8
|
||||
|
||||
/* The magic field should contain this. */
|
||||
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
||||
|
||||
/* This should be in %eax. */
|
||||
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
||||
|
||||
/* Alignment of multiboot modules. */
|
||||
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||
|
||||
/* Alignment of the multiboot info structure. */
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
||||
|
||||
/* Flags set in the 'flags' member of the multiboot header. */
|
||||
|
||||
#define MULTIBOOT_TAG_ALIGN 8
|
||||
#define MULTIBOOT_TAG_TYPE_END 0
|
||||
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
||||
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
||||
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
||||
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
||||
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
||||
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
||||
#define MULTIBOOT_TAG_TYPE_VBE 7
|
||||
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
||||
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
||||
#define MULTIBOOT_TAG_TYPE_APM 10
|
||||
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
||||
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
||||
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
||||
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||
|
||||
#define MULTIBOOT_HEADER_TAG_END 0
|
||||
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
||||
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
||||
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
||||
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
||||
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
||||
|
||||
#define MULTIBOOT_ARCHITECTURE_I386 0
|
||||
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
||||
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
||||
|
||||
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||
|
||||
#ifndef ASM_FILE
|
||||
|
||||
typedef unsigned char multiboot_uint8_t;
|
||||
typedef unsigned short multiboot_uint16_t;
|
||||
typedef unsigned int multiboot_uint32_t;
|
||||
typedef unsigned long long multiboot_uint64_t;
|
||||
|
||||
struct multiboot_header
|
||||
{
|
||||
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||
multiboot_uint32_t magic;
|
||||
|
||||
/* ISA */
|
||||
multiboot_uint32_t architecture;
|
||||
|
||||
/* Total header length. */
|
||||
multiboot_uint32_t header_length;
|
||||
|
||||
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||
multiboot_uint32_t checksum;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_information_request
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t requests[0];
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_address
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t header_addr;
|
||||
multiboot_uint32_t load_addr;
|
||||
multiboot_uint32_t load_end_addr;
|
||||
multiboot_uint32_t bss_end_addr;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_entry_address
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t entry_addr;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_console_flags
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t console_flags;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_framebuffer
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t width;
|
||||
multiboot_uint32_t height;
|
||||
multiboot_uint32_t depth;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_module_align
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
};
|
||||
|
||||
struct multiboot_color
|
||||
{
|
||||
multiboot_uint8_t red;
|
||||
multiboot_uint8_t green;
|
||||
multiboot_uint8_t blue;
|
||||
};
|
||||
|
||||
struct multiboot_mmap_entry
|
||||
{
|
||||
multiboot_uint64_t addr;
|
||||
multiboot_uint64_t len;
|
||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||
#define MULTIBOOT_MEMORY_NVS 4
|
||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t zero;
|
||||
} GRUB_PACKED;
|
||||
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||
|
||||
struct multiboot_tag
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
};
|
||||
|
||||
struct multiboot_tag_string
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
char string[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_module
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t mod_start;
|
||||
multiboot_uint32_t mod_end;
|
||||
char cmdline[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_basic_meminfo
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t mem_lower;
|
||||
multiboot_uint32_t mem_upper;
|
||||
};
|
||||
|
||||
struct multiboot_tag_bootdev
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t biosdev;
|
||||
multiboot_uint32_t slice;
|
||||
multiboot_uint32_t part;
|
||||
};
|
||||
|
||||
struct multiboot_tag_mmap
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t entry_size;
|
||||
multiboot_uint32_t entry_version;
|
||||
struct multiboot_mmap_entry entries[0];
|
||||
};
|
||||
|
||||
struct multiboot_vbe_info_block
|
||||
{
|
||||
multiboot_uint8_t external_specification[512];
|
||||
};
|
||||
|
||||
struct multiboot_vbe_mode_info_block
|
||||
{
|
||||
multiboot_uint8_t external_specification[256];
|
||||
};
|
||||
|
||||
struct multiboot_tag_vbe
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
|
||||
multiboot_uint16_t vbe_mode;
|
||||
multiboot_uint16_t vbe_interface_seg;
|
||||
multiboot_uint16_t vbe_interface_off;
|
||||
multiboot_uint16_t vbe_interface_len;
|
||||
|
||||
struct multiboot_vbe_info_block vbe_control_info;
|
||||
struct multiboot_vbe_mode_info_block vbe_mode_info;
|
||||
};
|
||||
|
||||
struct multiboot_tag_framebuffer_common
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
|
||||
multiboot_uint64_t framebuffer_addr;
|
||||
multiboot_uint32_t framebuffer_pitch;
|
||||
multiboot_uint32_t framebuffer_width;
|
||||
multiboot_uint32_t framebuffer_height;
|
||||
multiboot_uint8_t framebuffer_bpp;
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||
multiboot_uint8_t framebuffer_type;
|
||||
multiboot_uint16_t reserved;
|
||||
};
|
||||
|
||||
struct multiboot_tag_framebuffer
|
||||
{
|
||||
struct multiboot_tag_framebuffer_common common;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||
struct multiboot_color framebuffer_palette[0];
|
||||
};
|
||||
struct
|
||||
{
|
||||
multiboot_uint8_t framebuffer_red_field_position;
|
||||
multiboot_uint8_t framebuffer_red_mask_size;
|
||||
multiboot_uint8_t framebuffer_green_field_position;
|
||||
multiboot_uint8_t framebuffer_green_mask_size;
|
||||
multiboot_uint8_t framebuffer_blue_field_position;
|
||||
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct multiboot_tag_elf_sections
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t num;
|
||||
multiboot_uint32_t entsize;
|
||||
multiboot_uint32_t shndx;
|
||||
char sections[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_apm
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint16_t version;
|
||||
multiboot_uint16_t cseg;
|
||||
multiboot_uint32_t offset;
|
||||
multiboot_uint16_t cseg_16;
|
||||
multiboot_uint16_t dseg;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint16_t cseg_len;
|
||||
multiboot_uint16_t cseg_16_len;
|
||||
multiboot_uint16_t dseg_len;
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi32
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t pointer;
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi64
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint64_t pointer;
|
||||
};
|
||||
|
||||
struct multiboot_tag_smbios
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t major;
|
||||
multiboot_uint8_t minor;
|
||||
multiboot_uint8_t reserved[6];
|
||||
multiboot_uint8_t tables[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_old_acpi
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t rsdp[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_new_acpi
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t rsdp[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_network
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t dhcpack[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi_mmap
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t descr_size;
|
||||
multiboot_uint32_t descr_vers;
|
||||
multiboot_uint8_t efi_mmap[0];
|
||||
};
|
||||
|
||||
#endif /* ! ASM_FILE */
|
357
hal/print.c
357
hal/print.c
|
@ -1,7 +1,6 @@
|
|||
#include "type.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
#include "hal/print.h"
|
||||
#include "hal/cpu.h"
|
||||
#include "common.h"
|
||||
#include "cpu.h"
|
||||
#include "print.h"
|
||||
|
||||
// #define get_column(pos) ((pos) % 80)
|
||||
#define get_row(pos) ((pos) / 80)
|
||||
|
@ -9,200 +8,214 @@
|
|||
|
||||
static uint64 text_pos;
|
||||
|
||||
void SXAPI hal_print_init(void)
|
||||
void
|
||||
hal_print_init(void)
|
||||
{
|
||||
text_pos = 0;
|
||||
text_pos = 0;
|
||||
}
|
||||
|
||||
static void SXAPI halp_print_scroll(void)
|
||||
static void
|
||||
halp_print_scroll(void)
|
||||
{
|
||||
lb_mem_move((void *) (0xb8000 + get_pos(1, 0) * 2), (void *) (0xb8000 + get_pos(0, 0) * 2), (80 * 24) * 2);
|
||||
mem_mv((void *) (0xb8000 + get_pos(1, 0) * 2), (void *) (0xb8000 + get_pos(0, 0) * 2), (80 * 24) * 2);
|
||||
}
|
||||
|
||||
static void SXAPI halp_print_str(char const *str)
|
||||
static void
|
||||
halp_print_str(char const *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (*str != 0)
|
||||
{
|
||||
if (*str == '\n')
|
||||
{
|
||||
text_pos = 80 * (get_row(text_pos) + 1);
|
||||
if (text_pos > 80 * 25 - 1)
|
||||
{
|
||||
//can't hold
|
||||
halp_print_scroll();
|
||||
lb_mem_set((void *) (0xb8000 + 80 * 24 * 2), 0, 80 * 2); // clear last row
|
||||
text_pos = 80 * 24;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (text_pos > 80 * 25 - 1)
|
||||
{
|
||||
//can't hold
|
||||
halp_print_scroll();
|
||||
text_pos = 80 * 24;
|
||||
}
|
||||
*((char *) (0xb8000) + text_pos * 2) = *str;
|
||||
*((char *) (0xb8000) + text_pos * 2 + 1) = 7;
|
||||
str++;
|
||||
text_pos++;
|
||||
}
|
||||
}
|
||||
if (str == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (*str != 0)
|
||||
{
|
||||
if (*str == '\n')
|
||||
{
|
||||
text_pos = 80 * (get_row(text_pos) + 1);
|
||||
if (text_pos > 80 * 25 - 1)
|
||||
{
|
||||
//can't hold
|
||||
halp_print_scroll();
|
||||
mem_set((void *) (0xb8000 + 80 * 24 * 2), 0, 80 * 2); // clear last row
|
||||
text_pos = 80 * 24;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (text_pos > 80 * 25 - 1)
|
||||
{
|
||||
//can't hold
|
||||
halp_print_scroll();
|
||||
text_pos = 80 * 24;
|
||||
}
|
||||
*((char *) (0xb8000) + text_pos * 2) = *str;
|
||||
*((char *) (0xb8000) + text_pos * 2 + 1) = 7;
|
||||
str++;
|
||||
text_pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SXAPI halp_print_uint(uint64 number)
|
||||
static void
|
||||
halp_print_uint(uint64 number)
|
||||
{
|
||||
char arr[21]; // do not need to initialize
|
||||
arr[20] = 0; //zero-terminated
|
||||
uint32 index = 19;
|
||||
uint32 const div = 10;
|
||||
while (1)
|
||||
{
|
||||
uint64 quo = number / div;
|
||||
uint64 rmd = number % div;
|
||||
number = quo;
|
||||
arr[index--] = (char) ('0' + rmd);
|
||||
if (number == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
halp_print_str(&(arr[index + 1]));
|
||||
char arr[21]; // do not need to initialize
|
||||
arr[20] = 0; //zero-terminated
|
||||
uint32 index = 19;
|
||||
uint32 const div = 10;
|
||||
while (1)
|
||||
{
|
||||
uint64 quo = number / div;
|
||||
uint64 rmd = number % div;
|
||||
number = quo;
|
||||
arr[index--] = (char) ('0' + rmd);
|
||||
if (number == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
halp_print_str(&(arr[index + 1]));
|
||||
}
|
||||
|
||||
static void SXAPI halp_print_int(int64 number)
|
||||
static void
|
||||
halp_print_int(int64 number)
|
||||
{
|
||||
char arr[21]; // do not need to initialize
|
||||
arr[20] = 0; //zero-terminated
|
||||
uint32 index = 19;
|
||||
uint32 isNegative = 0;
|
||||
uint32 const div = 10;
|
||||
if (number < 0)
|
||||
{
|
||||
isNegative = 1;
|
||||
number *= -1;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
int64 quo = number / div;
|
||||
int64 rmd = number % div;
|
||||
number = quo;
|
||||
arr[index--] = (char) ('0' + rmd);
|
||||
if (number == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isNegative)
|
||||
{
|
||||
arr[index--] = '-';
|
||||
}
|
||||
halp_print_str(&(arr[index + 1]));
|
||||
char arr[21]; // do not need to initialize
|
||||
arr[20] = 0; //zero-terminated
|
||||
uint32 index = 19;
|
||||
uint32 isNegative = 0;
|
||||
uint32 const div = 10;
|
||||
if (number < 0)
|
||||
{
|
||||
isNegative = 1;
|
||||
number *= -1;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
int64 quo = number / div;
|
||||
int64 rmd = number % div;
|
||||
number = quo;
|
||||
arr[index--] = (char) ('0' + rmd);
|
||||
if (number == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isNegative)
|
||||
{
|
||||
arr[index--] = '-';
|
||||
}
|
||||
halp_print_str(&(arr[index + 1]));
|
||||
}
|
||||
|
||||
static void SXAPI halp_print_hex(uint64 number, uint64 capital)
|
||||
static void
|
||||
halp_print_hex(uint64 number, uint64 capital)
|
||||
{
|
||||
char const lookup_table_cap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
char const lookup_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
char const *const look_up = capital == 1 ? &lookup_table_cap[0] : &lookup_table[0];
|
||||
char arr[17];
|
||||
arr[16] = 0; //zero-terminated
|
||||
uint32 index = 15;
|
||||
uint32 const div = 16;
|
||||
while (1)
|
||||
{
|
||||
uint64 quo = number / div;
|
||||
uint64 rmd = number % div;
|
||||
number = quo;
|
||||
arr[index--] = look_up[rmd];
|
||||
if (number == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
halp_print_str(&(arr[index + 1]));
|
||||
char const lookup_table_cap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
char const lookup_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
char const *const look_up = capital == 1 ? &lookup_table_cap[0] : &lookup_table[0];
|
||||
char arr[17];
|
||||
arr[16] = 0; //zero-terminated
|
||||
uint32 index = 15;
|
||||
uint32 const div = 16;
|
||||
while (1)
|
||||
{
|
||||
uint64 quo = number / div;
|
||||
uint64 rmd = number % div;
|
||||
number = quo;
|
||||
arr[index--] = look_up[rmd];
|
||||
if (number == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
halp_print_str(&(arr[index + 1]));
|
||||
}
|
||||
|
||||
void SXAPI hal_clear_screen(void)
|
||||
void
|
||||
hal_clear_screen(void)
|
||||
{
|
||||
text_pos = 0; // reset text_pos
|
||||
lb_mem_set((void *) 0xb8000, 0, 25 * 80 * 2);
|
||||
text_pos = 0; // reset text_pos
|
||||
mem_set((void *) 0xb8000, 0, 25 * 80 * 2);
|
||||
}
|
||||
|
||||
void SXAPI hal_vprintf(char const *format, va_list args)
|
||||
static void
|
||||
halp_vprintf(char const *format, va_list args)
|
||||
{
|
||||
char buf[2] = {0, 0};
|
||||
int64 d;
|
||||
uint64 u;
|
||||
char *s;
|
||||
char c;
|
||||
for (; *format != '\0'; format++)
|
||||
{
|
||||
if (*format != '%')
|
||||
{
|
||||
buf[0] = *format;
|
||||
halp_print_str(buf);
|
||||
continue;
|
||||
}
|
||||
format++;
|
||||
switch (*format)
|
||||
{
|
||||
case 'd':
|
||||
d = va_arg(args, int64);
|
||||
halp_print_int(d);
|
||||
break;
|
||||
case 'u':
|
||||
u = va_arg(args, uint64);
|
||||
halp_print_uint(u);
|
||||
break;
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
halp_print_str(s);
|
||||
break;
|
||||
case 'c':
|
||||
c = (char) va_arg(args, int64);
|
||||
buf[0] = c;
|
||||
halp_print_str(buf);
|
||||
break;
|
||||
case 'x':
|
||||
u = va_arg(args, uint64);
|
||||
halp_print_hex(u, 0);
|
||||
break;
|
||||
case 'X':
|
||||
u = va_arg(args, uint64);
|
||||
halp_print_hex(u, 1);
|
||||
break;
|
||||
case '%':
|
||||
buf[0] = '%';
|
||||
halp_print_str(buf);
|
||||
break;
|
||||
default:
|
||||
buf[0] = '%';
|
||||
halp_print_str(buf);
|
||||
format--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
char buf[2] = {0, 0};
|
||||
int64
|
||||
d;
|
||||
uint64
|
||||
u;
|
||||
char *s;
|
||||
char c;
|
||||
for (; *format != '\0'; format++)
|
||||
{
|
||||
if (*format != '%')
|
||||
{
|
||||
buf[0] = *format;
|
||||
halp_print_str(buf);
|
||||
continue;
|
||||
}
|
||||
format++;
|
||||
switch (*format)
|
||||
{
|
||||
case 'd':
|
||||
d = va_arg(args, int64);
|
||||
halp_print_int(d);
|
||||
break;
|
||||
case 'u':
|
||||
u = va_arg(args, uint64);
|
||||
halp_print_uint(u);
|
||||
break;
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
halp_print_str(s);
|
||||
break;
|
||||
case 'c':
|
||||
c = (char) va_arg(args, int64);
|
||||
buf[0] = c;
|
||||
halp_print_str(buf);
|
||||
break;
|
||||
case 'x':
|
||||
u = va_arg(args, uint64);
|
||||
halp_print_hex(u, 0);
|
||||
break;
|
||||
case 'X':
|
||||
u = va_arg(args, uint64);
|
||||
halp_print_hex(u, 1);
|
||||
break;
|
||||
case '%':
|
||||
buf[0] = '%';
|
||||
halp_print_str(buf);
|
||||
break;
|
||||
default:
|
||||
buf[0] = '%';
|
||||
halp_print_str(buf);
|
||||
format--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI hal_printf(char const *format, ...)
|
||||
void
|
||||
hal_printf(char const *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
hal_vprintf(format, args);
|
||||
va_end(args);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
halp_vprintf(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void SXAPI hal_assert(uint32 expression, char *message)
|
||||
void
|
||||
hal_assert(uint32 expression, char *message
|
||||
)
|
||||
{
|
||||
if (!expression)
|
||||
{
|
||||
hal_printf("HAL: Assertion failed. Detail: %s", message == NULL ? "NULL" : message);
|
||||
hal_halt_cpu();
|
||||
}
|
||||
if (!expression)
|
||||
{
|
||||
hal_printf("HAL: Assertion failed. Detail: %s", message == NULL ? "NULL" : message);
|
||||
|
||||
hal_halt_cpu();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "common.h"
|
||||
#include "print.h"
|
||||
|
||||
void
|
||||
hal_assert(uint32 expression, char *message);
|
||||
|
||||
void
|
||||
hal_printf(const char *str, ...);
|
||||
|
||||
void
|
||||
hal_clear_screen(void);
|
||||
|
||||
void
|
||||
hal_print_init(void);
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef KERNEL_HAL_MEM_H
|
||||
#define KERNEL_HAL_MEM_H
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Kernel Memory Layout
|
||||
|
@ -33,26 +32,80 @@
|
|||
|
||||
#ifndef ASM_FILE
|
||||
|
||||
#include "type.h"
|
||||
#include "lib/linked_list.h"
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef uint32_t uint32;
|
||||
typedef int32_t int32;
|
||||
typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
typedef uintptr_t uintptr;
|
||||
typedef uint16_t uint16;
|
||||
typedef int16_t int16;
|
||||
typedef uint8_t uint8;
|
||||
typedef int8_t int8;
|
||||
|
||||
typedef _Bool bool;
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
|
||||
#define STRUCT_PACKED __attribute__((packed))
|
||||
|
||||
#define UNREFERENCED(x) {(x) = (x);}
|
||||
|
||||
#define KABI __attribute__((sysv_abi))
|
||||
|
||||
/**
|
||||
* PMM init info
|
||||
* Common macros, etc
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uintptr base;
|
||||
uint64 size;
|
||||
uint32 attr;
|
||||
} pmm_node_t;
|
||||
|
||||
typedef struct
|
||||
#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((uintptr)(member_addr) - (uintptr)(&(((struct_name*)0)->member_name))))
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define SWAP(a, b, T) do { T temp = *(a); *(a) = *(b); *(b) = temp; } while(0);
|
||||
|
||||
uint32
|
||||
lb_rand(void);
|
||||
|
||||
void
|
||||
lb_srand(uint32 _seed);
|
||||
|
||||
void
|
||||
lb_mrand(uint32 max);
|
||||
|
||||
uint64
|
||||
str_len(char const *str);
|
||||
|
||||
|
||||
uint64
|
||||
str_cmp(char const *str1, char const *str2);
|
||||
|
||||
|
||||
void
|
||||
mem_cpy(void *src, void *dst, uint64 size);
|
||||
|
||||
|
||||
void
|
||||
mem_mv(void *src, void *dst, uint64 size);
|
||||
|
||||
|
||||
void
|
||||
mem_set(void *src, uint8 val, uint64 size);
|
||||
|
||||
|
||||
static inline uint64
|
||||
bit_mask(uint32 bit)
|
||||
{
|
||||
uint32 num_of_nodes;
|
||||
pmm_node_t nodes[];
|
||||
} pmm_info_t;
|
||||
|
||||
#endif
|
||||
return (uint64) 1 << bit;
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
bit_field_mask(uint32 low, uint32 high)
|
||||
{
|
||||
return ~(~(uint64) 0 << high << 1) << low;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* HAL Structures
|
||||
*/
|
||||
|
||||
/**
|
||||
* boot_info structure
|
||||
* must NOT use kernel structures
|
||||
*/
|
||||
struct boot_info
|
||||
{
|
||||
struct
|
||||
{
|
||||
char cpu_vendor[13];
|
||||
} cpu_info;
|
||||
|
||||
struct
|
||||
{
|
||||
uintptr krnl_start_vaddr;
|
||||
uintptr krnl_end_vaddr;
|
||||
} mem_info;
|
||||
|
||||
struct intr_info
|
||||
{
|
||||
uint32 timer_intr_vec;
|
||||
uint32 dpc_intr_vec;
|
||||
uint32 page_fault_vec;
|
||||
|
||||
uint32 irql_low;
|
||||
uint32 irql_dpc;
|
||||
uint32 irql_high;
|
||||
} intr_info;
|
||||
};
|
||||
|
||||
/**
|
||||
* HAL functions
|
||||
*/
|
||||
int32 KABI
|
||||
hal_atomic_xchg_32(int32 *target, int32 val);
|
||||
|
||||
int32 KABI
|
||||
hal_atomic_inc_32(int32 *target, int32 increment);
|
||||
|
||||
int32 KABI
|
||||
hal_atomic_cmpxchg_32(int32 *target, int32 compare, int32 val);
|
||||
|
||||
uint32 KABI
|
||||
hal_set_irql(uint32 irql);
|
||||
|
||||
uint32 KABI
|
||||
hal_get_irql(void);
|
||||
|
||||
void KABI
|
||||
hal_halt(void);
|
||||
|
||||
void KABI
|
||||
hal_issue_intr(uint32 core, uint32 vector);
|
||||
|
||||
typedef void (KABI *intr_handler_fp)(uintptr exc_addr, uintptr exc_stack, uint32 error_code);
|
||||
|
||||
void KABI
|
||||
hal_reg_intr(uint32 index, intr_handler_fp handler);
|
||||
|
||||
void KABI
|
||||
hal_dereg_intr(uint32 index);
|
||||
|
||||
typedef void (KABI *exc_handler_fp)(uintptr exc_addr, uintptr exc_stack, uint32 error_code);
|
||||
|
||||
void KABI
|
||||
hal_reg_exc(uint32 exc, exc_handler_fp handler);
|
||||
|
||||
void KABI
|
||||
hal_dereg_exc(uint32 exc);
|
||||
|
||||
uint32 KABI
|
||||
hal_get_core_id(void);
|
||||
|
||||
void KABI
|
||||
ke_main(struct boot_info *boot_info);
|
|
@ -0,0 +1,147 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "kernel/status.h"
|
||||
#include "kernel/lb.h"
|
||||
#include "hal_export.h"
|
||||
|
||||
/**
|
||||
* memory
|
||||
*/
|
||||
void
|
||||
ke_alloc_init(void);
|
||||
|
||||
void *
|
||||
ke_alloc(uint32 size);
|
||||
|
||||
void
|
||||
ke_free(void *ptr);
|
||||
|
||||
|
||||
/**
|
||||
* atomic
|
||||
*/
|
||||
int32
|
||||
ke_atomic_xchg_32(int32 *target, int32 val);
|
||||
|
||||
int32
|
||||
ke_atomic_inc_32(int32 *target, int32 increment);
|
||||
|
||||
int32
|
||||
ke_atmoic_cmpxchg_32(int32 *target, int32 compare, int32 val);
|
||||
|
||||
|
||||
/**
|
||||
* assert
|
||||
*/
|
||||
#define ke_assert(expr) ke_assert_ex(#expr, __FILE__, __LINE__, expr)
|
||||
|
||||
void
|
||||
ke_assert_ex(const char *expr_str, const char *file, int32 line, int32 expr);
|
||||
|
||||
|
||||
/**
|
||||
* bugcheck
|
||||
*/
|
||||
void
|
||||
ke_panic(uint64 reason);
|
||||
|
||||
|
||||
/**
|
||||
* interrupt
|
||||
*/
|
||||
#define IRQL_LOW (0)
|
||||
#define IRQL_DPC (1)
|
||||
#define IRQL_HIGH (2)
|
||||
#define IRQL_NUM (3)
|
||||
|
||||
uint32
|
||||
ke_raise_irql(uint32 irql);
|
||||
|
||||
uint32
|
||||
ke_lower_irql(uint32 irql);
|
||||
|
||||
uint32
|
||||
ke_get_irql(void);
|
||||
|
||||
void
|
||||
ke_issue_intr(uint32 core, uint32 vector);
|
||||
|
||||
void
|
||||
ke_reg_intr(uint32 index, intr_handler_fp handler);
|
||||
|
||||
void
|
||||
ke_dereg_intr(uint32 index);
|
||||
|
||||
#define EXC_UNRCVY (0)
|
||||
#define EXC_DIV (1)
|
||||
#define EXC_PROT (2)
|
||||
#define EXC_OP (3)
|
||||
#define EXC_PF (4)
|
||||
#define EXC_UNSUP (5)
|
||||
#define EXC_DEBUG (6)
|
||||
void
|
||||
ke_reg_exc(uint32 exc, exc_handler_fp handler);
|
||||
|
||||
void
|
||||
ke_dereg_exc(uint32 exc);
|
||||
|
||||
uint32
|
||||
ke_get_core_id(void);
|
||||
|
||||
|
||||
/**
|
||||
* print
|
||||
*/
|
||||
void
|
||||
ke_printf(const char *str, ...);
|
||||
|
||||
void
|
||||
ke_vprintf(const char *str, va_list args);
|
||||
|
||||
|
||||
/**
|
||||
* spinlock
|
||||
*/
|
||||
struct spin_lock
|
||||
{
|
||||
int32 val;
|
||||
};
|
||||
|
||||
void
|
||||
ke_spin_init(struct spin_lock *lock);
|
||||
|
||||
void
|
||||
ke_spin_lock(struct spin_lock *lock);
|
||||
|
||||
void
|
||||
ke_spin_unlock(struct spin_lock *lock);
|
||||
|
||||
|
||||
/**
|
||||
* rwwlock
|
||||
*/
|
||||
struct rwwlock
|
||||
{
|
||||
struct spin_lock w_mutex;
|
||||
struct spin_lock r_mutex;
|
||||
struct spin_lock res_lock;
|
||||
struct spin_lock r_try;
|
||||
uint32 reader_ct;
|
||||
uint32 writer_ct;
|
||||
};
|
||||
|
||||
void
|
||||
ke_rww_init(struct rwwlock *lock);
|
||||
|
||||
void
|
||||
ke_rww_r_lock(struct rwwlock *lock);
|
||||
|
||||
void
|
||||
ke_rww_r_unlock(struct rwwlock *lock);
|
||||
|
||||
void
|
||||
ke_rww_w_lock(struct rwwlock *lock);
|
||||
|
||||
void
|
||||
ke_rww_w_unlock(struct rwwlock *lock);
|
|
@ -0,0 +1,218 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "kernel/status.h"
|
||||
|
||||
/*
|
||||
//Not used for now
|
||||
//BST interface
|
||||
|
||||
struct bstree;
|
||||
|
||||
struct bstree_node
|
||||
{
|
||||
struct bstree_node *left;
|
||||
struct bstree_node *treenode;
|
||||
};
|
||||
|
||||
struct bstree_impl
|
||||
{
|
||||
struct bstree_node *(KAPI *t_search)(struct bstree *tree, struct bstree_node *entry);
|
||||
|
||||
k_status (KAPI *t_insert)(struct bstree *tree, struct bstree_node *entry);
|
||||
|
||||
k_status (KAPI *t_delete)(struct bstree *tree, struct bstree_node *entry, struct bstree_node **out);
|
||||
|
||||
int32 (KAPI *t_size)(struct bstree *tree);
|
||||
|
||||
struct bstree_node *(KAPI *t_max)(struct bstree *tree);
|
||||
|
||||
struct bstree_node *(KAPI *t_min)(struct bstree *tree);
|
||||
|
||||
struct bstree_node *(KAPI *t_prev)(struct bstree_node *tree);
|
||||
|
||||
struct bstree_node *(KAPI *t_next)(struct bstree_node *tree);
|
||||
|
||||
k_status (KAPI *t_validate)(struct bstree *tree);
|
||||
};
|
||||
|
||||
typedef int32 (KAPI *bstree_cmp_fp)(struct bstree_node *left, struct bstree_node *treenode);
|
||||
|
||||
struct bstree
|
||||
{
|
||||
struct bstree_impl *impl;
|
||||
struct tree_node *root;
|
||||
bstree_cmp_fp cmp;
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* AVL tree
|
||||
*/
|
||||
struct atree_node
|
||||
{
|
||||
struct atree_node *left;
|
||||
struct atree_node *right;
|
||||
int32 height;
|
||||
};
|
||||
|
||||
/**
|
||||
* A comparison function between self (yours) and treenode (tree's)
|
||||
* Returns:
|
||||
* < 0 if treenode < self
|
||||
* = 0 if treenode = self
|
||||
* > 0 if treenode > self
|
||||
*/
|
||||
typedef int32 (*atree_cmp_fp)(
|
||||
struct atree_node *tree_node,
|
||||
struct atree_node *self);
|
||||
|
||||
struct atree
|
||||
{
|
||||
atree_cmp_fp cmpf;
|
||||
struct atree_node *root;
|
||||
};
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_search(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry);
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_insert(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry);
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_delete(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry);
|
||||
|
||||
|
||||
void
|
||||
lb_atree_init(
|
||||
struct atree *tree,
|
||||
atree_cmp_fp compare);
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_max(
|
||||
struct atree *tree);
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_min(
|
||||
struct atree *tree);
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_next(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry);
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_prev(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry);
|
||||
|
||||
bool
|
||||
lb_atree_validate(
|
||||
struct atree *tree);
|
||||
|
||||
uint32
|
||||
lb_atree_size(
|
||||
struct atree *tree);
|
||||
|
||||
|
||||
/**
|
||||
* Linked list
|
||||
*/
|
||||
|
||||
struct llist_node
|
||||
{
|
||||
struct llist_node *prev;
|
||||
struct llist_node *next;
|
||||
};
|
||||
|
||||
struct llist
|
||||
{
|
||||
struct llist_node *head;
|
||||
struct llist_node *tail;
|
||||
uint32 size;
|
||||
};
|
||||
|
||||
void
|
||||
lb_llist_init(struct llist *list);
|
||||
|
||||
uint32
|
||||
lb_llist_size(struct llist *list);
|
||||
|
||||
void
|
||||
lb_llist_push_front(struct llist *list, struct llist_node *node);
|
||||
|
||||
void
|
||||
lb_llist_push_back(struct llist *list, struct llist_node *node);
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_pop_front(struct llist *list);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_pop_back(struct llist *list);
|
||||
|
||||
void
|
||||
lb_llist_insert_by_idx(struct llist *list, uint32 index, struct llist_node *node);
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_remove_by_idx(struct llist *list, uint32 index);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_get(struct llist *list, uint32 index);
|
||||
|
||||
|
||||
void
|
||||
lb_llist_insert_by_ref(struct llist *list, struct llist_node *cur_node, struct llist_node *new_node);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_remove_by_ref(struct llist *list, struct llist_node *node);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_next(struct llist_node *node);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_prev(struct llist_node *node);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_first(struct llist *list);
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_last(struct llist *list);
|
||||
|
||||
|
||||
/**
|
||||
* SALLOC
|
||||
*/
|
||||
|
||||
void
|
||||
lb_salloc_init(void *base, uint32 size);
|
||||
|
||||
void *
|
||||
lb_salloc(void *base, uint32 size);
|
||||
|
||||
void
|
||||
lb_sfree(void *base, void *ptr);
|
||||
|
||||
bool
|
||||
lb_salloc_assert(void *base, const uint32 *blk_size, const bool *blk_free, uint32 size);
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "kernel/status.h"
|
||||
#include "kernel/lb.h"
|
||||
#include "kernel/ke.h"
|
||||
|
||||
/**
|
||||
* physical page allocation
|
||||
*/
|
||||
k_status
|
||||
mm_alloc_page(uintptr *out);
|
||||
|
||||
k_status
|
||||
mm_free_page(uintptr base);
|
||||
|
||||
k_status
|
||||
mm_query_page_attr(uintptr base, int32 *out);
|
||||
|
||||
k_status
|
||||
mm_pmm_init(struct boot_info *info);
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "kernel/status.h"
|
||||
#include "kernel/lb.h"
|
||||
|
||||
typedef uint32 k_ident;
|
||||
|
||||
typedef void (*ref_free_fp)(void *);
|
||||
|
||||
struct ref_node
|
||||
{
|
||||
int32 ref_count;
|
||||
ref_free_fp f_free;
|
||||
};
|
||||
|
||||
struct ident_node
|
||||
{
|
||||
struct atree_node tree_node;
|
||||
k_ident ident;
|
||||
struct ref_node *obj;
|
||||
ref_free_fp free_routine;
|
||||
};
|
||||
|
||||
//
|
||||
// All functions are sx since users or kernel devs should not be
|
||||
// specifying where the allocations take place
|
||||
//
|
||||
|
||||
k_status
|
||||
rf_ref_init(void);
|
||||
|
||||
k_status
|
||||
rf_ref_node_init(struct ref_node *rf_node, ref_free_fp free_func);
|
||||
|
||||
k_status
|
||||
rf_ref_obj(struct ref_node *rf_node);
|
||||
|
||||
k_status
|
||||
rf_deref_obj(struct ref_node *rf_node);
|
||||
|
||||
k_status
|
||||
rf_open_obj_by_ident(k_ident id, struct ref_node **out);
|
||||
|
||||
k_status
|
||||
rf_ident_create(struct ref_node *rf_node, struct ident_node *id_node, k_ident *out);
|
||||
|
||||
k_status
|
||||
rf_ident_close(k_ident id);
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef uint32 k_status;
|
||||
|
||||
/**
|
||||
* Specific error codes
|
||||
*/
|
||||
|
||||
#define STATUS_SUCCESS (0x0)
|
||||
|
||||
#define STATUS_INVALID_ARGS (0x1)
|
||||
#define STATUS_NO_MEM (0x2)
|
||||
#define STATUS_UNINITIALIZED (0x3)
|
||||
#define STATUS_DUPLICATE (0x4)
|
||||
|
||||
#define SX_SUCCESS(val) ((val) == (STATUS_SUCCESS))
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef HAL_BOOT_H
|
||||
#define HAL_BOOT_H
|
||||
|
||||
#include "kernel/hal/boot.h"
|
||||
|
||||
#endif
|
|
@ -1,82 +0,0 @@
|
|||
#ifndef HAL_CPU_H
|
||||
#define HAL_CPU_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/atomic.h"
|
||||
|
||||
#define HAL_CORE_COUNT 1
|
||||
|
||||
|
||||
struct STRUCT_PACKED hal_gdt_ptr
|
||||
{
|
||||
uint16 limit;
|
||||
uint64 base;
|
||||
};
|
||||
|
||||
struct STRUCT_PACKED hal_idt_ptr
|
||||
{
|
||||
uint16 limit;
|
||||
uint64 base;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* CPU Instructions
|
||||
*/
|
||||
extern void SXAPI hal_cpuid(uint32 *eax, uint32 *ebx, uint32 *ecx, uint32 *edx);
|
||||
|
||||
extern void SXAPI hal_halt_cpu(void);
|
||||
|
||||
extern void SXAPI hal_enable_interrupt(void);
|
||||
|
||||
extern void SXAPI hal_disable_interrupt(void);
|
||||
|
||||
|
||||
/**
|
||||
* IO Port Operations
|
||||
*/
|
||||
|
||||
extern int8 SXAPI hal_read_port_8(uint16 port);
|
||||
|
||||
extern int16 SXAPI hal_read_port_16(uint16 port);
|
||||
|
||||
extern int32 SXAPI hal_read_port_32(uint16 port);
|
||||
|
||||
extern void SXAPI hal_write_port_8(uint16 port, uint8 data);
|
||||
|
||||
extern void SXAPI hal_write_port_16(uint16 port, uint16 data);
|
||||
|
||||
extern void SXAPI hal_write_port_32(uint16 port, uint32 data);
|
||||
|
||||
|
||||
/**
|
||||
* CPU Structure Operations
|
||||
*/
|
||||
|
||||
extern void SXAPI hal_flush_gdt(struct hal_gdt_ptr *gdt_ptr, uint64 code_slct, uint64 data_slct);
|
||||
|
||||
extern void SXAPI hal_flush_tlb(void);
|
||||
|
||||
extern void SXAPI hal_flush_idt(struct hal_idt_ptr *idt_ptr);
|
||||
|
||||
extern void SXAPI hal_read_idt(struct hal_idt_ptr **idt_ptr);
|
||||
|
||||
/**
|
||||
* Control Register Operations
|
||||
*/
|
||||
#define MSR_IA32_APIC_BASE 0x1B
|
||||
|
||||
extern void SXAPI hal_read_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||
|
||||
extern void SXAPI hal_write_msr(uint32 *ecx, uint32 *edx, uint32 *eax);
|
||||
|
||||
extern void SXAPI hal_write_cr3(uint64 base);
|
||||
|
||||
extern uint64 SXAPI hal_read_cr3(void);
|
||||
|
||||
extern void SXAPI hal_write_cr8(uint64 pri);
|
||||
|
||||
extern uint64 SXAPI hal_read_cr8(void);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,576 +0,0 @@
|
|||
#ifndef HAL_INTR_H
|
||||
#define HAL_INTR_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/intr.h"
|
||||
|
||||
/**
|
||||
* Interrupt context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const uint64 rip;
|
||||
const uint64 cs;
|
||||
const uint64 rflags;
|
||||
const uint64 rsp;
|
||||
const uint64 ss;
|
||||
} hal_interrupt_context_t;
|
||||
|
||||
|
||||
/**
|
||||
* IDT Defns
|
||||
*/
|
||||
#define GATE_DPL_0 (0ull << 13)
|
||||
#define GATE_DPL_1 (1ull << 13)
|
||||
#define GATE_DPL_2 (2ull << 13)
|
||||
#define GATE_DPL_3 (3ull << 13)
|
||||
#define GATE_PRESENT (1ull << 15)
|
||||
#define GATE_TYPE_CALL (12ull << 8)
|
||||
#define GATE_TYPE_INTERRUPT (14ull << 8)
|
||||
#define GATE_TYPE_TRAP (15ull << 8)
|
||||
|
||||
#define IDT_ENTRY_NUM 256
|
||||
#define IDT_ENTRY_SIZE 16
|
||||
|
||||
/**
|
||||
* intr.h
|
||||
*/
|
||||
|
||||
int32 SXAPI hal_interrupt_init(void);
|
||||
|
||||
void SXAPI hal_write_gate(void *const gate,
|
||||
uint64 const offset,
|
||||
uint32 const selector,
|
||||
uint32 const attr);
|
||||
|
||||
void SXAPI hal_set_interrupt_handler(uint64 index, void (*handler)(void));
|
||||
|
||||
|
||||
/**
|
||||
* Dispatchers for asm code
|
||||
*/
|
||||
void SXAPI hal_interrupt_dispatcher(uint64 int_vec, hal_interrupt_context_t *context);
|
||||
|
||||
void SXAPI hal_exception_dispatcher(uint64 exc_vec, hal_interrupt_context_t *context, uint64 errorcode);
|
||||
|
||||
|
||||
/**
|
||||
* System exception Handlers
|
||||
*/
|
||||
extern SXAPI void hal_interrupt_handler_0(void);
|
||||
|
||||
extern SXAPI void hal_interrupt_handler_1(void);
|
||||
|
||||
extern SXAPI void hal_interrupt_handler_2(void);
|
||||
|
||||
extern SXAPI void hal_interrupt_handler_3(void);
|
||||
|
||||
extern SXAPI void hal_interrupt_handler_4(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_5(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_6(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_7(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_8(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_9(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_10(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_11(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_12(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_13(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_14(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_15(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_16(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_17(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_18(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_19(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_20(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_21(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_22(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_23(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_24(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_25(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_26(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_27(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_28(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_29(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_30(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_31(void);
|
||||
|
||||
/**
|
||||
* Kernel defined interrupt handlers
|
||||
*/
|
||||
extern void SXAPI hal_interrupt_handler_32(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_33(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_34(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_35(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_36(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_37(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_38(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_39(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_40(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_41(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_42(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_43(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_44(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_45(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_46(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_47(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_48(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_49(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_50(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_51(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_52(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_53(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_54(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_55(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_56(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_57(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_58(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_59(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_60(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_61(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_62(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_63(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_64(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_65(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_66(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_67(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_68(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_69(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_70(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_71(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_72(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_73(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_74(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_75(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_76(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_77(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_78(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_79(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_80(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_81(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_82(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_83(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_84(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_85(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_86(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_87(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_88(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_89(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_90(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_91(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_92(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_93(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_94(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_95(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_96(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_97(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_98(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_99(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_100(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_101(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_102(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_103(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_104(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_105(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_106(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_107(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_108(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_109(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_110(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_111(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_112(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_113(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_114(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_115(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_116(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_117(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_118(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_119(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_120(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_121(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_122(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_123(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_124(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_125(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_126(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_127(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_128(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_129(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_130(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_131(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_132(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_133(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_134(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_135(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_136(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_137(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_138(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_139(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_140(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_141(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_142(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_143(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_144(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_145(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_146(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_147(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_148(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_149(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_150(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_151(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_152(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_153(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_154(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_155(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_156(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_157(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_158(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_159(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_160(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_161(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_162(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_163(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_164(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_165(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_166(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_167(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_168(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_169(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_170(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_171(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_172(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_173(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_174(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_175(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_176(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_177(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_178(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_179(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_180(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_181(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_182(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_183(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_184(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_185(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_186(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_187(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_188(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_189(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_190(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_191(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_192(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_193(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_194(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_195(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_196(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_197(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_198(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_199(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_200(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_201(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_202(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_203(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_204(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_205(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_206(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_207(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_208(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_209(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_210(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_211(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_212(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_213(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_214(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_215(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_216(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_217(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_218(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_219(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_220(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_221(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_222(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_223(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_224(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_225(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_226(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_227(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_228(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_229(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_230(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_231(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_232(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_233(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_234(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_235(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_236(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_237(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_238(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_239(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_240(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_241(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_242(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_243(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_244(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_245(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_246(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_247(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_248(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_249(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_250(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_251(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_252(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_253(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_254(void);
|
||||
|
||||
extern void SXAPI hal_interrupt_handler_255(void);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef HAL_PRINT_H
|
||||
#define HAL_PRINT_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/print.h"
|
||||
|
||||
void SXAPI hal_assert(uint32 expression, char *message);
|
||||
|
||||
void SXAPI hal_printf(const char *str, ...);
|
||||
|
||||
void SXAPI hal_clear_screen(void);
|
||||
|
||||
void SXAPI hal_print_init(void);
|
||||
|
||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef KERNEL_HAL_ATOMIC_H
|
||||
#define KERNEL_HAL_ATOMIC_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
/**
|
||||
* Atomic operations
|
||||
*/
|
||||
|
||||
extern int32 SXAPI hal_interlocked_exchange_32(int32 *target, int32 val);
|
||||
|
||||
extern int32 SXAPI hal_interlocked_increment_32(int32 *target, int32 increment);
|
||||
|
||||
extern int32 SXAPI hal_interlocked_compare_exchange_32(int32 *target, int32 compare, int32 val);
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef KERNEL_HAL_BOOT_H
|
||||
#define KERNEL_HAL_BOOT_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/intr.h"
|
||||
#include "kernel/hal/mem.h"
|
||||
#include "status.h"
|
||||
|
||||
/**
|
||||
* Required OS boot info
|
||||
*/
|
||||
|
||||
struct boot_info
|
||||
{
|
||||
void *krnl_end;
|
||||
struct intr_info intr_info;
|
||||
char cpu_vd_str[13];
|
||||
};
|
||||
|
||||
sx_status SXAPI hal_init(void *m_info);
|
||||
|
||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||
#ifndef KERNEL_HAL_INTR_H
|
||||
#define KERNEL_HAL_INTR_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
/**
|
||||
* IRQL Definitions
|
||||
*/
|
||||
typedef uint32 k_irql;
|
||||
#define IRQL_DISABLED_LEVEL (1ul << 3)
|
||||
#define IRQL_DPC_LEVEL (1ul << 2)
|
||||
#define IRQL_APC_LEVEL (1ul << 1)
|
||||
#define IRQL_PASSIVE_LEVEL (1ul << 0)
|
||||
|
||||
k_irql SXAPI hal_set_irql(k_irql irql);
|
||||
|
||||
k_irql SXAPI hal_get_irql(void);
|
||||
|
||||
uint32 SXAPI hal_get_core_id(void);
|
||||
|
||||
void SXAPI hal_issue_interrupt(uint32 target_core, uint32 vector);
|
||||
|
||||
/**
|
||||
* Interrupt Handler Registration
|
||||
*/
|
||||
struct intr_info
|
||||
{
|
||||
uint32 timer_intr_vec;
|
||||
uint32 apc_intr_vec;
|
||||
uint32 dpc_intr_vec;
|
||||
};
|
||||
|
||||
typedef void (SXAPI *intr_handler)(void *context, void *intr_stack);
|
||||
|
||||
void SXAPI hal_register_interrupt_handler(uint32 coreid, uint32 index, intr_handler handler, void *context);
|
||||
|
||||
void SXAPI hal_deregister_interrupt_handler(uint32 coreid, uint32 index);
|
||||
|
||||
/**
|
||||
* Exception Handler Registration
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
unrecoverable_exc,
|
||||
div_by_zero_exc,
|
||||
general_protection_exc,
|
||||
invalid_op_exc,
|
||||
page_fault_exc,
|
||||
unsupported_exc,
|
||||
debug_exc
|
||||
} exc_type_t;
|
||||
|
||||
typedef void (SXAPI *exc_handler)(uint64 exc_addr, uint64 exc_stack, uint64 error_code);
|
||||
|
||||
void SXAPI hal_register_exception_handler(uint32 coreid, uint32 index, exc_handler handler);
|
||||
|
||||
void SXAPI hal_deregister_exception_handler(uint32 coreid, uint32 index);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef KERNEL_HAL_PRINT_H
|
||||
#define KERNEL_HAL_PRINT_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
void SXAPI hal_vprintf(const char *str, va_list args);
|
||||
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef KERNEL_KE_ALLOC_H
|
||||
#define KERNEL_KE_ALLOC_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
void SXAPI ke_alloc_init(void);
|
||||
|
||||
void *SXAPI ke_alloc(uint32 size);
|
||||
|
||||
void SXAPI ke_free(void *ptr);
|
||||
|
||||
#endif
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef KERNEL_KE_ASSERT_H
|
||||
#define KERNEL_KE_ASSERT_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
void SXAPI ke_assert_ex(const char *expr_str, const char *file, int32 line, int32 expr);
|
||||
|
||||
#define ke_assert(expr) ke_assert_ex(#expr, __FILE__, __LINE__, expr)
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef KERNEL_KE_ATOMIC_H
|
||||
#define KERNEL_KE_ATOMIC_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/atomic.h"
|
||||
|
||||
int32 SXAPI ke_interlocked_exchange_32(int32 *target, int32 val);
|
||||
|
||||
int32 SXAPI ke_interlocked_increment_32(int32 *target, int32 increment);
|
||||
|
||||
int32 SXAPI ke_interlocked_compare_exchange_32(int32 *target, int32 compare, int32 val);
|
||||
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef KERNEL_KE_BOOT_H
|
||||
#define KERNEL_KE_BOOT_H
|
||||
|
||||
#include "kernel/hal/boot.h"
|
||||
|
||||
void SXAPI ke_main(struct boot_info *boot_info);
|
||||
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef KERNEL_KE_BUG_CHECK_H
|
||||
#define KERNEL_KE_BUG_CHECK_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
#define BUG_CHECK_IRQL_MISMATCH 0
|
||||
#define BUG_CHECK_PMM_UNALIGNED 1
|
||||
|
||||
void SXAPI ke_panic(uint64 reason);
|
||||
|
||||
void SXAPI ke_trap(void);
|
||||
|
||||
#endif
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef KERNEL_KE_INTR_H
|
||||
#define KERNEL_KE_INTR_H
|
||||
|
||||
#include "kernel/hal/intr.h"
|
||||
#include "type.h"
|
||||
|
||||
k_irql SXAPI ke_raise_irql(k_irql irql);
|
||||
|
||||
k_irql SXAPI ke_lower_irql(k_irql irql);
|
||||
|
||||
uint32 SXAPI ke_get_current_core(void);
|
||||
|
||||
k_irql SXAPI ke_get_irql(void);
|
||||
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef KERNEL_KE_PRINT_H
|
||||
#define KERNEL_KE_PRINT_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/hal/print.h"
|
||||
|
||||
void SXAPI ke_printf(const char *str, ...);
|
||||
|
||||
void SXAPI ke_vprintf(const char *str, va_list args);
|
||||
|
||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef KERNEL_KE_RWLOCK_H
|
||||
#define KERNEL_KE_RWLOCK_H
|
||||
|
||||
#include "kernel/ke/spin_lock.h"
|
||||
#include "type.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
k_spin_lock_t w_mutex;
|
||||
k_spin_lock_t r_mutex;
|
||||
k_spin_lock_t res_lock;
|
||||
k_spin_lock_t r_try;
|
||||
uint32 reader_ct;
|
||||
uint32 writer_ct;
|
||||
} k_rwwlock_t;
|
||||
|
||||
void SXAPI ke_rwwlock_init(k_rwwlock_t *lock);
|
||||
|
||||
void SXAPI ke_rwwlock_reader_lock(k_rwwlock_t *lock);
|
||||
|
||||
void SXAPI ke_rwwlock_reader_unlock(k_rwwlock_t *lock);
|
||||
|
||||
void SXAPI ke_rwwlock_writer_lock(k_rwwlock_t *lock);
|
||||
|
||||
void SXAPI ke_rwwlock_writer_unlock(k_rwwlock_t *lock);
|
||||
|
||||
k_irql SXAPI ke_rwwlock_reader_lock_raise_irql(k_rwwlock_t *lock, k_irql irql);
|
||||
|
||||
void SXAPI ke_rwwlock_reader_unlock_lower_irql(k_rwwlock_t *lock, k_irql irql);
|
||||
|
||||
k_irql SXAPI ke_rwwlock_writer_lock_raise_irql(k_rwwlock_t *lock, k_irql irql);
|
||||
|
||||
void SXAPI ke_rwwlock_writer_unlock_lower_irql(k_rwwlock_t *lock, k_irql irql);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef KERNEL_KE_SPIN_LOCK_H
|
||||
#define KERNEL_KE_SPIN_LOCK_H
|
||||
|
||||
#include "type.h"
|
||||
#include "kernel/ke/intr.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 val;
|
||||
} k_spin_lock_t;
|
||||
|
||||
void SXAPI ke_spin_lock_init(k_spin_lock_t *lock);
|
||||
|
||||
void SXAPI ke_spin_lock(k_spin_lock_t *lock);
|
||||
|
||||
void SXAPI ke_spin_unlock(k_spin_lock_t *lock);
|
||||
|
||||
k_irql SXAPI ke_spin_lock_raise_irql(k_spin_lock_t *lock, k_irql irql);
|
||||
|
||||
void SXAPI ke_spin_unlock_lower_irql(k_spin_lock_t *lock, k_irql irql);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef KERNEL_MM_MEM_H
|
||||
#define KERNEL_MM_MEM_H
|
||||
|
||||
#include "kernel/hal/mem.h"
|
||||
|
||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||
#ifndef KERNEL_MM_PMM_H
|
||||
#define KERNEL_MM_PMM_H
|
||||
|
||||
#include "type.h"
|
||||
#include "lib/avl_tree.h"
|
||||
#include "lib/linked_list.h"
|
||||
#include "kernel/mm/mem.h"
|
||||
#include "kernel/ke/atomic.h"
|
||||
#include "status.h"
|
||||
|
||||
//#define PMM_PAGE_ATTR_FREE_BIT 0
|
||||
//#define PMM_PAGE_ATTR_PAGED_BIT 1
|
||||
//
|
||||
//typedef struct
|
||||
//{
|
||||
// uint32 attr;
|
||||
//} k_physical_page_attr_t;
|
||||
|
||||
|
||||
sx_status SXAPI sx_pmm_init(pmm_info_t *info);
|
||||
|
||||
sx_status SXAPI mm_alloc_page(uintptr *out);
|
||||
|
||||
sx_status SXAPI mm_free_page(uintptr base);
|
||||
|
||||
sx_status SXAPI mm_query_page_attr(uintptr base,
|
||||
int32 *out);
|
||||
|
||||
// TODO: implement these somehow, i might just reserve the first 16MB for these
|
||||
int32 SXAPI mm_alloc_contiguous_pages(uint64 num_of_page,
|
||||
uintptr highest_p_addr,
|
||||
uintptr *out);
|
||||
|
||||
int32 SXAPI mm_free_contiguous_pages(uintptr base);
|
||||
|
||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef KERNEL_RF_REF_H
|
||||
#define KERNEL_RF_REF_H
|
||||
|
||||
#include "type.h"
|
||||
#include "status.h"
|
||||
|
||||
typedef uint32 handle_t;
|
||||
|
||||
typedef void (SXAPI *ref_free_func)(void*);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32 ref_count;
|
||||
ref_free_func free_routine;
|
||||
} ref_node_t;
|
||||
|
||||
#define K_HANDLE_BASE (0x80000000ul)
|
||||
|
||||
//
|
||||
// All functions are sx since users or kernel devs should not be
|
||||
// specifying where the allocations take place
|
||||
//
|
||||
|
||||
sx_status SXAPI rf_reference_setup(void);
|
||||
|
||||
sx_status SXAPI rf_reference_create(ref_node_t *ref,
|
||||
ref_free_func free_func);
|
||||
|
||||
sx_status SXAPI rf_reference_obj(ref_node_t *ref);
|
||||
|
||||
sx_status SXAPI rf_dereference_obj(ref_node_t *ref);
|
||||
|
||||
// HANDLES
|
||||
sx_status SXAPI sx_open_obj_by_handle(handle_t handle, ref_node_t **out);
|
||||
|
||||
sx_status SXAPI sx_create_handle(ref_node_t *ref, handle_t *out);
|
||||
|
||||
sx_status SXAPI sx_close_handle(handle_t handle);
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef LIB_AVL_TREE_H
|
||||
#define LIB_AVL_TREE_H
|
||||
|
||||
#include "type.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
|
||||
struct avl_tree_node
|
||||
{
|
||||
struct avl_tree_node *left;
|
||||
struct avl_tree_node *right;
|
||||
struct avl_tree_node *parent;
|
||||
|
||||
int32 height;
|
||||
};
|
||||
|
||||
typedef int32 (SXAPI *avl_tree_compare_func)(struct avl_tree_node *left, struct avl_tree_node *right);
|
||||
|
||||
/*
|
||||
* A comparison function between tree_node and your_node
|
||||
* Returns:
|
||||
* < 0 if tree_node < your_node
|
||||
* = 0 if tree_node == your_node
|
||||
* > 0 if tree_node > your_node
|
||||
*/
|
||||
struct avl_tree
|
||||
{
|
||||
avl_tree_compare_func compare;
|
||||
struct avl_tree_node *root;
|
||||
};
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_search(struct avl_tree *tree, struct avl_tree_node *entry);
|
||||
|
||||
void SXAPI lb_avl_tree_insert(struct avl_tree *tree, struct avl_tree_node *entry);
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_delete(struct avl_tree *tree, struct avl_tree_node *entry);
|
||||
|
||||
void SXAPI lb_avl_tree_init(struct avl_tree *tree, avl_tree_compare_func compare);
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_largest(struct avl_tree *tree);
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_smallest(struct avl_tree *tree);
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_larger(struct avl_tree_node *entry);
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_smaller(struct avl_tree_node *entry);
|
||||
|
||||
bool SXAPI lb_avl_tree_validate(struct avl_tree *tree);
|
||||
|
||||
int32 SXAPI lb_avl_tree_size(struct avl_tree *tree);
|
||||
|
||||
#endif
|
|
@ -1,65 +0,0 @@
|
|||
#ifndef LIB_LINKED_LIST_H
|
||||
#define LIB_LINKED_LIST_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
struct linked_list_node
|
||||
{
|
||||
struct linked_list_node *prev;
|
||||
struct linked_list_node *next;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @returns 0 if they are equal
|
||||
* @param node each node in the list that will compare to arg
|
||||
* @param arg supplied by user
|
||||
*/
|
||||
typedef int32 (SXAPI *linked_list_cmp_func)(struct linked_list_node *node, void *arg);
|
||||
|
||||
struct linked_list
|
||||
{
|
||||
struct linked_list_node *head;
|
||||
struct linked_list_node *tail;
|
||||
int32 size;
|
||||
};
|
||||
|
||||
/* Linked list interfaces */
|
||||
|
||||
void SXAPI lb_linked_list_init(struct linked_list *list);
|
||||
|
||||
int32 SXAPI lb_linked_list_size(struct linked_list *list);
|
||||
|
||||
void SXAPI lb_linked_list_push_front(struct linked_list *list, struct linked_list_node *node);
|
||||
|
||||
void SXAPI lb_linked_list_push_back(struct linked_list *list, struct linked_list_node *node);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_pop_front(struct linked_list *list);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_pop_back(struct linked_list *list);
|
||||
|
||||
void SXAPI lb_linked_list_insert_by_idx(struct linked_list *list, int32 index, struct linked_list_node *node);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_remove_by_idx(struct linked_list *list, int32 index);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_get(struct linked_list *list, int32 index);
|
||||
|
||||
struct linked_list_node *
|
||||
SXAPI lb_linked_list_search(struct linked_list *list, void *obj, linked_list_cmp_func cmp_func);
|
||||
|
||||
/* Linked list node interfaces */
|
||||
|
||||
void SXAPI lb_linked_list_insert_by_ref(struct linked_list *list, struct linked_list_node *cur_node,
|
||||
struct linked_list_node *new_node);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_remove_by_ref(struct linked_list *list, struct linked_list_node *node);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_next(struct linked_list_node *node);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_prev(struct linked_list_node *node);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_first(struct linked_list *list);
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_last(struct linked_list *list);
|
||||
|
||||
#endif
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef LIB_SALLOC_H
|
||||
#define LIB_SALLOC_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
void SXAPI lb_salloc_init(void *base, uint32 size);
|
||||
|
||||
void *SXAPI lb_salloc(void *base, uint32 size);
|
||||
|
||||
void SXAPI lb_sfree(void *base, void *ptr);
|
||||
|
||||
bool SXAPI lb_salloc_assert(void *base, const uint32 *blk_size, const bool *blk_free, uint32 size);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,132 +0,0 @@
|
|||
#ifndef LIB_SXTDLIB_H
|
||||
#define LIB_SXTDLIB_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
uint32 SXAPI lb_rand(void);
|
||||
|
||||
void SXAPI lb_srand(uint32 _seed);
|
||||
|
||||
void SXAPI lb_mrand(uint32 max);
|
||||
|
||||
uint64 SXAPI lb_str_len(char const *str);
|
||||
|
||||
uint64 SXAPI lb_str_cmp(char const *str1, char const *str2);
|
||||
|
||||
void SXAPI lb_mem_copy(void *src, void *dst, uint64 size);
|
||||
|
||||
void SXAPI lb_mem_move(void *src, void *dst, uint64 size);
|
||||
|
||||
void SXAPI lb_mem_set(void *src, uint8 const val, uint64 size);
|
||||
|
||||
static inline uint64 SXAPI lb_align_down(uint64 val, uint64 alignment)
|
||||
{
|
||||
return (val / alignment) * alignment;
|
||||
}
|
||||
|
||||
static inline uint64 SXAPI lb_align_up(uint64 val, uint64 alignment)
|
||||
{
|
||||
return ((((val) % (alignment)) == 0) ? (((val) / (alignment)) * (alignment)) : (
|
||||
(((val) / (alignment)) * (alignment)) + 1));
|
||||
}
|
||||
|
||||
static inline uint64 SXAPI lb_is_overlap(uint64 x1, uint64 x2, uint64 y1, uint64 y2)
|
||||
{
|
||||
return ((x1 <= y2) && (y1 <= x2)) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
static inline int64 SXAPI lb_max_64(int64 a, int64 b)
|
||||
{
|
||||
return (a) > (b) ? a : b;
|
||||
}
|
||||
|
||||
static inline int64 SXAPI lb_min_64(int64 a, int64 b)
|
||||
{
|
||||
return (a) < (b) ? a : b;
|
||||
}
|
||||
|
||||
static inline int32 SXAPI lb_max_32(int32 a, int32 b)
|
||||
{
|
||||
return (a) > (b) ? a : b;
|
||||
}
|
||||
|
||||
static inline int32 SXAPI lb_min_32(int32 a, int32 b)
|
||||
{
|
||||
return (a) < (b) ? a : b;
|
||||
}
|
||||
|
||||
/*
|
||||
static inline u64 KAPI round_up_power_of_2(u64 num)
|
||||
{
|
||||
num--;
|
||||
num |= num >> 1;
|
||||
num |= num >> 2;
|
||||
num |= num >> 4;
|
||||
num |= num >> 8;
|
||||
num |= num >> 16;
|
||||
num |= num >> 32;
|
||||
num++;
|
||||
return (u64)num;
|
||||
}
|
||||
|
||||
static inline uint32 KAPI log_base_2(u64 num)
|
||||
{
|
||||
uint32 result = 0;
|
||||
|
||||
while (num >>= 1)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
|
||||
#define OBTAIN_STRUCT_ADDR(member_addr, struct_name, member_name) ((struct_name*)((uintptr)(member_addr) - (uintptr)(&(((struct_name*)0)->member_name))))
|
||||
|
||||
static inline uint64 SXAPI lb_bit_mask(uint32 bit)
|
||||
{
|
||||
return (uint64) 1 << bit;
|
||||
}
|
||||
|
||||
static inline uint64 SXAPI lb_bit_field_mask(uint32 low, uint32 high)
|
||||
{
|
||||
return ~(~(uint64) 0 << high << 1) << low;
|
||||
}
|
||||
|
||||
static inline void SXAPI lb_bit_map_set(void *bit_map, uint64 bit)
|
||||
{
|
||||
if (bit_map != NULL)
|
||||
{
|
||||
uint64 quot = bit >> 3;
|
||||
uint32 rmd = (uint32) (bit & lb_bit_field_mask(0, 2));
|
||||
|
||||
*((uint8 *) (bit_map) + quot) |= (uint8) lb_bit_mask(rmd);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void SXAPI lb_bit_map_clear(void *bit_map, uint64 bit)
|
||||
{
|
||||
if (bit_map != NULL)
|
||||
{
|
||||
uint64 quot = bit >> 3;
|
||||
uint32 rmd = (uint32) (bit & lb_bit_field_mask(0, 2));
|
||||
|
||||
*((uint8 *) (bit_map) + quot) &= ~(uint8) lb_bit_mask(rmd);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32 SXAPI lb_bit_map_read(void *bit_map, uint64 bit)
|
||||
{
|
||||
if (bit_map != NULL)
|
||||
{
|
||||
uint64 quot = bit >> 3;
|
||||
uint32 rmd = (uint32) (bit & lb_bit_field_mask(0, 2));
|
||||
|
||||
return (*((uint8 *) (bit_map) + quot) & (uint8) lb_bit_mask(rmd)) == 0 ? 0 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,50 +0,0 @@
|
|||
#ifndef STATUS_H
|
||||
#define STATUS_H
|
||||
|
||||
#include "type.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
|
||||
typedef uint32 sx_status;
|
||||
|
||||
//
|
||||
// 32 bit ints
|
||||
//
|
||||
// bits 30 - 31 - Error/Success
|
||||
// 00 = Success
|
||||
// 01 = Error
|
||||
//
|
||||
// bits 0-14 - Return Code - 32768 in total
|
||||
// bits 15-29 - Facility 32768 in total
|
||||
//
|
||||
|
||||
#define SX_MAKE_STATUS(Severity, Facility, Return) ((sx_status)(((Severity) << 30) | ((Facility) << 16) | (Return)))
|
||||
|
||||
#define SEVERITY_ERROR 0x3ul
|
||||
#define SEVERITY_SUCCESS 0x0ul
|
||||
#define SEVERITY_INFO 0x1ul
|
||||
|
||||
#define FACILITY_GENERIC 0ul
|
||||
#define FACILITY_RF 1ul
|
||||
#define FACILITY_MM 2ul
|
||||
|
||||
static inline bool sx_success(sx_status status)
|
||||
{
|
||||
uint32 severity = status >> 30;
|
||||
return (severity == SEVERITY_INFO) || (severity == SEVERITY_SUCCESS);
|
||||
}
|
||||
|
||||
#define STATUS_SUCCESS (SX_MAKE_STATUS(SEVERITY_SUCCESS, FACILITY_GENERIC, 0))
|
||||
#define STATUS_FAIL (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_GENERIC, 0))
|
||||
|
||||
#define RF_UNINITIALIZED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 1))
|
||||
#define RF_ALLOCATION_FAILED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 2))
|
||||
#define RF_INVALID_ARGUMENTS (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 3))
|
||||
#define RF_INVALID_HANDLE (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 4))
|
||||
#define RF_DUPLICATED_HANDLE (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_RF, 5))
|
||||
|
||||
#define MM_INVALID_ARGUMENTS (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 1))
|
||||
#define MM_ALLOCATION_FAILED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 2))
|
||||
#define MM_UNINITIALIZED (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 3))
|
||||
#define MM_NOT_ENOUGH_PAGE (SX_MAKE_STATUS(SEVERITY_ERROR, FACILITY_MM, 4))
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
#ifndef TYPE_H
|
||||
#define TYPE_H
|
||||
|
||||
#define SXAPI __attribute__((sysv_abi))
|
||||
#define SXTRAP _Noreturn
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef uint32_t uint32;
|
||||
typedef int32_t int32;
|
||||
typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
typedef uintptr_t uintptr;
|
||||
typedef uint16_t uint16;
|
||||
typedef int16_t int16;
|
||||
typedef uint8_t uint8;
|
||||
typedef int8_t int8;
|
||||
|
||||
typedef _Bool bool;
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
|
||||
#define STRUCT_PACKED __attribute__((packed))
|
||||
|
||||
#define UNREFERENCED(x) {(x) = (x);}
|
||||
|
||||
#endif
|
|
@ -6,5 +6,7 @@ dir := $(d)/mm
|
|||
include $(dir)/Rules.mk
|
||||
dir := $(d)/rf
|
||||
include $(dir)/Rules.mk
|
||||
dir := $(d)/lb
|
||||
include $(dir)/Rules.mk
|
||||
|
||||
include $(MK)/epilogue.mk
|
|
@ -3,12 +3,12 @@ include $(MK)/prologue.mk
|
|||
SRC_$(d) := $(d)/alloc.c \
|
||||
$(d)/assert.c \
|
||||
$(d)/atomic.c \
|
||||
$(d)/boot.c \
|
||||
$(d)/bug_check.c \
|
||||
$(d)/intr.c \
|
||||
$(d)/print.c \
|
||||
$(d)/rwwlock.c \
|
||||
$(d)/spin_lock.c
|
||||
$(d)/spin_lock.c \
|
||||
$(d)/main.c
|
||||
|
||||
include $(MK)/stdrules.mk
|
||||
|
||||
|
|
|
@ -1,30 +1,33 @@
|
|||
#include "type.h"
|
||||
#include "kernel/ke/alloc.h"
|
||||
#include "lib/salloc.h"
|
||||
#include "kp.h"
|
||||
|
||||
#define K_KERNEL_HEAP_SIZE 8192
|
||||
|
||||
static bool alloc_initialized;
|
||||
static uint8 alloc_heap[K_KERNEL_HEAP_SIZE];
|
||||
|
||||
void SXAPI ke_alloc_init(void)
|
||||
void
|
||||
ke_alloc_init(void)
|
||||
{
|
||||
if (!alloc_initialized)
|
||||
{
|
||||
lb_salloc_init(alloc_heap, K_KERNEL_HEAP_SIZE);
|
||||
alloc_initialized = TRUE;
|
||||
}
|
||||
if (!alloc_initialized)
|
||||
{
|
||||
lb_salloc_init(alloc_heap, K_KERNEL_HEAP_SIZE);
|
||||
alloc_initialized = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void *SXAPI ke_alloc(uint32 size)
|
||||
void *
|
||||
ke_alloc(
|
||||
uint32 size)
|
||||
{
|
||||
return alloc_initialized ? lb_salloc(alloc_heap, size) : NULL;
|
||||
return alloc_initialized ? lb_salloc(alloc_heap, size) : NULL;
|
||||
}
|
||||
|
||||
void SXAPI ke_free(void *ptr)
|
||||
void
|
||||
ke_free(
|
||||
void *ptr)
|
||||
{
|
||||
if (alloc_initialized)
|
||||
{
|
||||
lb_sfree(alloc_heap, ptr);
|
||||
}
|
||||
if (alloc_initialized)
|
||||
{
|
||||
lb_sfree(alloc_heap, ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include "type.h"
|
||||
#include "kernel/ke/assert.h"
|
||||
#include "kernel/ke/print.h"
|
||||
#include "kp.h"
|
||||
|
||||
void ke_assert_ex(const char *expr_str, const char *file, int32 line, int32 expr)
|
||||
{
|
||||
if (!expr)
|
||||
{
|
||||
ke_printf("Assertion \"%s\" failed at %s:%d.\n", expr_str, file, line);
|
||||
}
|
||||
}
|
||||
if (!expr)
|
||||
{
|
||||
ke_printf("Assertion \"%s\" failed at %s:%d.\n", expr_str, file, line);
|
||||
}
|
||||
}
|
|
@ -1,18 +1,17 @@
|
|||
#include "type.h"
|
||||
#include "kernel/ke/atomic.h"
|
||||
#include "kp.h"
|
||||
|
||||
int32 SXAPI ke_interlocked_exchange_32(int32 *target, int32 val)
|
||||
int32 ke_atomic_xchg_32(int32 *target, int32 val)
|
||||
{
|
||||
return hal_interlocked_exchange_32(target, val);
|
||||
return hal_atomic_xchg_32(target, val);
|
||||
}
|
||||
|
||||
int32 SXAPI ke_interlocked_increment_32(int32 *target, int32 increment)
|
||||
int32 ke_atomic_inc_32(int32 *target, int32 increment)
|
||||
{
|
||||
return hal_interlocked_increment_32(target, increment);
|
||||
return hal_atomic_inc_32(target, increment);
|
||||
}
|
||||
|
||||
int32 SXAPI ke_interlocked_compare_exchange_32(int32 *target, int32 compare, int32 val)
|
||||
int32 ke_atmoic_cmpxchg_32(int32 *target, int32 compare, int32 val)
|
||||
{
|
||||
return hal_interlocked_compare_exchange_32(target, compare, val);
|
||||
return hal_atomic_cmpxchg_32(target, compare, val);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#include "kernel/ke/boot.h"
|
||||
#include "kernel/ke/bug_check.h"
|
||||
|
||||
/**
|
||||
* Kernel entry point
|
||||
* @param boot_info passed by the bootloader
|
||||
*/
|
||||
void SXAPI ke_main(struct boot_info *boot_info)
|
||||
{
|
||||
sx_status status = STATUS_SUCCESS;
|
||||
status = hal_init(boot_info);
|
||||
if (!sx_success(status))
|
||||
{
|
||||
ke_panic(status);
|
||||
}
|
||||
ke_trap();
|
||||
}
|
||||
|
|
@ -1,15 +1,7 @@
|
|||
#include "type.h"
|
||||
#include "kernel/ke/print.h"
|
||||
#include "kernel/ke/bug_check.h"
|
||||
#include "kp.h"
|
||||
|
||||
void SXAPI SXTRAP ke_trap(void)
|
||||
void ke_panic(uint64 reason)
|
||||
{
|
||||
while (TRUE)
|
||||
{};
|
||||
}
|
||||
|
||||
void SXAPI SXTRAP ke_panic(uint64 reason)
|
||||
{
|
||||
ke_printf("BugCheck: Reason - %ul\n", reason);
|
||||
ke_trap();
|
||||
ke_printf("BugCheck: Reason - %ul\n", reason);
|
||||
hal_halt();
|
||||
}
|
||||
|
|
|
@ -1,25 +1,81 @@
|
|||
#include "kernel/ke/assert.h"
|
||||
#include "kernel/ke/intr.h"
|
||||
#include "common.h"
|
||||
#include "kernel/status.h"
|
||||
#include "kp.h"
|
||||
|
||||
k_irql SXAPI ke_raise_irql(k_irql irql)
|
||||
static uint32 irql_arr[IRQL_NUM];
|
||||
|
||||
k_status
|
||||
kp_intr_init(struct boot_info *info)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= irql);
|
||||
return hal_set_irql(irql);
|
||||
irql_arr[IRQL_HIGH] = info->intr_info.irql_high;
|
||||
irql_arr[IRQL_DPC] = info->intr_info.irql_dpc;
|
||||
irql_arr[IRQL_LOW] = info->intr_info.irql_low;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
k_irql SXAPI ke_lower_irql(k_irql irql)
|
||||
|
||||
uint32
|
||||
ke_raise_irql(uint32 irql)
|
||||
{
|
||||
k_irql old_irql = ke_get_irql();
|
||||
ke_assert(old_irql >= irql);
|
||||
return hal_set_irql(irql);
|
||||
ke_assert(ke_get_irql() <= irql);
|
||||
return hal_set_irql(irql);
|
||||
}
|
||||
|
||||
k_irql SXAPI ke_get_irql(void)
|
||||
|
||||
uint32
|
||||
ke_lower_irql(uint32 irql)
|
||||
{
|
||||
return hal_get_irql();
|
||||
uint32 old_irql = ke_get_irql();
|
||||
ke_assert(old_irql >= irql);
|
||||
return hal_set_irql(irql);
|
||||
}
|
||||
|
||||
uint32 SXAPI ke_get_current_core(void)
|
||||
|
||||
uint32
|
||||
ke_get_irql(void)
|
||||
{
|
||||
return hal_get_core_id();
|
||||
return hal_get_irql();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ke_issue_intr(uint32 core, uint32 vector)
|
||||
{
|
||||
hal_issue_intr(core, vector);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ke_reg_intr(uint32 index, intr_handler_fp handler)
|
||||
{
|
||||
hal_reg_intr(index, handler);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ke_dereg_intr(uint32 index)
|
||||
{
|
||||
hal_dereg_intr(index);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ke_reg_exc(uint32 exc, exc_handler_fp handler)
|
||||
{
|
||||
hal_reg_exc(exc, handler);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ke_dereg_exc(uint32 exc)
|
||||
{
|
||||
hal_dereg_exc(exc);
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
ke_get_core_id(void)
|
||||
{
|
||||
return hal_get_core_id();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/ke.h"
|
||||
|
||||
/**
|
||||
* interrupts
|
||||
*/
|
||||
k_status
|
||||
kp_intr_init(struct boot_info *boot_info);
|
|
@ -0,0 +1,35 @@
|
|||
#include "kp.h"
|
||||
#include "kernel/mm.h"
|
||||
|
||||
/**
|
||||
* Kernel entry point
|
||||
* @param boot_info passed by the bootloader
|
||||
*/
|
||||
void KABI
|
||||
ke_main(struct boot_info *boot_info)
|
||||
{
|
||||
k_status status = STATUS_SUCCESS;
|
||||
|
||||
// initialize interrupts
|
||||
status = kp_intr_init(boot_info);
|
||||
if (!SX_SUCCESS(status))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
// initialize memory manager
|
||||
status = mm_pmm_init(boot_info);
|
||||
if (!SX_SUCCESS(status))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
if (!SX_SUCCESS(status))
|
||||
{
|
||||
ke_panic(status);
|
||||
}
|
||||
|
||||
ke_panic(0x0);
|
||||
}
|
||||
|
|
@ -1,14 +1,19 @@
|
|||
#include "kernel/ke/print.h"
|
||||
#include "kp.h"
|
||||
|
||||
void SXAPI ke_printf(const char *str, ...)
|
||||
void
|
||||
ke_printf(const char *str, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
ke_vprintf(str, args);
|
||||
va_end(args);
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
ke_vprintf(str, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void SXAPI ke_vprintf(const char *str, va_list args)
|
||||
void
|
||||
ke_vprintf(const char *str, va_list args)
|
||||
{
|
||||
hal_vprintf(str, args);
|
||||
//TODO: implement
|
||||
ke_assert(0);
|
||||
UNREFERENCED(str);
|
||||
UNREFERENCED(args);
|
||||
}
|
||||
|
|
|
@ -1,95 +1,73 @@
|
|||
#include "kp.h"
|
||||
|
||||
#include "kernel/ke/rwwlock.h"
|
||||
|
||||
void ke_rwwlock_init(k_rwwlock_t *lock)
|
||||
void
|
||||
ke_rww_init(struct rwwlock *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_lock_init(&lock->w_mutex);
|
||||
ke_spin_lock_init(&lock->r_mutex);
|
||||
ke_spin_lock_init(&lock->res_lock);
|
||||
ke_spin_lock_init(&lock->r_try);
|
||||
lock->reader_ct = 0;
|
||||
lock->writer_ct = 0;
|
||||
}
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_init(&lock->w_mutex);
|
||||
ke_spin_init(&lock->r_mutex);
|
||||
ke_spin_init(&lock->res_lock);
|
||||
ke_spin_init(&lock->r_try);
|
||||
lock->reader_ct = 0;
|
||||
lock->writer_ct = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ke_rwwlock_reader_lock(k_rwwlock_t *lock)
|
||||
void
|
||||
ke_rww_r_lock(struct rwwlock *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_lock(&lock->r_try);
|
||||
ke_spin_lock(&lock->r_mutex);
|
||||
lock->reader_ct++;
|
||||
if (lock->reader_ct == 1)
|
||||
{
|
||||
ke_spin_lock(&lock->res_lock);
|
||||
}
|
||||
ke_spin_unlock(&lock->r_mutex);
|
||||
ke_spin_unlock(&lock->r_try);
|
||||
}
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_lock(&lock->r_try);
|
||||
ke_spin_lock(&lock->r_mutex);
|
||||
lock->reader_ct++;
|
||||
if (lock->reader_ct == 1)
|
||||
{
|
||||
ke_spin_lock(&lock->res_lock);
|
||||
}
|
||||
ke_spin_unlock(&lock->r_mutex);
|
||||
ke_spin_unlock(&lock->r_try);
|
||||
}
|
||||
}
|
||||
|
||||
void ke_rwwlock_reader_unlock(k_rwwlock_t *lock)
|
||||
void
|
||||
ke_rww_r_unlock(struct rwwlock *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_lock(&lock->r_mutex);
|
||||
lock->reader_ct--;
|
||||
if (lock->reader_ct == 0)
|
||||
{
|
||||
ke_spin_unlock(&lock->res_lock);
|
||||
}
|
||||
ke_spin_unlock(&lock->r_mutex);
|
||||
}
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_lock(&lock->r_mutex);
|
||||
lock->reader_ct--;
|
||||
if (lock->reader_ct == 0)
|
||||
{
|
||||
ke_spin_unlock(&lock->res_lock);
|
||||
}
|
||||
ke_spin_unlock(&lock->r_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
void ke_rwwlock_writer_lock(k_rwwlock_t *lock)
|
||||
void
|
||||
ke_rww_w_lock(struct rwwlock *lock)
|
||||
{
|
||||
ke_spin_lock(&lock->w_mutex);
|
||||
lock->writer_ct++;
|
||||
if (lock->writer_ct == 1)
|
||||
{
|
||||
ke_spin_lock(&lock->r_try);
|
||||
}
|
||||
ke_spin_unlock(&lock->w_mutex);
|
||||
ke_spin_lock(&lock->res_lock);
|
||||
ke_spin_lock(&lock->w_mutex);
|
||||
lock->writer_ct++;
|
||||
if (lock->writer_ct == 1)
|
||||
{
|
||||
ke_spin_lock(&lock->r_try);
|
||||
}
|
||||
ke_spin_unlock(&lock->w_mutex);
|
||||
ke_spin_lock(&lock->res_lock);
|
||||
}
|
||||
|
||||
void ke_rwwlock_writer_unlock(k_rwwlock_t *lock)
|
||||
void
|
||||
ke_rww_w_unlock(struct rwwlock *lock)
|
||||
{
|
||||
ke_spin_unlock(&lock->res_lock);
|
||||
ke_spin_lock(&lock->w_mutex);
|
||||
lock->writer_ct--;
|
||||
if (lock->writer_ct == 0)
|
||||
{
|
||||
ke_spin_unlock(&lock->r_try);
|
||||
}
|
||||
ke_spin_unlock(&lock->w_mutex);
|
||||
}
|
||||
|
||||
k_irql ke_rwwlock_reader_lock_raise_irql(k_rwwlock_t *lock, k_irql irql)
|
||||
{
|
||||
k_irql old_irql = ke_raise_irql(irql);
|
||||
ke_rwwlock_reader_lock(lock);
|
||||
return old_irql;
|
||||
}
|
||||
|
||||
void ke_rwwlock_reader_unlock_lower_irql(k_rwwlock_t *lock, k_irql irql)
|
||||
{
|
||||
ke_rwwlock_reader_unlock(lock);
|
||||
ke_lower_irql(irql);
|
||||
}
|
||||
|
||||
k_irql ke_rwwlock_writer_lock_raise_irql(k_rwwlock_t *lock, k_irql irql)
|
||||
{
|
||||
k_irql old_irql = ke_raise_irql(irql);
|
||||
ke_rwwlock_writer_lock(lock);
|
||||
return old_irql;
|
||||
}
|
||||
|
||||
void ke_rwwlock_writer_unlock_lower_irql(k_rwwlock_t *lock, k_irql irql)
|
||||
{
|
||||
ke_rwwlock_writer_unlock(lock);
|
||||
ke_lower_irql(irql);
|
||||
ke_spin_unlock(&lock->res_lock);
|
||||
ke_spin_lock(&lock->w_mutex);
|
||||
lock->writer_ct--;
|
||||
if (lock->writer_ct == 0)
|
||||
{
|
||||
ke_spin_unlock(&lock->r_try);
|
||||
}
|
||||
ke_spin_unlock(&lock->w_mutex);
|
||||
}
|
||||
|
|
|
@ -1,47 +1,32 @@
|
|||
#include "kernel/ke/atomic.h"
|
||||
#include "kernel/ke/spin_lock.h"
|
||||
#include "kp.h"
|
||||
|
||||
void SXAPI ke_spin_lock_init(k_spin_lock_t *lock)
|
||||
void
|
||||
ke_spin_init(struct spin_lock *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
lock->val = 0;
|
||||
}
|
||||
if (lock != NULL)
|
||||
{
|
||||
lock->val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI ke_spin_lock(k_spin_lock_t *lock)
|
||||
|
||||
void
|
||||
ke_spin_lock(struct spin_lock *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
while (ke_interlocked_compare_exchange_32(&lock->val, 0, 1) != 0)
|
||||
{}
|
||||
}
|
||||
if (lock != NULL)
|
||||
{
|
||||
while (ke_atmoic_cmpxchg_32(&lock->val, 0, 1) != 0)
|
||||
{}
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI ke_spin_unlock(k_spin_lock_t *lock)
|
||||
|
||||
void
|
||||
ke_spin_unlock(struct spin_lock *lock)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
lock->val = 0;
|
||||
}
|
||||
if (lock != NULL)
|
||||
{
|
||||
lock->val = 0;
|
||||
}
|
||||
}
|
||||
|
||||
k_irql SXAPI ke_spin_lock_raise_irql(k_spin_lock_t *lock, k_irql irql)
|
||||
{
|
||||
k_irql prev_irql = ke_get_irql();
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_raise_irql(irql);
|
||||
ke_spin_lock(lock);
|
||||
}
|
||||
return prev_irql;
|
||||
}
|
||||
|
||||
void SXAPI ke_spin_unlock_lower_irql(k_spin_lock_t *lock, k_irql irql)
|
||||
{
|
||||
if (lock != NULL)
|
||||
{
|
||||
ke_spin_unlock(lock);
|
||||
ke_lower_irql(irql);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
include $(MK)/prologue.mk
|
||||
|
||||
SRC_$(d) := $(d)/atree.c \
|
||||
$(d)/llist.c \
|
||||
$(d)/salloc.c
|
||||
include $(MK)/stdrules.mk
|
||||
|
||||
include $(MK)/epilogue.mk
|
|
@ -0,0 +1,576 @@
|
|||
#include "lp.h"
|
||||
|
||||
static
|
||||
struct atree_node *
|
||||
atree_node_max(
|
||||
struct atree_node *node)
|
||||
{
|
||||
while ((node != NULL) && (node->right != NULL))
|
||||
{
|
||||
node = node->right;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
struct atree_node *
|
||||
atree_node_min(
|
||||
struct atree_node *node)
|
||||
{
|
||||
while ((node != NULL) && (node->left != NULL))
|
||||
{
|
||||
node = node->left;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void
|
||||
atree_node_init(
|
||||
struct atree_node *it)
|
||||
{
|
||||
if (it != NULL)
|
||||
{
|
||||
it->height = 0;
|
||||
it->left = NULL;
|
||||
it->right = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int32
|
||||
atree_node_get_height(
|
||||
struct atree_node *node)
|
||||
{
|
||||
return node == NULL ? -1 : node->height;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int32
|
||||
atree_node_get_balance_factor(
|
||||
struct atree_node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return atree_node_get_height(node->left) - atree_node_get_height(node->right);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
struct atree_node *
|
||||
atree_node_right_rotate(
|
||||
struct atree_node *node)
|
||||
{
|
||||
struct atree_node *lchild = node->left;
|
||||
node->left = lchild->right;
|
||||
lchild->right = node;
|
||||
|
||||
node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1;
|
||||
lchild->height = MAX(atree_node_get_height(lchild->left), atree_node_get_height(lchild->right)) + 1;
|
||||
return lchild;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
struct atree_node *
|
||||
atree_node_left_rotate(
|
||||
struct atree_node *node)
|
||||
{
|
||||
struct atree_node *rchild = node->right;
|
||||
node->right = rchild->left;
|
||||
rchild->left = node;
|
||||
|
||||
node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1;
|
||||
rchild->height = MAX(atree_node_get_height(rchild->left), atree_node_get_height(rchild->right)) + 1;
|
||||
return rchild;
|
||||
}
|
||||
|
||||
|
||||
static struct atree_node *
|
||||
atree_node_balance(struct atree_node *node)
|
||||
{
|
||||
int32 bf;
|
||||
int32 cbf;
|
||||
|
||||
bf = atree_node_get_balance_factor(node);
|
||||
|
||||
if (bf > 1)
|
||||
{
|
||||
/**
|
||||
* Left double heavy
|
||||
*/
|
||||
cbf = atree_node_get_balance_factor(node->left);
|
||||
if (cbf >= 0)
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Left child is left heavy
|
||||
* x (k) y (k-1)
|
||||
* / \ RR(x) / \
|
||||
* (k-1) y A (k-3) -----------> (k-2)B x (k-2)
|
||||
* / \ / \
|
||||
* (k-2) B C (k-3) (k-3) C A (k-3)
|
||||
*/
|
||||
return atree_node_right_rotate(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Left child is right heavy
|
||||
* x (k) x (k)
|
||||
* / \ / \
|
||||
* (k-1) y A (k-3) LR(y) (k-1) z A (k-3)
|
||||
* / \ ------------> / \
|
||||
* (k-3) B z (k-2) (k-2) y D (k-4)
|
||||
* / \ / \
|
||||
* (k-3) C D (k-4) (k-3) B C (k-3)
|
||||
*
|
||||
*
|
||||
* x (k) __z__ (k-1)
|
||||
* / \ / \
|
||||
* (k-1) z A (k-3) (k-2) y x (k-2)
|
||||
* / \ RR(x) / \ / \
|
||||
* (k-2) y D (k-4) ------------> B C D A
|
||||
* / \
|
||||
* (k-3)B C (k-3)
|
||||
*/
|
||||
node->left = atree_node_left_rotate(node->left);
|
||||
return atree_node_right_rotate(node);
|
||||
}
|
||||
}
|
||||
else if (bf < -1)
|
||||
{
|
||||
{
|
||||
cbf = atree_node_get_balance_factor(node->right);
|
||||
if (cbf <= 0)
|
||||
{
|
||||
// right right, see above
|
||||
return atree_node_left_rotate(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// right left, see above
|
||||
node->right = atree_node_right_rotate(node->right);
|
||||
return atree_node_left_rotate(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct atree_node *
|
||||
atree_node_insert(struct atree_node *node, struct atree_node *entry, atree_cmp_fp compare, struct atree_node **overwritten)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
atree_node_init(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
int32 comp = compare(node, entry);
|
||||
if (comp < 0)
|
||||
{
|
||||
node->right = atree_node_insert(node->right, entry, compare, overwritten);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp == 0)
|
||||
{
|
||||
/**
|
||||
* overwrite existing value
|
||||
*/
|
||||
atree_node_init(entry);
|
||||
entry->right = node->right;
|
||||
entry->left = node->left;
|
||||
entry->height = node->height;
|
||||
*overwritten = node;
|
||||
return entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->left = atree_node_insert(node->left, entry, compare, overwritten);
|
||||
}
|
||||
}
|
||||
|
||||
node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1;
|
||||
|
||||
return atree_node_balance(node);
|
||||
}
|
||||
|
||||
|
||||
static struct atree_node *
|
||||
atree_node_search(struct atree_node *node, struct atree_node *entry, atree_cmp_fp compare, struct atree_node **parent)
|
||||
{
|
||||
int32 comp;
|
||||
struct atree_node *prev;
|
||||
struct atree_node *temp;
|
||||
|
||||
prev = NULL;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
comp = compare(node, entry);
|
||||
temp = node;
|
||||
if (comp < 0)
|
||||
{
|
||||
node = node->right;
|
||||
}
|
||||
else if (comp > 0)
|
||||
{
|
||||
node = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
prev = temp;
|
||||
}
|
||||
|
||||
if (parent != NULL)
|
||||
{
|
||||
*parent = prev;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
static struct atree_node *
|
||||
atree_node_delete(struct atree_node *node, struct atree_node *entry, atree_cmp_fp compare, struct atree_node **deleted)
|
||||
{
|
||||
int32 comp;
|
||||
struct atree_node *succ_parent;
|
||||
|
||||
if (node == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
comp = compare(node, entry);
|
||||
if (comp < 0)
|
||||
{
|
||||
node->right = atree_node_delete(node->right, entry, compare, deleted);
|
||||
}
|
||||
else if (comp > 0)
|
||||
{
|
||||
node->left = atree_node_delete(node->left, entry, compare, deleted);
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* Write the deleted node first
|
||||
*/
|
||||
*deleted = node;
|
||||
|
||||
if ((node->left == NULL) || (node->right == NULL))
|
||||
{
|
||||
/**
|
||||
* 0 or 1 child
|
||||
*/
|
||||
struct atree_node *child = node->left != NULL ? node->left : node->right;
|
||||
|
||||
if (child == NULL)
|
||||
{
|
||||
node = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = child;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* 2 children
|
||||
* meaning that the successor must be in the right subtree
|
||||
*/
|
||||
struct atree_node *succ = atree_node_min(node->right);
|
||||
atree_node_search(node, succ, compare, &succ_parent);
|
||||
|
||||
/**
|
||||
* Swap the nodes
|
||||
* note that after swapping, the BST property of the right subtree is preserved
|
||||
*/
|
||||
if (succ_parent == node)
|
||||
{
|
||||
/**
|
||||
* check special case where the successor is the right child
|
||||
*/
|
||||
node->right = succ->right;
|
||||
succ->right = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (succ_parent->left == succ)
|
||||
{
|
||||
succ_parent->left = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
succ_parent->right = node;
|
||||
}
|
||||
SWAP(&node->right, &succ->right, struct atree_node*);
|
||||
}
|
||||
SWAP(&node->left, &succ->left, struct atree_node*);
|
||||
SWAP(&node->height, &succ->height, int32);
|
||||
|
||||
/**
|
||||
* Delete the node from the right subtree
|
||||
*/
|
||||
succ->right = atree_node_delete(succ->right, node, compare, deleted);
|
||||
|
||||
node = succ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* balance the new head
|
||||
*/
|
||||
if (node != NULL)
|
||||
{
|
||||
node->height = MAX(atree_node_get_height(node->left), atree_node_get_height(node->right)) + 1;
|
||||
node = atree_node_balance(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_min(
|
||||
struct atree *tree)
|
||||
{
|
||||
return atree_node_min(tree->root);
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_max(
|
||||
struct atree *tree)
|
||||
{
|
||||
return atree_node_max(tree->root);
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_next(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry)
|
||||
{
|
||||
struct atree_node *succ;
|
||||
struct atree_node *node;
|
||||
int32 comp;
|
||||
|
||||
if (entry->right != NULL)
|
||||
{
|
||||
succ = atree_node_min(entry->right);
|
||||
}
|
||||
else
|
||||
{
|
||||
succ = NULL;
|
||||
node = tree->root;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
comp = tree->cmpf(node, entry);
|
||||
|
||||
if (comp < 0)
|
||||
{
|
||||
node = node->right;
|
||||
}
|
||||
else if (comp > 0)
|
||||
{
|
||||
succ = node;
|
||||
node = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return succ;
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_prev(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry)
|
||||
{
|
||||
struct atree_node *prev;
|
||||
struct atree_node *node;
|
||||
int32 comp;
|
||||
|
||||
if (entry->left != NULL)
|
||||
{
|
||||
prev = atree_node_max(entry->left);
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = NULL;
|
||||
node = tree->root;
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
comp = tree->cmpf(node, entry);
|
||||
|
||||
if (comp < 0)
|
||||
{
|
||||
prev = node;
|
||||
node = node->right;
|
||||
}
|
||||
else if (comp > 0)
|
||||
{
|
||||
node = node->left;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_search(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry)
|
||||
{
|
||||
return atree_node_search(tree->root, entry, tree->cmpf, NULL);
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_insert(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry)
|
||||
{
|
||||
struct atree_node *old;
|
||||
|
||||
old = NULL;
|
||||
tree->root = atree_node_insert(tree->root, entry, tree->cmpf, &old);
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
struct atree_node *
|
||||
lb_atree_delete(
|
||||
struct atree *tree,
|
||||
struct atree_node *entry)
|
||||
{
|
||||
struct atree_node *node;
|
||||
|
||||
node = NULL;
|
||||
tree->root = atree_node_delete(tree->root, entry, tree->cmpf, &node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
lb_atree_size(
|
||||
struct atree *tree)
|
||||
{
|
||||
uint32 size;
|
||||
struct atree_node *node;
|
||||
|
||||
size = 0;
|
||||
if (tree->root != NULL)
|
||||
{
|
||||
node = lb_atree_min(tree);
|
||||
while (node != NULL)
|
||||
{
|
||||
size++;
|
||||
node = lb_atree_next(tree, node);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_atree_init(
|
||||
struct atree *tree,
|
||||
atree_cmp_fp compare)
|
||||
{
|
||||
tree->cmpf = compare;
|
||||
tree->root = NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used by tests
|
||||
*/
|
||||
|
||||
static
|
||||
int32
|
||||
atree_node_calc_height(struct atree_node *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return MAX(atree_node_calc_height(tree->left), atree_node_calc_height(tree->right)) + 1;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
bool
|
||||
atree_node_test(struct atree_node *tree, atree_cmp_fp compare)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (atree_node_get_balance_factor(tree) < -1 || atree_node_get_balance_factor(tree) > 1 ||
|
||||
atree_node_calc_height(tree) != tree->height)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(tree->height == 0 && ((tree->left != NULL) || (tree->right != NULL)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(tree->right == tree || tree->left == tree || (tree->right == tree->left && tree->right != NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((tree->right != NULL && compare(tree, tree->right) > 0) ||
|
||||
(tree->left != NULL && compare(tree, tree->left) < 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return atree_node_test(tree->left, compare) && atree_node_test(tree->right, compare);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
lb_atree_validate(struct atree *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return atree_node_test(tree->root, tree->cmpf);
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
#include "lp.h"
|
||||
|
||||
static void
|
||||
llist_node_init(struct llist_node *node)
|
||||
{
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_llist_init(struct llist *list)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->size = 0;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
lb_llist_size(struct llist *list)
|
||||
{
|
||||
return list->size;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_llist_push_front(struct llist *list, struct llist_node *node)
|
||||
{
|
||||
llist_node_init(node);
|
||||
lb_llist_insert_by_ref(list, NULL, node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_llist_push_back(struct llist *list, struct llist_node *node)
|
||||
{
|
||||
llist_node_init(node);
|
||||
lb_llist_insert_by_ref(list, list->tail, node);
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_pop_front(struct llist *list)
|
||||
{
|
||||
struct llist_node *ret;
|
||||
|
||||
ret = list->head;
|
||||
lb_llist_remove_by_ref(list, list->head);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_pop_back(struct llist *list)
|
||||
{
|
||||
struct llist_node *ret;
|
||||
|
||||
ret = list->tail;
|
||||
lb_llist_remove_by_ref(list, list->tail);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_llist_insert_by_ref(struct llist *list, struct llist_node *cur_node, struct llist_node *new_node)
|
||||
{
|
||||
struct llist_node *left_node;
|
||||
struct llist_node *right_node;
|
||||
|
||||
if (list == NULL || new_node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
llist_node_init(new_node);
|
||||
|
||||
/*
|
||||
* adjust the current node
|
||||
*/
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
new_node->next = list->head;
|
||||
new_node->prev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_node->prev = cur_node;
|
||||
new_node->next = cur_node->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* assign left and treenode node
|
||||
*/
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
left_node = NULL;
|
||||
right_node = list->head == NULL ? NULL : list->head;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_node = cur_node;
|
||||
right_node = cur_node->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* adjust left and treenode node accordingly
|
||||
*/
|
||||
if (left_node != NULL)
|
||||
{
|
||||
left_node->next = new_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->head = new_node;
|
||||
}
|
||||
|
||||
if (right_node != NULL)
|
||||
{
|
||||
right_node->prev = new_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->tail = new_node;
|
||||
}
|
||||
|
||||
list->size++;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_llist_insert_by_idx(struct llist *list, uint32 index, struct llist_node *node)
|
||||
{
|
||||
struct llist_node *prev_node;
|
||||
|
||||
prev_node = lb_llist_get(list, index - 1);
|
||||
llist_node_init(node);
|
||||
|
||||
if (prev_node == NULL)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
lb_llist_insert_by_ref(list, NULL, node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lb_llist_insert_by_ref(list, prev_node, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_remove_by_idx(struct llist *list, uint32 index)
|
||||
{
|
||||
struct llist_node *cur_node;
|
||||
|
||||
cur_node = lb_llist_get(list, index);
|
||||
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lb_llist_remove_by_ref(list, cur_node);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the next node
|
||||
*/
|
||||
struct llist_node *
|
||||
lb_llist_remove_by_ref(struct llist *list, struct llist_node *node)
|
||||
{
|
||||
struct llist_node *ret;
|
||||
|
||||
/*
|
||||
* Adjust the left and treenode node
|
||||
*/
|
||||
if (node->prev != NULL)
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->head = node->next;
|
||||
}
|
||||
|
||||
if (node->next != NULL)
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->tail = node->prev;
|
||||
}
|
||||
|
||||
ret = node->next;
|
||||
|
||||
llist_node_init(node);
|
||||
|
||||
list->size--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_get(struct llist *list, uint32 index)
|
||||
{
|
||||
if (list->head == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct llist_node *cur_node = list->head;
|
||||
while (index-- && (cur_node = cur_node->next) != NULL)
|
||||
{}
|
||||
return cur_node;
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_next(struct llist_node *node)
|
||||
{
|
||||
return node->next;
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_prev(struct llist_node *node)
|
||||
{
|
||||
return node->prev;
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_first(struct llist *list)
|
||||
{
|
||||
return list->head;
|
||||
}
|
||||
|
||||
|
||||
struct llist_node *
|
||||
lb_llist_last(struct llist *list)
|
||||
{
|
||||
return list->tail;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/lb.h"
|
|
@ -0,0 +1,234 @@
|
|||
#include "lp.h"
|
||||
|
||||
struct salloc_header
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32 size;
|
||||
uint32 flags;
|
||||
};
|
||||
};
|
||||
|
||||
#define ALLOC_FLAG_NUM 2
|
||||
#define ALLOC_HEADER_FLAG_FREE 0
|
||||
#define ALLOC_HEADER_FLAG_LAST 1
|
||||
|
||||
static void
|
||||
set_salloc_header_size(struct salloc_header *header, uint32 size)
|
||||
{
|
||||
// align the integer, ignoring overflowed bits
|
||||
size <<= ALLOC_FLAG_NUM;
|
||||
|
||||
// clear ALLOC_FLAG_NUM-th to 31-th bits
|
||||
header->size &= ~(uint32) bit_field_mask(ALLOC_FLAG_NUM, 31);
|
||||
// set bits
|
||||
header->size |= size;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
read_salloc_header_size(struct salloc_header *header)
|
||||
{
|
||||
return header->size >> ALLOC_FLAG_NUM;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
read_salloc_header_flag(struct salloc_header *header, uint32 bit)
|
||||
{
|
||||
return (header->flags & (uint32) bit_mask(bit)) == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_salloc_header_flag(struct salloc_header *header, uint32 bit, uint32 value)
|
||||
{
|
||||
value &= (uint32) bit_mask(0);
|
||||
if (value == 1)
|
||||
{
|
||||
header->flags |= (uint32) bit_mask(bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
header->flags &= ~(uint32) bit_mask(bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void salloc_join(void *base)
|
||||
{
|
||||
if (base != NULL)
|
||||
{
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 c_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 c_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 c_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
char *n_ptr = c_blk_last == 1 ? NULL : c_ptr + c_blk_size;
|
||||
if (n_ptr != NULL && c_blk_free == 1)
|
||||
{
|
||||
// if this is not the last block and the prev block is free
|
||||
uint32 n_blk_free = read_salloc_header_flag((struct salloc_header *) n_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 n_blk_last = read_salloc_header_flag((struct salloc_header *) n_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 n_blk_size = read_salloc_header_size((struct salloc_header *) n_ptr);
|
||||
|
||||
if (n_blk_free == 1)
|
||||
{
|
||||
// logically gone
|
||||
set_salloc_header_size((struct salloc_header *) c_ptr, n_blk_size + c_blk_size);
|
||||
set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, n_blk_last);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// update the c_ptr
|
||||
if (c_blk_last == 0)
|
||||
{
|
||||
c_ptr += c_blk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
lb_salloc_assert(void *base, const uint32 *blk_size, const bool *blk_free, uint32 size)
|
||||
{
|
||||
if (base == NULL || blk_free == NULL || blk_size == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
uint32 i = 0;
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 cur_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 cur_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 cur_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
if (cur_blk_free != blk_free[i] || cur_blk_size != blk_size[i])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ptr += cur_blk_size;
|
||||
i++;
|
||||
}
|
||||
if (cur_blk_last == 1)
|
||||
{
|
||||
return i == size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_salloc_init(void *base, uint32 size)
|
||||
{
|
||||
if (base != NULL && size >= sizeof(struct salloc_header))
|
||||
{
|
||||
struct salloc_header *ptr = (struct salloc_header *) base;
|
||||
set_salloc_header_size(ptr, size);
|
||||
set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_FREE, 1);
|
||||
set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_LAST, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
lb_salloc(void *base, uint32 size)
|
||||
{
|
||||
void *result = NULL;
|
||||
if (base != NULL && size != 0)
|
||||
{
|
||||
uint32 total_size = size + sizeof(struct salloc_header);
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 cur_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 cur_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
uint32 cur_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
if (cur_blk_free == 0 || cur_blk_size < total_size)
|
||||
{
|
||||
//if cur block not a free block
|
||||
//or the current block size is less than the size we want
|
||||
if (cur_blk_last == 1)
|
||||
{
|
||||
//if last one, break and fail.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ptr += cur_blk_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have a free block with enough size
|
||||
if (total_size == cur_blk_size ||
|
||||
cur_blk_size - total_size < sizeof(struct salloc_header))
|
||||
{
|
||||
// since the space left is not enough for salloc_header
|
||||
// we alloc the whole block
|
||||
set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we split the block here
|
||||
// set properties for the first block
|
||||
set_salloc_header_size((struct salloc_header *) c_ptr, total_size);
|
||||
set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, 0);
|
||||
set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0);
|
||||
|
||||
// set properties for the second block
|
||||
set_salloc_header_size((struct salloc_header *) (c_ptr + total_size), cur_blk_size - total_size);
|
||||
set_salloc_header_flag((struct salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_LAST,
|
||||
cur_blk_last);
|
||||
set_salloc_header_flag((struct salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_FREE, 1);
|
||||
}
|
||||
// return the pointer, skip the alloc header
|
||||
result = c_ptr + sizeof(struct salloc_header);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lb_sfree(void *base, void *ptr)
|
||||
{
|
||||
if (base != NULL && ptr != NULL)
|
||||
{
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 cur_blk_free = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 cur_blk_last = read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 cur_blk_size = read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
if (cur_blk_free == 0 && ptr == c_ptr + sizeof(struct salloc_header))
|
||||
{
|
||||
// we found the block, mark it as free
|
||||
set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 1);
|
||||
// merge blocks
|
||||
salloc_join(base);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur_blk_last == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ptr += cur_blk_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/mm.h"
|
||||
|
||||
/**
|
||||
* PMM init info
|
||||
*/
|
||||
struct pmm_node
|
||||
{
|
||||
uintptr base;
|
||||
uint64 size;
|
||||
uint32 attr;
|
||||
};
|
||||
|
||||
struct pmm_info
|
||||
{
|
||||
uint32 num_of_nodes;
|
||||
struct pmm_node nodes[];
|
||||
};
|
||||
|
310
kernel/mm/pmm.c
310
kernel/mm/pmm.c
|
@ -1,21 +1,16 @@
|
|||
#include "kernel/ke/assert.h"
|
||||
#include "kernel/ke/rwwlock.h"
|
||||
#include "status.h"
|
||||
#include "kernel/ke/alloc.h"
|
||||
#include "kernel/mm/pmm.h"
|
||||
#include "mp.h"
|
||||
|
||||
struct phys_page_desc
|
||||
{
|
||||
struct linked_list_node free_list_node;
|
||||
struct avl_tree_node tree_node;
|
||||
uintptr base;
|
||||
int32 attr;
|
||||
struct llist_node free_list_node;
|
||||
struct atree_node tree_node;
|
||||
uintptr base;
|
||||
int32 attr;
|
||||
};
|
||||
|
||||
static struct avl_tree active_tree;
|
||||
static struct linked_list free_list;
|
||||
static k_rwwlock_t lock;
|
||||
static _Bool initialized;
|
||||
static struct atree active_tree;
|
||||
static struct llist free_list;
|
||||
static struct rwwlock lock;
|
||||
|
||||
/*
|
||||
* A comparison function between tree_node and your_node
|
||||
|
@ -24,72 +19,73 @@ static _Bool initialized;
|
|||
* = 0 if tree_node == your_node
|
||||
* > 0 if tree_node > your_node
|
||||
*/
|
||||
static int32 SXAPI mmp_base_paddr_compare(struct avl_tree_node* tree_node, struct avl_tree_node *my_node)
|
||||
//static int32 mmp_base_paddr_compare(struct atree_node *tree_node, struct atree_node *my_node)
|
||||
//{
|
||||
// uintptr tree_base = OBTAIN_STRUCT_ADDR(tree_node,
|
||||
// struct phys_page_desc,
|
||||
// tree_node)->base;
|
||||
// uintptr my_base = OBTAIN_STRUCT_ADDR(my_node,
|
||||
// struct phys_page_desc,
|
||||
// tree_node)->base;
|
||||
// if (tree_base > my_base)
|
||||
// {
|
||||
// return 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (tree_base < my_base)
|
||||
// {
|
||||
// return -1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
k_status mm_pmm_init(struct boot_info *info)
|
||||
{
|
||||
uintptr tree_base = OBTAIN_STRUCT_ADDR(tree_node,
|
||||
struct phys_page_desc,
|
||||
tree_node)->base;
|
||||
uintptr my_base = OBTAIN_STRUCT_ADDR(my_node,
|
||||
struct phys_page_desc,
|
||||
tree_node)->base;
|
||||
if (tree_base > my_base)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tree_base < my_base)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sx_status SXAPI sx_pmm_init(pmm_info_t *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
{
|
||||
return MM_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
if (initialized)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ke_rwwlock_init(&lock);
|
||||
lb_linked_list_init(&free_list);
|
||||
lb_avl_tree_init(&active_tree, mmp_base_paddr_compare);
|
||||
|
||||
for (uint32 i = 0; i < info->num_of_nodes; i++)
|
||||
{
|
||||
pmm_node_t *each_node = &info->nodes[i];
|
||||
|
||||
ke_assert (each_node->base % KERNEL_PAGE_SIZE != 0);
|
||||
|
||||
for (uint64 j = 0; j <= each_node->size; j++)
|
||||
{
|
||||
// note that k_alloc function here might trigger page fault
|
||||
// however it's fine as long as we don't touch linked list just yet
|
||||
// it will use the pages that are already on file to enlarge the kernel heap
|
||||
// don't worry, be happy :)
|
||||
struct phys_page_desc *page_info = ke_alloc(sizeof(struct phys_page_desc));
|
||||
|
||||
if (page_info == NULL)
|
||||
{
|
||||
return MM_ALLOCATION_FAILED;
|
||||
}
|
||||
|
||||
page_info->base = each_node->base;
|
||||
lb_linked_list_push_back(&free_list, &page_info->free_list_node);
|
||||
}
|
||||
}
|
||||
initialized = TRUE;
|
||||
return STATUS_SUCCESS;
|
||||
UNREFERENCED(info);
|
||||
// if (info == NULL)
|
||||
// {
|
||||
// return MM_INVALID_ARGUMENTS;
|
||||
// }
|
||||
//
|
||||
// if (initialized)
|
||||
// {
|
||||
// return STATUS_SUCCESS;
|
||||
// }
|
||||
//
|
||||
// ke_rwwlock_init(&lock);
|
||||
// lb_linked_list_init(&free_list);
|
||||
// lb_avl_tree_init(&active_tree, mmp_base_paddr_compare);
|
||||
//
|
||||
// for (uint32 i = 0; i < info->num_of_nodes; i++)
|
||||
// {
|
||||
// pmm_node_t *each_node = &info->nodes[i];
|
||||
//
|
||||
// ke_assert (each_node->base % KERNEL_PAGE_SIZE != 0);
|
||||
//
|
||||
// for (uint64 j = 0; j <= each_node->size; j++)
|
||||
// {
|
||||
// // note that k_alloc function here might trigger page fault
|
||||
// // however it's fine as long as we don't touch linked list just yet
|
||||
// // it will use the pages that are already on file to enlarge the kernel heap
|
||||
// // don't worry, be happy :)
|
||||
// struct phys_page_desc *page_info = ke_alloc(sizeof(struct phys_page_desc));
|
||||
//
|
||||
// if (page_info == NULL)
|
||||
// {
|
||||
// return MM_ALLOCATION_FAILED;
|
||||
// }
|
||||
//
|
||||
// page_info->base = each_node->base;
|
||||
// lb_linked_list_push_back(&free_list, &page_info->free_list_node);
|
||||
// }
|
||||
// }
|
||||
// initialized = TRUE;
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
// free lists can only be updated at IRQL == DISABLED
|
||||
|
@ -97,104 +93,102 @@ sx_status SXAPI sx_pmm_init(pmm_info_t *info)
|
|||
// potential callers of these, since timer/interrupts queue DPC, which might trigger
|
||||
// page fault (kernel heap), therefore, it must set IRQL to DISABLED
|
||||
|
||||
sx_status SXAPI mm_alloc_page(uintptr *out)
|
||||
k_status mm_alloc_page(uintptr *out)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
return MM_UNINITIALIZED;
|
||||
}
|
||||
uint32 irql;
|
||||
k_status status;
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
return MM_INVALID_ARGUMENTS;
|
||||
}
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
k_irql irql = ke_rwwlock_writer_lock_raise_irql(&lock, IRQL_DISABLED_LEVEL);
|
||||
sx_status result = STATUS_SUCCESS;
|
||||
struct linked_list_node *node = NULL;
|
||||
struct phys_page_desc *page_info = NULL;
|
||||
node = lb_linked_list_pop_front(&free_list);
|
||||
if (node != NULL)
|
||||
{
|
||||
page_info = OBTAIN_STRUCT_ADDR(node,
|
||||
struct phys_page_desc,
|
||||
free_list_node);
|
||||
lb_avl_tree_insert(&active_tree, &page_info->tree_node);
|
||||
*out = page_info->base;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MM_NOT_ENOUGH_PAGE;
|
||||
}
|
||||
irql = ke_raise_irql(IRQL_HIGH);
|
||||
ke_rww_w_lock(&lock);
|
||||
|
||||
ke_rwwlock_writer_unlock_lower_irql(&lock, irql);
|
||||
return result;
|
||||
struct llist_node *node = NULL;
|
||||
struct phys_page_desc *page_info = NULL;
|
||||
node = lb_llist_pop_front(&free_list);
|
||||
if (node != NULL)
|
||||
{
|
||||
page_info = OBTAIN_STRUCT_ADDR(node,
|
||||
struct phys_page_desc,
|
||||
free_list_node);
|
||||
lb_atree_insert(&active_tree, &page_info->tree_node);
|
||||
*out = page_info->base;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
ke_rww_w_unlock(&lock);
|
||||
ke_lower_irql(irql);
|
||||
return status;
|
||||
}
|
||||
|
||||
sx_status SXAPI mm_query_page_attr(uintptr base,
|
||||
int32 *out)
|
||||
k_status mm_query_page_attr(uintptr base,
|
||||
int32 *out)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
return MM_UNINITIALIZED;
|
||||
}
|
||||
uint32 irql;
|
||||
k_status result;
|
||||
struct atree_node *node;
|
||||
struct phys_page_desc dummy;
|
||||
struct phys_page_desc *page_info;
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
return MM_INVALID_ARGUMENTS;
|
||||
}
|
||||
result = STATUS_SUCCESS;
|
||||
node = NULL;
|
||||
page_info = NULL;
|
||||
|
||||
k_irql irql = ke_rwwlock_reader_lock_raise_irql(&lock, IRQL_DISABLED_LEVEL);
|
||||
sx_status result = STATUS_SUCCESS;
|
||||
struct avl_tree_node *node = NULL;
|
||||
// search for dummy
|
||||
struct phys_page_desc dummy, *page_info = NULL;
|
||||
dummy.base = base;
|
||||
dummy.base = base;
|
||||
|
||||
node = lb_avl_tree_delete(&active_tree, &dummy.tree_node);
|
||||
irql = ke_raise_irql(IRQL_HIGH);
|
||||
ke_rww_r_lock(&lock);
|
||||
|
||||
if (node != NULL)
|
||||
{
|
||||
page_info = OBTAIN_STRUCT_ADDR(node, struct phys_page_desc, tree_node);
|
||||
*out = page_info->attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MM_INVALID_ARGUMENTS;
|
||||
}
|
||||
node = lb_atree_search(&active_tree, &dummy.tree_node);
|
||||
|
||||
ke_rwwlock_reader_unlock_lower_irql(&lock, irql);
|
||||
ke_rww_r_unlock(&lock);
|
||||
ke_lower_irql(irql);
|
||||
|
||||
return result;
|
||||
if (node != NULL)
|
||||
{
|
||||
page_info = OBTAIN_STRUCT_ADDR(node, struct phys_page_desc, tree_node);
|
||||
*out = page_info->attr;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
sx_status SXAPI mm_free_page(uintptr base)
|
||||
k_status mm_free_page(uintptr base)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
return MM_UNINITIALIZED;
|
||||
}
|
||||
// just lock since not sharing with anyone
|
||||
uint32 irql;
|
||||
k_status result;
|
||||
struct atree_node *node;
|
||||
struct phys_page_desc dummy, *page_info;
|
||||
|
||||
// just lock since not sharing with anyone
|
||||
k_irql irql = ke_rwwlock_writer_lock_raise_irql(&lock, IRQL_DISABLED_LEVEL);
|
||||
sx_status result = STATUS_SUCCESS;
|
||||
struct avl_tree_node *node = NULL;
|
||||
// search for dummy
|
||||
struct phys_page_desc dummy, *page_info;
|
||||
dummy.base = base;
|
||||
result = STATUS_SUCCESS;
|
||||
dummy.base = base;
|
||||
|
||||
node = lb_avl_tree_delete(&active_tree, &dummy.tree_node);
|
||||
if (node != NULL)
|
||||
{
|
||||
page_info = OBTAIN_STRUCT_ADDR(node, struct phys_page_desc, tree_node);
|
||||
lb_linked_list_push_back(&free_list, &page_info->free_list_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MM_INVALID_ARGUMENTS;
|
||||
}
|
||||
irql = ke_raise_irql(IRQL_HIGH);
|
||||
ke_rww_w_lock(&lock);
|
||||
|
||||
ke_rwwlock_writer_unlock_lower_irql(&lock, irql);
|
||||
node = lb_atree_delete(&active_tree, &dummy.tree_node);
|
||||
|
||||
return result;
|
||||
if (node != NULL)
|
||||
{
|
||||
page_info = OBTAIN_STRUCT_ADDR(node, struct phys_page_desc, tree_node);
|
||||
lb_llist_push_back(&free_list, &page_info->free_list_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
ke_rww_w_unlock(&lock);
|
||||
ke_lower_irql(irql);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
include $(MK)/prologue.mk
|
||||
|
||||
SRC_$(d) := $(d)/ref.c
|
||||
SRC_$(d) := $(d)/rf.c
|
||||
|
||||
include $(MK)/stdrules.mk
|
||||
|
||||
|
|
334
kernel/rf/ref.c
334
kernel/rf/ref.c
|
@ -1,334 +0,0 @@
|
|||
#include "kernel/rf/ref.h"
|
||||
#include "kernel/ke/alloc.h"
|
||||
#include "kernel/ke/spin_lock.h"
|
||||
#include "kernel/ke/assert.h"
|
||||
#include "kernel/ke/atomic.h"
|
||||
#include "lib/avl_tree.h"
|
||||
#include "status.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct avl_tree_node tree_node;
|
||||
handle_t handle;
|
||||
ref_node_t *ref;
|
||||
ref_free_func free_routine;
|
||||
} handle_node_t;
|
||||
|
||||
static void SXAPI rfp_handle_node_free(void *node)
|
||||
{
|
||||
ke_free(node);
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Ke Functions
|
||||
// ===========================
|
||||
|
||||
static struct avl_tree handle_tree;
|
||||
static bool initialized;
|
||||
static k_spin_lock_t handle_tree_lock;
|
||||
static uint32 handle_base;
|
||||
|
||||
static int32 rfp_handle_compare(struct avl_tree_node *tree_node, struct avl_tree_node *my_node)
|
||||
{
|
||||
handle_node_t *tcb = OBTAIN_STRUCT_ADDR(tree_node, handle_node_t, tree_node);
|
||||
handle_node_t *my_tcb = OBTAIN_STRUCT_ADDR(my_node, handle_node_t, tree_node);
|
||||
|
||||
if ((uintptr) tcb->handle > (uintptr) my_tcb->handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr) tcb->handle == (uintptr) my_tcb->handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static handle_node_t *rfp_search_handle_node(handle_t handle)
|
||||
{
|
||||
struct avl_tree_node *result;
|
||||
handle_node_t temp;
|
||||
temp.handle = handle;
|
||||
result = lb_avl_tree_search(&handle_tree, &temp.tree_node);
|
||||
return result == NULL ? NULL : OBTAIN_STRUCT_ADDR(result, handle_node_t, tree_node);
|
||||
}
|
||||
|
||||
sx_status SXAPI rf_reference_setup(void)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
lb_avl_tree_init(&handle_tree, rfp_handle_compare);
|
||||
ke_spin_lock_init(&handle_tree_lock);
|
||||
handle_base = K_HANDLE_BASE;
|
||||
initialized = TRUE;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
sx_status SXAPI rf_reference_create(ref_node_t *ref,
|
||||
ref_free_func free_func)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (ref == NULL || free_func == NULL)
|
||||
{
|
||||
return RF_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
ref->free_routine = free_func;
|
||||
ref->ref_count = 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
sx_status SXAPI rf_reference_obj(ref_node_t *ref_node)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (ref_node == NULL)
|
||||
{
|
||||
return RF_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
int32 old_ref_count = ke_interlocked_increment_32(&ref_node->ref_count, 1);
|
||||
|
||||
ke_assert(old_ref_count >= 1);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
sx_status SXAPI rf_dereference_obj(ref_node_t *ref_node)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (ref_node == NULL)
|
||||
{
|
||||
return RF_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
sx_status result = STATUS_SUCCESS;
|
||||
|
||||
int32 old_ref_count = ke_interlocked_increment_32(&ref_node->ref_count, -1);
|
||||
|
||||
ke_assert(old_ref_count >= 1);
|
||||
|
||||
if (old_ref_count == 1)
|
||||
{
|
||||
ref_node->free_routine(ref_node);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static sx_status SXAPI rf_open_obj_by_handle(handle_t handle, ref_node_t **out)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return RF_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
return RF_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
k_irql irql;
|
||||
sx_status status = STATUS_SUCCESS;
|
||||
ref_node_t *ref = NULL;
|
||||
|
||||
|
||||
irql = ke_spin_lock_raise_irql(&handle_tree_lock, IRQL_DPC_LEVEL);
|
||||
handle_node_t *handle_node = rfp_search_handle_node(handle);
|
||||
if (handle_node == NULL)
|
||||
{
|
||||
status = RF_INVALID_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref = handle_node->ref;
|
||||
}
|
||||
|
||||
// PREREQUISITE: Having a handle -> having a reference
|
||||
// MUST GUARANTEE that handle exists while we reference
|
||||
if (sx_success(status))
|
||||
{
|
||||
// reference the object then return the reference
|
||||
rf_reference_obj(ref);
|
||||
*out = ref;
|
||||
}
|
||||
|
||||
ke_spin_unlock_lower_irql(&handle_tree_lock, irql);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static sx_status SXAPI rf_create_handle(ref_node_t *ref,
|
||||
handle_node_t *node,
|
||||
handle_t *out)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return RF_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (ref == NULL || node == NULL || out == NULL)
|
||||
{
|
||||
return RF_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
sx_status result = STATUS_SUCCESS;
|
||||
k_irql irql;
|
||||
|
||||
|
||||
if (sx_success(result))
|
||||
{
|
||||
// TODO: CHECK OVERFLOW
|
||||
node->handle = (handle_t) ke_interlocked_increment_32((int32*)&handle_base, 1);
|
||||
node->ref = ref;
|
||||
irql = ke_spin_lock_raise_irql(&handle_tree_lock, IRQL_DPC_LEVEL);
|
||||
handle_node_t *existing_node = rfp_search_handle_node(node->handle);
|
||||
if (existing_node == NULL)
|
||||
{
|
||||
lb_avl_tree_insert(&handle_tree, &node->tree_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = RF_DUPLICATED_HANDLE;
|
||||
}
|
||||
|
||||
ke_spin_unlock_lower_irql(&handle_tree_lock, irql);
|
||||
}
|
||||
|
||||
|
||||
if (sx_success(result))
|
||||
{
|
||||
rf_reference_obj(ref);
|
||||
*out = node->handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->free_routine(node);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static sx_status SXAPI rf_close_handle(handle_t handle)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return RF_UNINITIALIZED;
|
||||
}
|
||||
|
||||
k_irql irql;
|
||||
sx_status status = STATUS_SUCCESS;
|
||||
ref_node_t *ref = NULL;
|
||||
bool free = FALSE;
|
||||
|
||||
irql = ke_spin_lock_raise_irql(&handle_tree_lock, IRQL_DPC_LEVEL);
|
||||
handle_node_t *handle_node = rfp_search_handle_node(handle);
|
||||
if (handle_node == NULL)
|
||||
{
|
||||
status = RF_INVALID_HANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref = handle_node->ref;
|
||||
lb_avl_tree_delete(&handle_tree, &handle_node->tree_node);
|
||||
free = TRUE;
|
||||
}
|
||||
ke_spin_unlock_lower_irql(&handle_tree_lock, irql);
|
||||
|
||||
if (free)
|
||||
{
|
||||
handle_node->free_routine(handle_node);
|
||||
}
|
||||
|
||||
if (sx_success(status))
|
||||
{
|
||||
// dereference the object
|
||||
rf_dereference_obj(ref);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
// ===========================
|
||||
// SX Functions
|
||||
// ===========================
|
||||
|
||||
sx_status SXAPI sx_create_handle(ref_node_t *ref, handle_t *out)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return RF_UNINITIALIZED;
|
||||
}
|
||||
|
||||
handle_node_t *node;
|
||||
node = (handle_node_t *) ke_alloc(sizeof(handle_node_t));
|
||||
if (node == NULL)
|
||||
{
|
||||
return RF_ALLOCATION_FAILED;
|
||||
}
|
||||
|
||||
node->free_routine = rfp_handle_node_free;
|
||||
|
||||
return rf_create_handle(ref, node, out);
|
||||
}
|
||||
|
||||
sx_status SXAPI sx_close_handle(handle_t handle)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return RF_UNINITIALIZED;
|
||||
}
|
||||
|
||||
// need to keep sx version since need to do handle check here
|
||||
|
||||
return rf_close_handle(handle);
|
||||
}
|
||||
|
||||
sx_status SXAPI sx_open_obj_by_handle(handle_t handle, ref_node_t **out)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC_LEVEL);
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
return RF_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
return RF_INVALID_ARGUMENTS;
|
||||
}
|
||||
|
||||
// check special handles first
|
||||
// if (handle == K_HANDLE_CURRENT_THREAD)
|
||||
// {
|
||||
// // no need to ref first since definitely current thread context
|
||||
// hw_tcb_t *tcb = ke_current_thread();
|
||||
// ke_reference_obj(&tcb->ref_node);
|
||||
// *out = &tcb->ref_node;
|
||||
// return STATUS_SUCCESS;
|
||||
// }
|
||||
|
||||
return rf_open_obj_by_handle(handle, out);
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
#include "rp.h"
|
||||
#include "kernel/ke.h"
|
||||
#include "kernel/lb.h"
|
||||
|
||||
#define K_IDENT_BASE (0x80000000ul)
|
||||
|
||||
static struct atree ident_tree;
|
||||
static struct spin_lock ident_tree_lock;
|
||||
static uint32 ident_base;
|
||||
|
||||
|
||||
static int32
|
||||
handle_compare(struct atree_node *tree_node, struct atree_node *my_node)
|
||||
{
|
||||
struct ident_node *tcb = OBTAIN_STRUCT_ADDR(tree_node, struct ident_node, tree_node);
|
||||
struct ident_node *my_tcb = OBTAIN_STRUCT_ADDR(my_node, struct ident_node, tree_node);
|
||||
|
||||
if ((uintptr) tcb->ident > (uintptr) my_tcb->ident)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr) tcb->ident == (uintptr) my_tcb->ident)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct ident_node *
|
||||
search_handle_node(k_ident ident)
|
||||
{
|
||||
struct atree_node *result;
|
||||
struct ident_node temp;
|
||||
temp.ident = ident;
|
||||
result = lb_atree_search(&ident_tree, &temp.tree_node);
|
||||
return result == NULL ? NULL : OBTAIN_STRUCT_ADDR(result, struct ident_node, tree_node);
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_ref_init(void)
|
||||
{
|
||||
lb_atree_init(&ident_tree, handle_compare);
|
||||
ke_spin_init(&ident_tree_lock);
|
||||
ident_base = K_IDENT_BASE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_ref_node_init(struct ref_node *rf_node, ref_free_fp free_func)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC);
|
||||
|
||||
rf_node->f_free = free_func;
|
||||
rf_node->ref_count = 1;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_ref_obj(struct ref_node *ref_node)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC);
|
||||
|
||||
if (ref_node == NULL)
|
||||
{
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
int32 old_ref_count = ke_atomic_inc_32(&ref_node->ref_count, 1);
|
||||
|
||||
ke_assert(old_ref_count >= 1);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_deref_obj(struct ref_node *rf_node)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC);
|
||||
|
||||
if (rf_node == NULL)
|
||||
{
|
||||
return STATUS_INVALID_ARGS;
|
||||
}
|
||||
|
||||
k_status result = STATUS_SUCCESS;
|
||||
|
||||
int32 old_ref_count = ke_atomic_inc_32(&rf_node->ref_count, -1);
|
||||
|
||||
ke_assert(old_ref_count >= 1);
|
||||
|
||||
if (old_ref_count == 1)
|
||||
{
|
||||
rf_node->f_free(rf_node);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_open_obj_by_ident(k_ident id, struct ref_node **out)
|
||||
{
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC);
|
||||
|
||||
uint32 irql;
|
||||
k_status status = STATUS_SUCCESS;
|
||||
struct ref_node *ref = NULL;
|
||||
|
||||
irql = ke_raise_irql(IRQL_DPC);
|
||||
ke_spin_lock(&ident_tree_lock);
|
||||
struct ident_node *ident_node = search_handle_node(id);
|
||||
if (ident_node == NULL)
|
||||
{
|
||||
status = STATUS_INVALID_ARGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref = ident_node->obj;
|
||||
}
|
||||
|
||||
// PREREQUISITE: Having a handle -> having a reference
|
||||
// MUST GUARANTEE that handle exists while we reference
|
||||
if (SX_SUCCESS(status))
|
||||
{
|
||||
// reference the object then return the reference
|
||||
rf_ref_obj(ref);
|
||||
*out = ref;
|
||||
}
|
||||
|
||||
ke_spin_unlock(&ident_tree_lock);
|
||||
ke_lower_irql(irql);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_ident_create(struct ref_node *rf_node, struct ident_node *id_node, k_ident *out)
|
||||
{
|
||||
k_status result;
|
||||
uint32 irql;
|
||||
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC);
|
||||
|
||||
result = STATUS_SUCCESS;
|
||||
|
||||
// TODO: CHECK OVERFLOW
|
||||
id_node->ident = (k_ident) ke_atomic_inc_32((int32 *) &ident_base, 1);
|
||||
id_node->obj = rf_node;
|
||||
|
||||
irql = ke_raise_irql(IRQL_DPC);
|
||||
ke_spin_lock(&ident_tree_lock);
|
||||
|
||||
struct ident_node *existing_node = search_handle_node(id_node->ident);
|
||||
if (existing_node == NULL)
|
||||
{
|
||||
lb_atree_insert(&ident_tree, &id_node->tree_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* Shouldn't get to here
|
||||
*/
|
||||
result = STATUS_DUPLICATE;
|
||||
}
|
||||
|
||||
ke_spin_unlock(&ident_tree_lock);
|
||||
ke_lower_irql(irql);
|
||||
|
||||
|
||||
if (SX_SUCCESS(result))
|
||||
{
|
||||
rf_ref_obj(rf_node);
|
||||
*out = id_node->ident;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
k_status
|
||||
rf_ident_close(k_ident id)
|
||||
{
|
||||
uint32 irql;
|
||||
k_status status;
|
||||
struct ref_node *ref;
|
||||
|
||||
ke_assert(ke_get_irql() <= IRQL_DPC);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
ref = NULL;
|
||||
|
||||
irql = ke_raise_irql(IRQL_DPC);
|
||||
ke_spin_lock(&ident_tree_lock);
|
||||
|
||||
struct ident_node *id_node = search_handle_node(id);
|
||||
if (id_node == NULL)
|
||||
{
|
||||
status = STATUS_INVALID_ARGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ref = id_node->obj;
|
||||
lb_atree_delete(&ident_tree, &id_node->tree_node);
|
||||
}
|
||||
|
||||
ke_spin_unlock(&ident_tree_lock);
|
||||
ke_lower_irql(irql);
|
||||
|
||||
if (SX_SUCCESS(status))
|
||||
{
|
||||
/**
|
||||
* Success means already freed
|
||||
*/
|
||||
id_node->free_routine(id_node);
|
||||
/**
|
||||
* Dereference the object
|
||||
*/
|
||||
rf_deref_obj(ref);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include "kernel/rf.h"
|
10
lib/Rules.mk
10
lib/Rules.mk
|
@ -1,10 +0,0 @@
|
|||
include $(MK)/prologue.mk
|
||||
|
||||
SRC_$(d) := $(d)/avl_tree.c \
|
||||
$(d)/linked_list.c \
|
||||
$(d)/salloc.c \
|
||||
$(d)/sxtdlib.c
|
||||
|
||||
include $(MK)/stdrules.mk
|
||||
|
||||
include $(MK)/epilogue.mk
|
599
lib/avl_tree.c
599
lib/avl_tree.c
|
@ -1,599 +0,0 @@
|
|||
#include "lib/avl_tree.h"
|
||||
|
||||
static inline int32 SXAPI lbp_avl_tree_node_get_height(struct avl_tree_node *node)
|
||||
{
|
||||
return node == NULL ? -1 : node->height;
|
||||
}
|
||||
|
||||
static inline int32 SXAPI lbp_avl_tree_node_get_balance_factor(struct avl_tree_node *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return lbp_avl_tree_node_get_height(node->left) - lbp_avl_tree_node_get_height(node->right);
|
||||
}
|
||||
|
||||
static struct avl_tree_node *SXAPI lbp_avl_tree_node_right_rotate(struct avl_tree_node *root)
|
||||
{
|
||||
struct avl_tree_node *left_children = root->left;
|
||||
//adjust parents first
|
||||
left_children->parent = root->parent;
|
||||
root->parent = left_children;
|
||||
if (left_children->right != NULL)
|
||||
{
|
||||
left_children->right->parent = root;
|
||||
}
|
||||
//perform rotation
|
||||
root->left = root->left->right;
|
||||
left_children->right = root;
|
||||
//adjust height
|
||||
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
|
||||
left_children->height =
|
||||
lb_max_32(lbp_avl_tree_node_get_height(left_children->left),
|
||||
lbp_avl_tree_node_get_height(left_children->right)) + 1;
|
||||
return left_children;
|
||||
}
|
||||
|
||||
static struct avl_tree_node *SXAPI lbp_avl_tree_node_left_rotate(struct avl_tree_node *root)
|
||||
{
|
||||
struct avl_tree_node *right_children = root->right;
|
||||
//adjust parents
|
||||
right_children->parent = root->parent;
|
||||
root->parent = right_children;
|
||||
if (right_children->left != NULL)
|
||||
{
|
||||
right_children->left->parent = root;
|
||||
}
|
||||
//perform rotation
|
||||
root->right = root->right->left;
|
||||
right_children->left = root;
|
||||
|
||||
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
|
||||
right_children->height =
|
||||
lb_max_32(lbp_avl_tree_node_get_height(right_children->left),
|
||||
lbp_avl_tree_node_get_height(right_children->right)) +
|
||||
1;
|
||||
return right_children;
|
||||
}
|
||||
|
||||
static struct avl_tree_node *SXAPI lbp_avl_tree_node_balance(struct avl_tree_node *node)
|
||||
{
|
||||
const int32 bf = lbp_avl_tree_node_get_balance_factor(node);
|
||||
|
||||
if (bf > 1)
|
||||
{
|
||||
const int32 left_bf = lbp_avl_tree_node_get_balance_factor(node->left);
|
||||
if (left_bf >= 0)
|
||||
{
|
||||
//left left
|
||||
return lbp_avl_tree_node_right_rotate(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
//left right
|
||||
node->left = lbp_avl_tree_node_left_rotate(node->left);
|
||||
return lbp_avl_tree_node_right_rotate(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bf < -1)
|
||||
{
|
||||
const int32 right_bf = lbp_avl_tree_node_get_balance_factor(node->right);
|
||||
if (right_bf <= 0)
|
||||
{
|
||||
// right right
|
||||
return lbp_avl_tree_node_left_rotate(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
// right left
|
||||
node->right = lbp_avl_tree_node_right_rotate(node->right);
|
||||
return lbp_avl_tree_node_left_rotate(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static struct avl_tree_node *SXAPI lbp_avl_tree_node_insert(struct avl_tree_node *root, struct avl_tree_node *node,
|
||||
avl_tree_compare_func compare,
|
||||
struct avl_tree_node *parent)
|
||||
{
|
||||
if (node == NULL || compare == NULL)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
if (root == NULL)
|
||||
{
|
||||
node->parent = parent;
|
||||
return node;
|
||||
}
|
||||
|
||||
const int32 comp = compare(root, node);
|
||||
if (comp < 0)
|
||||
{
|
||||
root->right = lbp_avl_tree_node_insert(root->right, node, compare, root);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp == 0)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
root->left = lbp_avl_tree_node_insert(root->left, node, compare, root);
|
||||
}
|
||||
}
|
||||
|
||||
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
|
||||
|
||||
return lbp_avl_tree_node_balance(root);
|
||||
}
|
||||
|
||||
static void SXAPI lbp_avl_tree_swap_nodes(struct avl_tree_node *node1, struct avl_tree_node *node2)
|
||||
{
|
||||
if (node1 == NULL || node2 == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct avl_tree_node *parent = NULL;
|
||||
struct avl_tree_node *child = NULL;
|
||||
struct avl_tree_node *temp = NULL;
|
||||
//swap node but does not change anything else other than node1,node2
|
||||
// determine the parent/child relationship
|
||||
if (node1->parent != NULL && node1->parent == node2)
|
||||
{
|
||||
parent = node2;
|
||||
child = node1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node2->parent != NULL && node2->parent == node1)
|
||||
{
|
||||
parent = node1;
|
||||
child = node2;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent != NULL && child != NULL)
|
||||
{
|
||||
//connected case
|
||||
if (parent->parent != NULL)
|
||||
{
|
||||
if (parent->parent->left == parent)
|
||||
{
|
||||
parent->parent->left = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->parent->right = child;
|
||||
}
|
||||
}
|
||||
//update left/right for parent
|
||||
if (parent->left != NULL && child != parent->left)
|
||||
{
|
||||
parent->left->parent = child;
|
||||
}
|
||||
if (parent->right != NULL && child != parent->right)
|
||||
{
|
||||
parent->right->parent = child;
|
||||
}
|
||||
//update left/right for children
|
||||
if (child->left != NULL)
|
||||
{
|
||||
child->left->parent = parent;
|
||||
}
|
||||
if (child->right != NULL)
|
||||
{
|
||||
child->right->parent = parent;
|
||||
}
|
||||
|
||||
child->parent = parent->parent;
|
||||
parent->parent = child;
|
||||
if (child == parent->left)
|
||||
{
|
||||
/* parent
|
||||
/ \
|
||||
children */
|
||||
parent->left = child->left;
|
||||
child->left = parent;
|
||||
|
||||
temp = parent->right;
|
||||
parent->right = child->right;
|
||||
child->right = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* parent
|
||||
/ \
|
||||
children */
|
||||
parent->right = child->right;
|
||||
child->right = parent;
|
||||
|
||||
temp = parent->left;
|
||||
parent->left = child->left;
|
||||
child->left = temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//not connected case
|
||||
//adjust all the nodes other than node1,node2
|
||||
if (node1->left != NULL)
|
||||
{
|
||||
node1->left->parent = node2;
|
||||
}
|
||||
if (node1->right != NULL)
|
||||
{
|
||||
node1->right->parent = node2;
|
||||
}
|
||||
|
||||
if (node2->left != NULL)
|
||||
{
|
||||
node2->left->parent = node1;
|
||||
}
|
||||
if (node2->right != NULL)
|
||||
{
|
||||
node2->right->parent = node1;
|
||||
}
|
||||
|
||||
if (node1->parent != NULL)
|
||||
{
|
||||
if (node1->parent->left == node1)
|
||||
{
|
||||
node1->parent->left = node2;
|
||||
}
|
||||
else
|
||||
{
|
||||
node1->parent->right = node2;
|
||||
}
|
||||
}
|
||||
|
||||
if (node2->parent != NULL)
|
||||
{
|
||||
if (node2->parent->left == node2)
|
||||
{
|
||||
node2->parent->left = node1;
|
||||
}
|
||||
else
|
||||
{
|
||||
node2->parent->right = node1;
|
||||
}
|
||||
}
|
||||
|
||||
//adjust node1,node2
|
||||
temp = node1->parent;
|
||||
node1->parent = node2->parent;
|
||||
node2->parent = temp;
|
||||
|
||||
temp = node1->left;
|
||||
node1->left = node2->left;
|
||||
node2->left = temp;
|
||||
|
||||
temp = node1->right;
|
||||
node1->right = node2->right;
|
||||
node2->right = temp;
|
||||
}
|
||||
|
||||
//swap height
|
||||
int32 height = node1->height;
|
||||
node1->height = node2->height;
|
||||
node2->height = height;
|
||||
}
|
||||
|
||||
static struct avl_tree_node *SXAPI lbp_avl_tree_node_delete(struct avl_tree_node *root,
|
||||
struct avl_tree_node *node,
|
||||
avl_tree_compare_func compare,
|
||||
struct avl_tree_node **deleted_node)
|
||||
{
|
||||
if (root == NULL || node == NULL || compare == NULL || deleted_node == NULL)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
const int32 comp = compare(root, node);
|
||||
if (comp < 0)
|
||||
{
|
||||
root->right = lbp_avl_tree_node_delete(root->right, node, compare, deleted_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp > 0)
|
||||
{
|
||||
root->left = lbp_avl_tree_node_delete(root->left, node, compare, deleted_node);
|
||||
}
|
||||
else
|
||||
{
|
||||
*deleted_node = root;
|
||||
// node with only one child or no child
|
||||
if ((root->left == NULL) || (root->right == NULL))
|
||||
{
|
||||
struct avl_tree_node *child = root->left != NULL ? root->left : root->right;
|
||||
|
||||
if (child == NULL)
|
||||
{ // 0 child
|
||||
root = NULL;
|
||||
}
|
||||
else // 1 child
|
||||
{
|
||||
child->parent = root->parent;
|
||||
root = child;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// node with two children: Get the inorder successor (smallest
|
||||
// in the right subtree)
|
||||
struct avl_tree_node *successor = lb_avl_tree_larger(root);
|
||||
//swap fields
|
||||
lbp_avl_tree_swap_nodes(successor, root);
|
||||
|
||||
// Detach the inorder successor
|
||||
successor->right = lbp_avl_tree_node_delete(successor->right, root, compare, deleted_node);
|
||||
|
||||
root = successor;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (root == NULL)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
root->height = lb_max_32(lbp_avl_tree_node_get_height(root->left), lbp_avl_tree_node_get_height(root->right)) + 1;
|
||||
root = lbp_avl_tree_node_balance(root);
|
||||
return root;
|
||||
}
|
||||
|
||||
static struct avl_tree_node *SXAPI lbp_avl_tree_node_search(struct avl_tree_node *root, struct avl_tree_node *node,
|
||||
avl_tree_compare_func compare)
|
||||
{
|
||||
if (root == NULL || compare == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
const int32 comp = compare(root, node);
|
||||
if (comp < 0)
|
||||
{
|
||||
return lbp_avl_tree_node_search(root->right, node, compare);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comp == 0)
|
||||
{
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lbp_avl_tree_node_search(root->left, node, compare);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SXAPI lbp_avl_tree_node_init(struct avl_tree_node *it)
|
||||
{
|
||||
if (it != NULL)
|
||||
{
|
||||
it->height = 0;
|
||||
it->left = NULL;
|
||||
it->right = NULL;
|
||||
it->parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_smallest(struct avl_tree *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct avl_tree_node *entry = tree->root;
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
while (entry->left != NULL)
|
||||
{
|
||||
entry = entry->left;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_largest(struct avl_tree *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct avl_tree_node *entry = tree->root;
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
while (entry->right != NULL)
|
||||
{
|
||||
entry = entry->right;
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_larger(struct avl_tree_node *it)
|
||||
{
|
||||
if (it == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct avl_tree_node *root = it;
|
||||
if (root->right != NULL)
|
||||
{
|
||||
root = root->right;
|
||||
while (root->left != NULL)
|
||||
{
|
||||
root = root->left;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (root->parent != NULL)
|
||||
{
|
||||
if (root->parent->left == root)
|
||||
{
|
||||
return root->parent;
|
||||
}
|
||||
root = root->parent;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_smaller(struct avl_tree_node *it)
|
||||
{
|
||||
if (it == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct avl_tree_node *root = it;
|
||||
if (root->left != NULL)
|
||||
{
|
||||
root = root->left;
|
||||
while (root->right != NULL)
|
||||
{
|
||||
root = root->right;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (root->parent != NULL)
|
||||
{
|
||||
if (root->parent->right == root)
|
||||
{
|
||||
return root->parent;
|
||||
}
|
||||
root = root->parent;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_search(struct avl_tree *tree, struct avl_tree_node *node)
|
||||
{
|
||||
return lbp_avl_tree_node_search(tree->root, node, tree->compare);
|
||||
}
|
||||
|
||||
|
||||
void SXAPI lb_avl_tree_insert(struct avl_tree *tree, struct avl_tree_node *data)
|
||||
{
|
||||
if (tree != NULL && data != NULL)
|
||||
{
|
||||
lbp_avl_tree_node_init(data);
|
||||
tree->root = lbp_avl_tree_node_insert(tree->root, data, tree->compare, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
struct avl_tree_node *SXAPI lb_avl_tree_delete(struct avl_tree *tree, struct avl_tree_node *data)
|
||||
{
|
||||
struct avl_tree_node *node = NULL;
|
||||
if (tree != NULL && data != NULL)
|
||||
{
|
||||
tree->root = lbp_avl_tree_node_delete(tree->root, data, tree->compare, &node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
int32 SXAPI lb_avl_tree_size(struct avl_tree *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (tree->root == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int32 size = 0;
|
||||
struct avl_tree_node *entry = lb_avl_tree_smallest(tree);
|
||||
while (entry != NULL)
|
||||
{
|
||||
size++;
|
||||
entry = lb_avl_tree_larger(entry);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void SXAPI lb_avl_tree_init(struct avl_tree *tree, avl_tree_compare_func compare)
|
||||
{
|
||||
if (tree != NULL)
|
||||
{
|
||||
tree->compare = compare;
|
||||
tree->root = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TESTING STUFF
|
||||
|
||||
static int32 SXAPI lbp_avl_tree_node_calculate_height(struct avl_tree_node *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return lb_max_32(lbp_avl_tree_node_calculate_height(tree->left), lbp_avl_tree_node_calculate_height(tree->right)) +
|
||||
1;
|
||||
}
|
||||
|
||||
static bool SXAPI lbp_avl_tree_node_test(struct avl_tree_node *tree, avl_tree_compare_func compare)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (lbp_avl_tree_node_get_balance_factor(tree) < -1 || lbp_avl_tree_node_get_balance_factor(tree) > 1 ||
|
||||
lbp_avl_tree_node_calculate_height(tree) != tree->height)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (tree->left != NULL)
|
||||
{
|
||||
if (tree->left->parent != tree)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (tree->right != NULL)
|
||||
{
|
||||
if (tree->right->parent != tree)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (compare != NULL)
|
||||
{
|
||||
if ((tree->right != NULL && compare(tree, tree->right) > 0) ||
|
||||
(tree->left != NULL && compare(tree, tree->left) < 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return lbp_avl_tree_node_test(tree->left, compare) && lbp_avl_tree_node_test(tree->right, compare);
|
||||
}
|
||||
|
||||
bool SXAPI lb_avl_tree_validate(struct avl_tree *tree)
|
||||
{
|
||||
if (tree == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return lbp_avl_tree_node_test(tree->root, tree->compare);
|
||||
}
|
|
@ -1,306 +0,0 @@
|
|||
#include "lib/linked_list.h"
|
||||
|
||||
static inline void SXAPI lbp_init_linked_list_node(struct linked_list_node *node)
|
||||
{
|
||||
if (node != NULL)
|
||||
{
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI lb_linked_list_init(struct linked_list *list)
|
||||
{
|
||||
if (list != NULL)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
list->size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int32 SXAPI lb_linked_list_size(struct linked_list *list)
|
||||
{
|
||||
if (list == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return list->size;
|
||||
}
|
||||
|
||||
void SXAPI lb_linked_list_push_front(struct linked_list *list, struct linked_list_node *node)
|
||||
{
|
||||
if (list == NULL || node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lbp_init_linked_list_node(node);
|
||||
|
||||
lb_linked_list_insert_by_ref(list, NULL, node);
|
||||
}
|
||||
|
||||
void SXAPI lb_linked_list_push_back(struct linked_list *list, struct linked_list_node *node)
|
||||
{
|
||||
if (list == NULL || node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lbp_init_linked_list_node(node);
|
||||
|
||||
lb_linked_list_insert_by_ref(list, list->tail, node);
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_pop_front(struct linked_list *list)
|
||||
{
|
||||
struct linked_list_node *ret = NULL;
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = list->head;
|
||||
|
||||
lb_linked_list_remove_by_ref(list, list->head);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_pop_back(struct linked_list *list)
|
||||
{
|
||||
struct linked_list_node *ret = NULL;
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = list->tail;
|
||||
|
||||
lb_linked_list_remove_by_ref(list, list->tail);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void SXAPI lb_linked_list_insert_by_ref(struct linked_list *list, struct linked_list_node *cur_node,
|
||||
struct linked_list_node *new_node)
|
||||
{
|
||||
struct linked_list_node *left_node = NULL;
|
||||
struct linked_list_node *right_node = NULL;
|
||||
|
||||
if (list == NULL || new_node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lbp_init_linked_list_node(new_node);
|
||||
|
||||
/*
|
||||
* adjust the current node
|
||||
*/
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
new_node->next = list->head;
|
||||
new_node->prev = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_node->prev = cur_node;
|
||||
new_node->next = cur_node->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* assign left and right node
|
||||
*/
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
left_node = NULL;
|
||||
right_node = list->head == NULL ? NULL : list->head;
|
||||
}
|
||||
else
|
||||
{
|
||||
left_node = cur_node;
|
||||
right_node = cur_node->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* adjust left and right node accordingly
|
||||
*/
|
||||
if (left_node != NULL)
|
||||
{
|
||||
left_node->next = new_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->head = new_node;
|
||||
}
|
||||
|
||||
if (right_node != NULL)
|
||||
{
|
||||
right_node->prev = new_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->tail = new_node;
|
||||
}
|
||||
|
||||
list->size++;
|
||||
}
|
||||
|
||||
void SXAPI lb_linked_list_insert_by_idx(struct linked_list *list, int32 index, struct linked_list_node *node)
|
||||
{
|
||||
if (list == NULL || index < 0 || node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
struct linked_list_node *prev_node = lb_linked_list_get(list, index - 1);
|
||||
lbp_init_linked_list_node(node);
|
||||
|
||||
if (prev_node == NULL)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
lb_linked_list_insert_by_ref(list, NULL, node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lb_linked_list_insert_by_ref(list, prev_node, node);
|
||||
}
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_remove_by_idx(struct linked_list *list, int32 index)
|
||||
{
|
||||
if (list == NULL || index < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct linked_list_node *cur_node = lb_linked_list_get(list, index);
|
||||
|
||||
if (cur_node == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return lb_linked_list_remove_by_ref(list, cur_node);
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the next node
|
||||
*/
|
||||
struct linked_list_node *SXAPI lb_linked_list_remove_by_ref(struct linked_list *list, struct linked_list_node *node)
|
||||
{
|
||||
struct linked_list_node *ret = NULL;
|
||||
|
||||
if (list == NULL || node == NULL)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the left and right node
|
||||
*/
|
||||
if (node->prev != NULL)
|
||||
{
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->head = node->next;
|
||||
}
|
||||
|
||||
if (node->next != NULL)
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
list->tail = node->prev;
|
||||
}
|
||||
|
||||
ret = node->next;
|
||||
|
||||
lbp_init_linked_list_node(node);
|
||||
|
||||
list->size--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_get(struct linked_list *list, int32 index)
|
||||
{
|
||||
if (list == NULL || index < 0 || list->head == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct linked_list_node *cur_node = list->head;
|
||||
while (index-- && (cur_node = cur_node->next) != NULL)
|
||||
{}
|
||||
return cur_node;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_next(struct linked_list_node *node)
|
||||
{
|
||||
if (node != NULL)
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_prev(struct linked_list_node *node)
|
||||
{
|
||||
if (node != NULL)
|
||||
{
|
||||
node = node->prev;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_first(struct linked_list *list)
|
||||
{
|
||||
struct linked_list_node *result = NULL;
|
||||
if (list != NULL)
|
||||
{
|
||||
result = list->head;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_last(struct linked_list *list)
|
||||
{
|
||||
struct linked_list_node *result = NULL;
|
||||
if (list != NULL)
|
||||
{
|
||||
result = list->tail;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct linked_list_node *SXAPI lb_linked_list_search(struct linked_list *list, void *obj, linked_list_cmp_func cmp_func)
|
||||
{
|
||||
struct linked_list_node *ret = NULL;
|
||||
struct linked_list_node *node = lb_linked_list_first(list);
|
||||
|
||||
if (list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
if (cmp_func(node, obj) == 0)
|
||||
{
|
||||
ret = node;
|
||||
break;
|
||||
}
|
||||
|
||||
node = lb_linked_list_next(node);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
219
lib/salloc.c
219
lib/salloc.c
|
@ -1,219 +0,0 @@
|
|||
#include "type.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
#include "lib/salloc.h"
|
||||
|
||||
struct salloc_header
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32 size;
|
||||
uint32 flags;
|
||||
};
|
||||
};
|
||||
|
||||
#define ALLOC_FLAG_NUM 2
|
||||
#define ALLOC_HEADER_FLAG_FREE 0
|
||||
#define ALLOC_HEADER_FLAG_LAST 1
|
||||
|
||||
static void lbp_set_salloc_header_size(struct salloc_header *header, uint32 size)
|
||||
{
|
||||
// align the integer, ignoring overflowed bits
|
||||
size <<= ALLOC_FLAG_NUM;
|
||||
|
||||
// clear ALLOC_FLAG_NUM-th to 31-th bits
|
||||
header->size &= ~(uint32) lb_bit_field_mask(ALLOC_FLAG_NUM, 31);
|
||||
// set bits
|
||||
header->size |= size;
|
||||
}
|
||||
|
||||
static uint32 lbp_read_salloc_header_size(struct salloc_header *header)
|
||||
{
|
||||
return header->size >> ALLOC_FLAG_NUM;
|
||||
}
|
||||
|
||||
static uint32 lbp_read_salloc_header_flag(struct salloc_header *header, uint32 bit)
|
||||
{
|
||||
return (header->flags & (uint32) lb_bit_mask(bit)) == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
static void lbp_set_salloc_header_flag(struct salloc_header *header, uint32 bit, uint32 value)
|
||||
{
|
||||
value &= (uint32) lb_bit_mask(0);
|
||||
if (value == 1)
|
||||
{
|
||||
header->flags |= (uint32) lb_bit_mask(bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
header->flags &= ~(uint32) lb_bit_mask(bit);
|
||||
}
|
||||
}
|
||||
|
||||
static void lbp_salloc_join(void *base)
|
||||
{
|
||||
if (base != NULL)
|
||||
{
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 c_blk_free = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 c_blk_last = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 c_blk_size = lbp_read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
char *n_ptr = c_blk_last == 1 ? NULL : c_ptr + c_blk_size;
|
||||
if (n_ptr != NULL && c_blk_free == 1)
|
||||
{
|
||||
// if this is not the last block and the prev block is free
|
||||
uint32 n_blk_free = lbp_read_salloc_header_flag((struct salloc_header *) n_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 n_blk_last = lbp_read_salloc_header_flag((struct salloc_header *) n_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 n_blk_size = lbp_read_salloc_header_size((struct salloc_header *) n_ptr);
|
||||
|
||||
if (n_blk_free == 1)
|
||||
{
|
||||
// logically gone
|
||||
lbp_set_salloc_header_size((struct salloc_header *) c_ptr, n_blk_size + c_blk_size);
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, n_blk_last);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// update the c_ptr
|
||||
if (c_blk_last == 0)
|
||||
{
|
||||
c_ptr += c_blk_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SXAPI lb_salloc_assert(void *base, const uint32 *blk_size, const bool *blk_free, uint32 size)
|
||||
{
|
||||
if (base == NULL || blk_free == NULL || blk_size == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
uint32 i = 0;
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 cur_blk_free = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 cur_blk_last = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 cur_blk_size = lbp_read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
if (cur_blk_free != blk_free[i] || cur_blk_size != blk_size[i])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ptr += cur_blk_size;
|
||||
i++;
|
||||
}
|
||||
if (cur_blk_last == 1)
|
||||
{
|
||||
return i == size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI lb_salloc_init(void *base, uint32 size)
|
||||
{
|
||||
if (base != NULL && size >= sizeof(struct salloc_header))
|
||||
{
|
||||
struct salloc_header *ptr = (struct salloc_header *) base;
|
||||
lbp_set_salloc_header_size(ptr, size);
|
||||
lbp_set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_FREE, 1);
|
||||
lbp_set_salloc_header_flag(ptr, ALLOC_HEADER_FLAG_LAST, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void *SXAPI lb_salloc(void *base, uint32 size)
|
||||
{
|
||||
void *result = NULL;
|
||||
if (base != NULL && size != 0)
|
||||
{
|
||||
uint32 total_size = size + sizeof(struct salloc_header);
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 cur_blk_free = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 cur_blk_size = lbp_read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
uint32 cur_blk_last = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
if (cur_blk_free == 0 || cur_blk_size < total_size)
|
||||
{
|
||||
//if cur block not a free block
|
||||
//or the current block size is less than the size we want
|
||||
if (cur_blk_last == 1)
|
||||
{
|
||||
//if last one, break and fail.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ptr += cur_blk_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have a free block with enough size
|
||||
if (total_size == cur_blk_size ||
|
||||
cur_blk_size - total_size < sizeof(struct salloc_header))
|
||||
{
|
||||
// since the space left is not enough for salloc_header
|
||||
// we alloc the whole block
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we split the block here
|
||||
// set properties for the first block
|
||||
lbp_set_salloc_header_size((struct salloc_header *) c_ptr, total_size);
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST, 0);
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 0);
|
||||
|
||||
// set properties for the second block
|
||||
lbp_set_salloc_header_size((struct salloc_header *) (c_ptr + total_size), cur_blk_size - total_size);
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_LAST,
|
||||
cur_blk_last);
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) (c_ptr + total_size), ALLOC_HEADER_FLAG_FREE, 1);
|
||||
}
|
||||
// return the pointer, skip the alloc header
|
||||
result = c_ptr + sizeof(struct salloc_header);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SXAPI lb_sfree(void *base, void *ptr)
|
||||
{
|
||||
if (base != NULL && ptr != NULL)
|
||||
{
|
||||
char *c_ptr = (char *) base;
|
||||
while (1)
|
||||
{
|
||||
uint32 cur_blk_free = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE);
|
||||
uint32 cur_blk_last = lbp_read_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST);
|
||||
uint32 cur_blk_size = lbp_read_salloc_header_size((struct salloc_header *) c_ptr);
|
||||
if (cur_blk_free == 0 && ptr == c_ptr + sizeof(struct salloc_header))
|
||||
{
|
||||
// we found the block, mark it as free
|
||||
lbp_set_salloc_header_flag((struct salloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE, 1);
|
||||
// merge blocks
|
||||
lbp_salloc_join(base);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur_blk_last == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ptr += cur_blk_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
112
lib/sxtdlib.c
112
lib/sxtdlib.c
|
@ -1,112 +0,0 @@
|
|||
#include "type.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
|
||||
void SXAPI lb_mem_copy(void *src, void *dst, uint64 size)
|
||||
{
|
||||
if (src == NULL || dst == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
char *cSrc = (char *) src;
|
||||
char *cDst = (char *) dst;
|
||||
while (size--)
|
||||
{
|
||||
*(cDst++) = *(cSrc++);
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI lb_mem_set(void *src, uint8 const val, uint64 size)
|
||||
{
|
||||
if (src == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
while (size--)
|
||||
{
|
||||
*(uint8 *) src = val;
|
||||
src = (void *) ((uintptr) src + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI lb_mem_move(void *src, void *dst, uint64 size)
|
||||
{
|
||||
if (src == NULL || dst == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (src >= dst)
|
||||
{
|
||||
lb_mem_copy(src, dst, size);
|
||||
return;
|
||||
}
|
||||
src = (void *) ((uintptr) src + size - 1);
|
||||
dst = (void *) ((uintptr) dst + size - 1);
|
||||
while (size--)
|
||||
{
|
||||
*(char *) dst = *(char *) src;
|
||||
dst = (void *) ((uintptr) dst - 1);
|
||||
src = (void *) ((uintptr) src - 1);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Random Generator
|
||||
//
|
||||
static uint32 seed = 1;
|
||||
static uint32 max = 16777215;
|
||||
|
||||
uint32 SXAPI lb_rand(void)
|
||||
{
|
||||
seed = seed * 1103512986 + 29865;
|
||||
return (unsigned int) (seed / 65536) % (max + 1);
|
||||
}
|
||||
|
||||
void SXAPI lb_srand(uint32 _seed)
|
||||
{
|
||||
seed = _seed;
|
||||
}
|
||||
|
||||
void SXAPI lb_mrand(uint32 _max)
|
||||
{
|
||||
max = _max;
|
||||
}
|
||||
|
||||
//
|
||||
// String Library
|
||||
//
|
||||
|
||||
uint64 SXAPI lb_str_len(char const *str)
|
||||
{
|
||||
uint64 length = 0;
|
||||
if (str == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (*str != 0)
|
||||
{
|
||||
str++;
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
uint64 SXAPI lb_str_cmp(char const *str1, char const *str2)
|
||||
{
|
||||
if (str1 == NULL || str2 == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint64 length = lb_str_len(str1);
|
||||
if (length != lb_str_len(str2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
while (length--)
|
||||
{
|
||||
if (*(str1 + length) != *(str2 + length))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
include $(MK)/prologue.mk
|
||||
|
||||
SRCIN_$(d) := $(d)/linker.ld.in
|
||||
SRCIN_$(d) := $(d)/linker.ld.in \
|
||||
$(d)/grub.cfg.in
|
||||
|
||||
include $(MK)/stdrules.mk
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
menuentry "secX" {
|
||||
multiboot2 /secX/secxkrnl.elf
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
#define ASM_FILE
|
||||
#include "kernel/hal/mem.h"
|
||||
#include "common.h"
|
||||
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(ke_main)
|
||||
ENTRY(hal_main_32)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
|
|
@ -29,4 +29,4 @@ $(OBJIN_$(d)): $(OUT)/%: %.in
|
|||
OBJ := $(OBJ) $(OBJ_$(d)) $(OBJAS_$(d))
|
||||
CLEAN := $(CLEAN) $(OBJ_$(d)) $(OBJAS_$(d)) $(OBJIN_$(d)) $(DEP_$(d))
|
||||
|
||||
-include $(DEP_$(d))
|
||||
-include $(DEP_$(d))
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,947 +0,0 @@
|
|||
#include "driver.h"
|
||||
#include "test_case.h"
|
||||
#include "lib/avl_tree.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct avl_tree_node tree_entry;
|
||||
int32 val;
|
||||
} int_tree_node;
|
||||
|
||||
static int_tree_node *create_tree_node(int val)
|
||||
{
|
||||
int_tree_node *rs = talloc(sizeof(int_tree_node));
|
||||
rs->val = val;
|
||||
return rs;
|
||||
}
|
||||
|
||||
static int32 SXAPI compare(struct avl_tree_node *root, struct avl_tree_node *node)
|
||||
{
|
||||
int_tree_node *rooti = OBTAIN_STRUCT_ADDR(root, int_tree_node, tree_entry);
|
||||
int_tree_node *nodei = OBTAIN_STRUCT_ADDR(node, int_tree_node, tree_entry);
|
||||
return rooti->val - nodei->val;
|
||||
}
|
||||
|
||||
static void _pre_order(struct avl_tree_node *node, bool root)
|
||||
{
|
||||
if (node == NULL)
|
||||
return;
|
||||
int_tree_node *my_node = OBTAIN_STRUCT_ADDR(node, int_tree_node, tree_entry);
|
||||
printf("%d-", my_node->val);
|
||||
_pre_order(node->left, FALSE);
|
||||
_pre_order(node->right, FALSE);
|
||||
if (root)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void pre_order(struct avl_tree_node *node)
|
||||
{
|
||||
#ifdef TDBG
|
||||
_pre_order(node, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int counter = 0;
|
||||
|
||||
static bool _pre_order_assert(struct avl_tree_node *node, int order[], int size)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
if (counter >= size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool result = TRUE;
|
||||
int_tree_node *my_node = OBTAIN_STRUCT_ADDR(node, int_tree_node, tree_entry);
|
||||
if (order[counter] != my_node->val)
|
||||
{
|
||||
result = FALSE;
|
||||
}
|
||||
counter++;
|
||||
result = result && _pre_order_assert(node->left, order, size);
|
||||
result = result && _pre_order_assert(node->right, order, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool pre_order_assert(struct avl_tree *node, int order[], int size)
|
||||
{
|
||||
counter = 0;
|
||||
return _pre_order_assert(node->root, order, size);
|
||||
}
|
||||
|
||||
//////// TESTS/////////
|
||||
|
||||
static bool insert_simple_l(void)
|
||||
{
|
||||
//1 2
|
||||
// \ / \
|
||||
// 2 == 1L ==> 1 3
|
||||
// \
|
||||
// 3
|
||||
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(1)->tree_entry);
|
||||
pre_order(tree.root);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
pre_order(tree.root);
|
||||
int val1[] = {1, 2};
|
||||
result = result && pre_order_assert(&tree, val1, 2);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
pre_order(tree.root);
|
||||
int val2[] = {2, 1, 3};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_simple_r(void)
|
||||
{
|
||||
// 3 2
|
||||
// / / \
|
||||
// 2 == 1R ==> 1 3
|
||||
// /
|
||||
//1
|
||||
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
int val1[] = {3, 2};
|
||||
result = result && pre_order_assert(&tree, val1, 2);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(1)->tree_entry);
|
||||
|
||||
int val2[] = {2, 1, 3};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_simple_ll(void)
|
||||
{
|
||||
//2 3
|
||||
// \ / \
|
||||
// 4 == 2L ==> 2 4
|
||||
// /
|
||||
//3
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
int val1[] = {2, 4};
|
||||
result = result && pre_order_assert(&tree, val1, 2);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
|
||||
int val2[] = {3, 2, 4};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_simple_rr(void)
|
||||
{
|
||||
// 4 3
|
||||
// / / \
|
||||
//2 == 2R ==> 2 4
|
||||
// \
|
||||
// 3
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
int val1[] = {4, 2};
|
||||
result = result && pre_order_assert(&tree, val1, 2);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
|
||||
int val2[] = {3, 2, 4};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_complex_1(void)
|
||||
{
|
||||
// 20+ 20++ 20++ 9
|
||||
// / \ / \ / \ / \
|
||||
// 4 26 => 4- 26 => 9+ 26 => 4+ 20
|
||||
// / \ / \ / \ / / \
|
||||
//3 9 3 9- 4+ 15 3 15 26
|
||||
// \ /
|
||||
// 15 3
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(26)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(9)->tree_entry);
|
||||
int val1[] = {20, 4, 3, 9, 26};
|
||||
result = result && pre_order_assert(&tree, val1, 5);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
|
||||
int val2[] = {9, 4, 3, 20, 15, 26};
|
||||
result = result && pre_order_assert(&tree, val2, 6);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_complex_2(void)
|
||||
{
|
||||
// 20+ 20++ 20++ 9
|
||||
// / \ / \ / \ / \
|
||||
// 4 26 => 4- 26 => 9++ 26 => 4 20-
|
||||
// / \ / \ / / \ \
|
||||
//3 9 3 9+ 4 3 8 26
|
||||
// / / \
|
||||
// 8 3 8
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(26)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(9)->tree_entry);
|
||||
int val1[] = {20, 4, 3, 9, 26};
|
||||
result = result && pre_order_assert(&tree, val1, 5);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(8)->tree_entry);
|
||||
|
||||
int val2[] = {9, 4, 3, 8, 20, 26};
|
||||
result = result && pre_order_assert(&tree, val2, 6);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_complex_3(void)
|
||||
{
|
||||
// __20+__ _20++_ __20++_ ___9___
|
||||
// / \ / \ / \ / \
|
||||
// 4 26 => 4- 26 => 9+ 26 => 4+ __20__
|
||||
// / \ / \ / \ / \ / \ / \ / \ / \
|
||||
// 3+ 9 21 30 3+ 9- 21 30 4+ 11- 21 30 3+ 7 11- 26
|
||||
// / / \ / / \ / \ \ / \ / \
|
||||
//2 7 11 2 7 11- 3+ 7 15 2 15 21 30
|
||||
// \ /
|
||||
// 15 2
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(26)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(9)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(21)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(7)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(11)->tree_entry);
|
||||
int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30};
|
||||
result = result && pre_order_assert(&tree, val1, 10);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
|
||||
int val2[] = {9, 4, 3, 2, 7, 20, 11, 15, 26, 21, 30};
|
||||
result = result && pre_order_assert(&tree, val2, 11);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_complex_4(void)
|
||||
{
|
||||
// __20+__ _20++_ __20++_ ___9___
|
||||
// / \ / \ / \ / \
|
||||
// 4 26 4- 26 9+ 26 4 _20-
|
||||
// / \ / \ / \ / \ / \ / \ / \ / \
|
||||
// 3+ 9 21 30 => 3+ 9+ 21 30 => 4 11 21 30 => 3+ 7- 11 26
|
||||
// / / \ / / \ / \ / \ / \
|
||||
//2 7 11 2 7- 11 3+ 7- 2 8 21 30
|
||||
// \ / \
|
||||
// 8 2 8
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(26)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(9)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(21)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(7)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(11)->tree_entry);
|
||||
int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30};
|
||||
result = result && pre_order_assert(&tree, val1, 10);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(8)->tree_entry);
|
||||
|
||||
int val2[] = {9, 4, 3, 2, 7, 8, 20, 11, 26, 21, 30};
|
||||
result = result && pre_order_assert(&tree, val2, 11);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool insert_duplicate(void)
|
||||
{
|
||||
// __20+__ _20++_ __20++_ ___9___
|
||||
// / \ / \ / \ / \
|
||||
// 4 26 4- 26 9+ 26 4 _20-
|
||||
// / \ / \ / \ / \ / \ / \ / \ / \
|
||||
// 3+ 9 21 30 => 3+ 9+ 21 30 => 4 11 21 30 => 3+ 7- 11 26
|
||||
// / / \ / / \ / \ / \ / \
|
||||
//2 7 11 2 7- 11 3+ 7- 2 8 21 30
|
||||
// \ / \
|
||||
// 8 2 8
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(26)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(9)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(21)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(7)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(11)->tree_entry);
|
||||
int val1[] = {20, 4, 3, 2, 9, 7, 11, 26, 21, 30};
|
||||
result = result && pre_order_assert(&tree, val1, 10);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(7)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
|
||||
result = result && pre_order_assert(&tree, val1, 10);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
|
||||
static bool delete_simple_l(void)
|
||||
{
|
||||
// 2 3
|
||||
// x \ / \
|
||||
//1 3 == 1L ==> 2 4
|
||||
// \
|
||||
// 4
|
||||
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(1);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
int val1[] = {2, 1, 3, 4};
|
||||
result = result && pre_order_assert(&tree, val1, 4);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {3, 2, 4};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_simple_r(void)
|
||||
{
|
||||
// 3 2
|
||||
// / x / \
|
||||
// 2 4 == 1R ==> 1 3
|
||||
// /
|
||||
//1
|
||||
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(4);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(1)->tree_entry);
|
||||
int val1[] = {3, 2, 1, 4};
|
||||
result = result && pre_order_assert(&tree, val1, 4);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {2, 1, 3};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_simple_ll(void)
|
||||
{
|
||||
// 2 3
|
||||
// x \ / \
|
||||
//1 4 == 2L ==> 2 4
|
||||
// /
|
||||
// 3
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(1);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(4)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
int val1[] = {2, 1, 4, 3};
|
||||
result = result && pre_order_assert(&tree, val1, 4);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {3, 2, 4};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_simple_rr(void)
|
||||
{
|
||||
// 3 2
|
||||
// / x / \
|
||||
//2 4 == 2R ==> 1 3
|
||||
// \
|
||||
// 1
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(4);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(3)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(2)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(1)->tree_entry);
|
||||
int val1[] = {3, 2, 1, 4};
|
||||
result = result && pre_order_assert(&tree, val1, 4);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {2, 1, 3};
|
||||
result = result && pre_order_assert(&tree, val2, 3);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_1(void)
|
||||
{
|
||||
// Test Case #1
|
||||
// - A single node tree has its only node removed.
|
||||
// Create:
|
||||
// 10
|
||||
//
|
||||
// Call: remove(10)
|
||||
//
|
||||
// Result:
|
||||
// empty tree
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(10);
|
||||
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
int val1[] = {10};
|
||||
result = result && pre_order_assert(&tree, val1, 1);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
result = result && pre_order_assert(&tree, val1, 0);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_2(void)
|
||||
{
|
||||
// Test Case #2
|
||||
// - A small tree has its root removed.
|
||||
// Create:
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \
|
||||
// 25 35
|
||||
//
|
||||
// Call: remove(20)
|
||||
//
|
||||
// Results: (simplest result with no rotations)
|
||||
// (replace root with smallest value on the right or 25)
|
||||
//
|
||||
// 25
|
||||
// / \
|
||||
// 10 30
|
||||
// \
|
||||
// 35
|
||||
//
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(20);
|
||||
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(10)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(25)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(35)->tree_entry);
|
||||
int val1[] = {20, 10, 30, 25, 35};
|
||||
result = result && pre_order_assert(&tree, val1, 5);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {25, 10, 30, 35};
|
||||
result = result && pre_order_assert(&tree, val2, 4);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_3(void)
|
||||
{
|
||||
// Test Case #3
|
||||
// - A small tree has a node with 2 children removed
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ /
|
||||
// 5 15 25
|
||||
//
|
||||
// Call: remove(10)
|
||||
//
|
||||
// Results:
|
||||
// 20
|
||||
// / \
|
||||
// 15 30
|
||||
// / /
|
||||
// 5 25
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(10);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(5)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(25)->tree_entry);
|
||||
int val1[] = {20, 10, 5, 15, 30, 25};
|
||||
result = result && pre_order_assert(&tree, val1, 6);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {20, 15, 5, 30, 25};
|
||||
result = result && pre_order_assert(&tree, val2, 5);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_4(void)
|
||||
{
|
||||
// Test Case #4
|
||||
// - A small tree has all nodes but the root removed from the bottom up.
|
||||
// Create:
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ /
|
||||
// 5 15 25
|
||||
//
|
||||
// Call: remove(5), remove(15), remove(25), remove(10), remove(30)
|
||||
//
|
||||
//
|
||||
// Results:
|
||||
// 20
|
||||
//
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *delete5 = create_tree_node(5);
|
||||
int_tree_node *delete10 = create_tree_node(10);
|
||||
int_tree_node *delete15 = create_tree_node(15);
|
||||
int_tree_node *delete25 = create_tree_node(25);
|
||||
int_tree_node *delete30 = create_tree_node(30);
|
||||
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &delete10->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &delete30->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &delete5->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &delete15->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &delete25->tree_entry);
|
||||
|
||||
int val1[] = {20, 10, 5, 15, 30, 25};
|
||||
result = result && pre_order_assert(&tree, val1, 6);
|
||||
|
||||
lb_avl_tree_delete(&tree, &delete5->tree_entry);
|
||||
lb_avl_tree_delete(&tree, &delete15->tree_entry);
|
||||
lb_avl_tree_delete(&tree, &delete25->tree_entry);
|
||||
lb_avl_tree_delete(&tree, &delete10->tree_entry);
|
||||
lb_avl_tree_delete(&tree, &delete30->tree_entry);
|
||||
|
||||
int val2[] = {20};
|
||||
result = result && pre_order_assert(&tree, val2, 1);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_single_rotation(void)
|
||||
{
|
||||
// Test case single rotation
|
||||
//
|
||||
// Create:
|
||||
//
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ / \
|
||||
// 5 15 25 40
|
||||
// / / / \
|
||||
// 12 22 35 50
|
||||
// /
|
||||
// 31
|
||||
//
|
||||
// Call: remove(50)
|
||||
//
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ / \
|
||||
// 5 15 25 35
|
||||
// / / / \
|
||||
// 12 22 31 40
|
||||
//
|
||||
//
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(50);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(10)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(5)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(25)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(40)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(12)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(22)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(35)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(31)->tree_entry);
|
||||
int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50};
|
||||
result = result && pre_order_assert(&tree, val1, 12);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {20, 10, 5, 15, 12, 30, 25, 22, 35, 31, 40};
|
||||
result = result && pre_order_assert(&tree, val2, 11);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_double_rotation(void)
|
||||
{
|
||||
// Test case double rotation
|
||||
//
|
||||
// Create:
|
||||
//
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ / \
|
||||
// 5 15 25 40
|
||||
// / / / \
|
||||
// 12 22 35 50
|
||||
// /
|
||||
// 31
|
||||
//
|
||||
// Call: remove(22)
|
||||
//
|
||||
// 20
|
||||
// / \
|
||||
// 10 35
|
||||
// / \ / \
|
||||
// 5 15 30 40
|
||||
// / / \ \
|
||||
// 12 25 31 50
|
||||
//
|
||||
//
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(22);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(10)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(5)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(25)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(40)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(12)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(35)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(50)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(31)->tree_entry);
|
||||
int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50};
|
||||
result = result && pre_order_assert(&tree, val1, 12);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {20, 10, 5, 15, 12, 35, 30, 25, 31, 40, 50};
|
||||
result = result && pre_order_assert(&tree, val2, 11);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_complex_multiple_rotation(void)
|
||||
{
|
||||
// Test case multiple rotation
|
||||
//
|
||||
// Create:
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ / \
|
||||
// 5 15 25 40
|
||||
// / / / \
|
||||
// 12 22 35 50
|
||||
// /
|
||||
// 31
|
||||
//
|
||||
// Call: remove(5)
|
||||
//
|
||||
// Results:
|
||||
// 30
|
||||
// / \
|
||||
// 20 40
|
||||
// / \ / \
|
||||
// 12 25 35 50
|
||||
// / \ / /
|
||||
// 10 15 22 31
|
||||
//
|
||||
//
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *deleted = create_tree_node(5);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(10)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &deleted->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(25)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(40)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(12)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(22)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(35)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(50)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(31)->tree_entry);
|
||||
int val1[] = {20, 10, 5, 15, 12, 30, 25, 22, 40, 35, 31, 50};
|
||||
result = result && pre_order_assert(&tree, val1, 12);
|
||||
|
||||
lb_avl_tree_delete(&tree, &deleted->tree_entry);
|
||||
|
||||
int val2[] = {30, 20, 12, 10, 15, 25, 22, 40, 35, 31, 50};
|
||||
result = result && pre_order_assert(&tree, val2, 11);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
static bool delete_DNE(void)
|
||||
{
|
||||
// Test case DNE
|
||||
// Delete a node that does not exist
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ /
|
||||
// 5 15 25
|
||||
//
|
||||
// Call: remove(100), remove(24)
|
||||
//
|
||||
//
|
||||
// Results:
|
||||
// 20
|
||||
// / \
|
||||
// 10 30
|
||||
// / \ /
|
||||
// 5 15 25
|
||||
//
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
int_tree_node *delete100 = create_tree_node(100);
|
||||
int_tree_node *delete24 = create_tree_node(24);
|
||||
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(20)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(10)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(30)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(5)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(15)->tree_entry);
|
||||
lb_avl_tree_insert(&tree, &create_tree_node(25)->tree_entry);
|
||||
|
||||
int val1[] = {20, 10, 5, 15, 30, 25};
|
||||
result = result && pre_order_assert(&tree, val1, 6);
|
||||
|
||||
lb_avl_tree_delete(&tree, &delete24->tree_entry);
|
||||
lb_avl_tree_delete(&tree, &delete100->tree_entry);
|
||||
result = result && pre_order_assert(&tree, val1, 6);
|
||||
return result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
#define AVL_APOCALYPSE_NUM 500
|
||||
#define AVL_APOCALYPSE_ITER 2
|
||||
static int_tree_node apocalypse[AVL_APOCALYPSE_NUM];
|
||||
|
||||
static bool test_apocalypse(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct avl_tree tree;
|
||||
lb_avl_tree_init(&tree, compare);
|
||||
|
||||
// insert test
|
||||
for (int i = 0; i < AVL_APOCALYPSE_NUM; i++)
|
||||
{
|
||||
apocalypse[i].val = (int32)lb_rand();
|
||||
while (lb_avl_tree_search(&tree, &apocalypse[i].tree_entry) != NULL)
|
||||
{
|
||||
apocalypse[i].val += (int32)lb_rand() % 32765;
|
||||
}
|
||||
lb_avl_tree_insert(&tree, &apocalypse[i].tree_entry);
|
||||
}
|
||||
|
||||
// integrity test
|
||||
result = result && lb_avl_tree_validate(&tree);
|
||||
result = result && lb_avl_tree_size(&tree) == AVL_APOCALYPSE_NUM;
|
||||
|
||||
// smaller and bigger test
|
||||
struct avl_tree_node *entry = lb_avl_tree_smallest(&tree);
|
||||
uint32 size = 0;
|
||||
int32 prev = -1;
|
||||
int32 cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
while (entry != NULL)
|
||||
{
|
||||
if (cur < prev)
|
||||
{
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
size++;
|
||||
entry = lb_avl_tree_larger(entry);
|
||||
prev = cur;
|
||||
if (entry != NULL)
|
||||
{
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
}
|
||||
}
|
||||
|
||||
result = result && size == AVL_APOCALYPSE_NUM;
|
||||
|
||||
// larger test
|
||||
entry = lb_avl_tree_largest(&tree);
|
||||
size = 0;
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
prev = cur;
|
||||
while (entry != NULL)
|
||||
{
|
||||
if (cur > prev)
|
||||
{
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
size++;
|
||||
entry = lb_avl_tree_smaller(entry);
|
||||
prev = cur;
|
||||
if (entry != NULL)
|
||||
{
|
||||
cur = OBTAIN_STRUCT_ADDR(entry, int_tree_node, tree_entry)->val;
|
||||
}
|
||||
}
|
||||
|
||||
result = result && size == AVL_APOCALYPSE_NUM;
|
||||
|
||||
|
||||
// delete and search test
|
||||
for (int i = 0; i < AVL_APOCALYPSE_NUM; i++)
|
||||
{
|
||||
result = result && (lb_avl_tree_search(&tree, &apocalypse[i].tree_entry) != NULL);
|
||||
lb_avl_tree_delete(&tree, &apocalypse[i].tree_entry);
|
||||
result = result && (lb_avl_tree_search(&tree, &apocalypse[i].tree_entry) == NULL);
|
||||
result = result && lb_avl_tree_validate(&tree);
|
||||
}
|
||||
|
||||
result = result && (lb_avl_tree_size(&tree) == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void SXAPI avl_tree_test(void)
|
||||
{
|
||||
test_begin("AVL tree test");
|
||||
|
||||
// simple tests
|
||||
run_case("insert_simple_l", insert_simple_l());
|
||||
run_case("insert_simple_r", insert_simple_r());
|
||||
run_case("insert_simple_ll", insert_simple_ll());
|
||||
run_case("insert_simple_rr", insert_simple_rr());
|
||||
|
||||
// complex ones
|
||||
run_case("insert_complex_1", insert_complex_1());
|
||||
run_case("insert_complex_2", insert_complex_2());
|
||||
run_case("insert_complex_3", insert_complex_3());
|
||||
run_case("insert_complex_4", insert_complex_4());
|
||||
|
||||
// insert duplicate
|
||||
run_case("insert_duplicate", insert_duplicate());
|
||||
|
||||
// simple tests
|
||||
run_case("delete_simple_l", delete_simple_l());
|
||||
run_case("delete_simple_r", delete_simple_r());
|
||||
run_case("delete_simple_ll", delete_simple_ll());
|
||||
run_case("delete_simple_rr", delete_simple_rr());
|
||||
|
||||
// complex tests
|
||||
run_case("delete_complex_1", delete_complex_1());
|
||||
run_case("delete_complex_2", delete_complex_2());
|
||||
run_case("delete_complex_3", delete_complex_3());
|
||||
run_case("delete_complex_4", delete_complex_4());
|
||||
run_case("delete_complex_single_rotation", delete_complex_single_rotation());
|
||||
run_case("delete_complex_double_rotation", delete_complex_double_rotation());
|
||||
run_case("delete_complex_multiple_rotation", delete_complex_multiple_rotation());
|
||||
|
||||
// delete non-existing
|
||||
run_case("delete_DNE", delete_DNE());
|
||||
|
||||
lb_srand(2986);
|
||||
// ultimate apocalypse
|
||||
for (int i = 0; i < AVL_APOCALYPSE_ITER; i++)
|
||||
{
|
||||
run_case("test_apocalypse", test_apocalypse());
|
||||
}
|
||||
|
||||
test_end();
|
||||
}
|
||||
|
169
test/driver.c
169
test/driver.c
|
@ -1,169 +0,0 @@
|
|||
#include "driver.h"
|
||||
#include "test_case.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GAT_SIZE 256
|
||||
#define CASE_NUM 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *case_name;
|
||||
bool success;
|
||||
bool used;
|
||||
} case_info;
|
||||
|
||||
static case_info ginfo[CASE_NUM];
|
||||
static void *gat[GAT_SIZE];
|
||||
static char *test_name;
|
||||
|
||||
static void test_info(void)
|
||||
{
|
||||
printf("[TD-INFO][%s] - ", test_name);
|
||||
}
|
||||
|
||||
static void test_warning(void)
|
||||
{
|
||||
printf("[TD-WARN][%s] - ", test_name);
|
||||
}
|
||||
|
||||
static void test_error(void)
|
||||
{
|
||||
printf("[TD-ERR][%s] - ", test_name);
|
||||
}
|
||||
|
||||
static void gat_push(void *ptr)
|
||||
{
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
if (gat[i] == NULL)
|
||||
{
|
||||
gat[i] = ptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool gat_full(void)
|
||||
{
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
if (gat[i] == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void gat_free(void)
|
||||
{
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
if (gat[i] != NULL)
|
||||
{
|
||||
free(gat[i]);
|
||||
gat[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ginfo_push(char *case_name, bool success)
|
||||
{
|
||||
char *r_case_name = (case_name == NULL ? "Anonymous Case" : case_name);
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
if (!ginfo[i].used)
|
||||
{
|
||||
ginfo[i].case_name = r_case_name;
|
||||
ginfo[i].success = success;
|
||||
ginfo[i].used = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
test_warning();
|
||||
printf("GINFO full, [%s] result not recorded.\n", r_case_name);
|
||||
}
|
||||
|
||||
void SXAPI test_begin(char *name)
|
||||
{
|
||||
test_name = (name == NULL ? "Anonymous Test" : name);
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
gat[i] = NULL;
|
||||
}
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
ginfo[i].used = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI test_end(void)
|
||||
{
|
||||
gat_free();
|
||||
int32 total = 0, failed = 0, success = 0;
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
if (ginfo[i].used)
|
||||
{
|
||||
total++;
|
||||
if (ginfo[i].success)
|
||||
{
|
||||
success++;
|
||||
}
|
||||
else
|
||||
{
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
test_info();
|
||||
printf("%s\n", failed > 0 ? "FAIL" : "PASS");
|
||||
printf(" %d cases executed. S: %d. F: %d.\n", total, success, failed);
|
||||
if (failed > 0)
|
||||
{
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
if (ginfo[i].used && !ginfo[i].success)
|
||||
{
|
||||
printf(" %s FAILED\n", ginfo[i].case_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
ginfo[i].used = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void SXAPI *talloc(uint32 size)
|
||||
{
|
||||
if (!gat_full())
|
||||
{
|
||||
void *result = malloc(size);
|
||||
gat_push(result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
test_error();
|
||||
printf("GAT full, rejecting further allocations.\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SXAPI run_case(char *name, bool result)
|
||||
{
|
||||
ginfo_push(name, result);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
linked_list_test();
|
||||
salloc_test();
|
||||
avl_tree_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef TEST_TEST_H
|
||||
#define TEST_TEST_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void
|
||||
linked_list_test(void);
|
||||
|
||||
void
|
||||
avl_tree_test(void);
|
||||
|
||||
void
|
||||
salloc_test(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef TEST_DRIVER_H
|
||||
#define TEST_DRIVER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void
|
||||
test_begin(char *name);
|
||||
|
||||
void
|
||||
test_end(void);
|
||||
|
||||
void *
|
||||
talloc(uint32 size);
|
||||
|
||||
void
|
||||
run_case(char *name, bool result);
|
||||
|
||||
#endif
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef TEST_DRIVER_H
|
||||
#define TEST_DRIVER_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
void SXAPI test_begin(char *name);
|
||||
|
||||
void SXAPI test_end(void);
|
||||
|
||||
void *SXAPI talloc(uint32 size);
|
||||
|
||||
void SXAPI run_case(char *name, bool result);
|
||||
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef TEST_TEST_H
|
||||
#define TEST_TEST_H
|
||||
|
||||
#include "type.h"
|
||||
|
||||
void SXAPI linked_list_test(void);
|
||||
|
||||
void SXAPI avl_tree_test(void);
|
||||
|
||||
void SXAPI salloc_test(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,68 @@
|
|||
#include "common.h"
|
||||
#include "kernel/ke.h"
|
||||
#include "hal_export.h"
|
||||
|
||||
/**
|
||||
* Bogus implementation of HAL
|
||||
*/
|
||||
int32 KABI
|
||||
hal_atomic_xchg_32(int32 *target, int32 val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32 KABI
|
||||
hal_atomic_inc_32(int32 *target, int32 increment)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 KABI
|
||||
hal_atomic_cmpxchg_32(int32 *target, int32 compare, int32 val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 KABI
|
||||
hal_set_irql(uint32 irql)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 KABI
|
||||
hal_get_irql(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KABI
|
||||
hal_issue_intr(uint32 core, uint32 vector)
|
||||
{
|
||||
}
|
||||
|
||||
void KABI
|
||||
hal_reg_intr(uint32 index, intr_handler_fp handler)
|
||||
{
|
||||
}
|
||||
|
||||
void KABI
|
||||
hal_dereg_intr(uint32 index)
|
||||
{
|
||||
}
|
||||
|
||||
void KABI
|
||||
hal_reg_exc(uint32 exc, exc_handler_fp handler)
|
||||
{
|
||||
}
|
||||
|
||||
void KABI
|
||||
hal_dereg_exc(uint32 exc)
|
||||
{
|
||||
}
|
||||
|
||||
uint32 KABI
|
||||
hal_get_core_id(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -1,475 +0,0 @@
|
|||
#include "driver.h"
|
||||
#include "test_case.h"
|
||||
#include "lib/linked_list.h"
|
||||
#include "lib/sxtdlib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct linked_list_node lnode;
|
||||
int32 val;
|
||||
} my_list_node;
|
||||
|
||||
static int32 SXAPI equals(struct linked_list_node *node, void *obj)
|
||||
{
|
||||
return ((int32)(uintptr) obj) - OBTAIN_STRUCT_ADDR(node, my_list_node, lnode)->val;
|
||||
}
|
||||
|
||||
static bool validate_list(struct linked_list *list)
|
||||
{
|
||||
bool result = TRUE;
|
||||
// list_head_test
|
||||
if (list->head != NULL)
|
||||
{
|
||||
result = result && (list->head->prev == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result && (list->tail == NULL);
|
||||
}
|
||||
|
||||
if (list->tail != NULL)
|
||||
{
|
||||
result = result && (list->tail->next == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result && (list->head == NULL);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void print_list(struct linked_list *list)
|
||||
{
|
||||
#ifdef TDBG
|
||||
struct linked_list_node *node = lb_linked_list_first(list);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, my_list_node, lnode);
|
||||
printf("%d->",enode->val);
|
||||
node = lb_linked_list_next(node);
|
||||
}
|
||||
printf("[END]\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static bool assert_list(struct linked_list *list, int val[], int size)
|
||||
{
|
||||
struct linked_list_node *node = lb_linked_list_first(list);
|
||||
int i = 0;
|
||||
|
||||
if (!validate_list(list))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (node != NULL && i < size)
|
||||
{
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, my_list_node, lnode);
|
||||
if (enode->val != val[i])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
i++;
|
||||
node = lb_linked_list_next(node);
|
||||
}
|
||||
|
||||
if (i != size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
node = lb_linked_list_last(list);
|
||||
while (node != NULL && i >= 0)
|
||||
{
|
||||
my_list_node *enode = OBTAIN_STRUCT_ADDR(node, my_list_node, lnode);
|
||||
if (enode->val != val[i - 1])
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
i--;
|
||||
node = lb_linked_list_prev(node);
|
||||
}
|
||||
|
||||
return i == 0;
|
||||
}
|
||||
|
||||
static void insert_val(struct linked_list *list, int index, int val)
|
||||
{
|
||||
my_list_node *a = (my_list_node *) talloc(sizeof(my_list_node));
|
||||
a->val = val;
|
||||
lb_linked_list_insert_by_idx(list, index, &a->lnode);
|
||||
}
|
||||
|
||||
static void push_back_val(struct linked_list *list, int val)
|
||||
{
|
||||
my_list_node *a = (my_list_node *) talloc(sizeof(my_list_node));
|
||||
a->val = val;
|
||||
lb_linked_list_push_back(list, &a->lnode);
|
||||
}
|
||||
|
||||
static void push_front_val(struct linked_list *list, int val)
|
||||
{
|
||||
my_list_node *a = (my_list_node *) talloc(sizeof(my_list_node));
|
||||
a->val = val;
|
||||
lb_linked_list_push_front(list, &a->lnode);
|
||||
}
|
||||
|
||||
|
||||
static bool insert_test_beginning(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 3);
|
||||
print_list(&list);
|
||||
|
||||
// 3210==0123
|
||||
int val[4] = {3, 2, 1, 0};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool insert_test_middle(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
|
||||
insert_val(&list, 1, 4);
|
||||
insert_val(&list, 1, 5);
|
||||
insert_val(&list, 2, 6);
|
||||
|
||||
int val[] = {2, 5, 6, 4, 1, 0};
|
||||
return assert_list(&list, val, 6);
|
||||
}
|
||||
|
||||
static bool insert_test_end(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
print_list(&list);
|
||||
|
||||
int val[] = {0, 1, 2, 3};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool insert_test_invalid(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 3);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 0);
|
||||
|
||||
// large index
|
||||
insert_val(&list, 5, 9);
|
||||
insert_val(&list, 6, 9);
|
||||
insert_val(&list, 999, 9);
|
||||
|
||||
// small index
|
||||
insert_val(&list, -1, 8);
|
||||
insert_val(&list, -2, 8);
|
||||
insert_val(&list, -999, 8);
|
||||
|
||||
// NULL
|
||||
insert_val(NULL, 1, 4);
|
||||
lb_linked_list_insert_by_ref(NULL, list.head, list.tail);
|
||||
lb_linked_list_insert_by_ref(&list, list.head, NULL);
|
||||
|
||||
int val[] = {0, 1, 2, 3};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
|
||||
static bool remove_test_beginning(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 3);
|
||||
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
//print_list(&list);
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
//print_list(&list);
|
||||
|
||||
// 10==01
|
||||
int val[] = {1, 0};
|
||||
return assert_list(&list, val, 2);
|
||||
}
|
||||
|
||||
static bool remove_test_middle(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
|
||||
insert_val(&list, 0, 3);
|
||||
insert_val(&list, 0, 4);
|
||||
insert_val(&list, 0, 5);
|
||||
|
||||
print_list(&list);
|
||||
lb_linked_list_remove_by_idx(&list, 1);
|
||||
print_list(&list);
|
||||
lb_linked_list_remove_by_idx(&list, 2);
|
||||
print_list(&list);
|
||||
|
||||
// 5310=====0135
|
||||
int val[] = {5, 3, 1, 0};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool remove_test_end(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
print_list(&list);
|
||||
insert_val(&list, 1, 1);
|
||||
print_list(&list);
|
||||
insert_val(&list, 2, 2);
|
||||
print_list(&list);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
print_list(&list);
|
||||
lb_linked_list_remove_by_idx(&list, 3);
|
||||
print_list(&list);
|
||||
lb_linked_list_remove_by_idx(&list, 2);
|
||||
print_list(&list);
|
||||
|
||||
int val[] = {0, 1};
|
||||
return assert_list(&list, val, 2);
|
||||
}
|
||||
|
||||
static bool remove_test_all(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_linked_list_remove_by_idx(&list, 3);
|
||||
lb_linked_list_remove_by_idx(&list, 2);
|
||||
lb_linked_list_remove_by_idx(&list, 1);
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_linked_list_remove_by_idx(&list, 1);
|
||||
lb_linked_list_remove_by_idx(&list, 1);
|
||||
lb_linked_list_remove_by_idx(&list, 1);
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool remove_test_invalid(void)
|
||||
{
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
insert_val(&list, 0, 3);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 0);
|
||||
|
||||
// large index
|
||||
lb_linked_list_remove_by_idx(&list, 5);
|
||||
lb_linked_list_remove_by_idx(&list, 6);
|
||||
lb_linked_list_remove_by_idx(&list, 999);
|
||||
|
||||
// small index
|
||||
lb_linked_list_remove_by_idx(&list, -1);
|
||||
lb_linked_list_remove_by_idx(&list, -2);
|
||||
lb_linked_list_remove_by_idx(&list, -999);
|
||||
|
||||
// NULL
|
||||
lb_linked_list_remove_by_idx(NULL, 1);
|
||||
lb_linked_list_remove_by_ref(NULL, list.head);
|
||||
lb_linked_list_remove_by_ref(&list, NULL);
|
||||
|
||||
// 0123=====3210
|
||||
int val[] = {0, 1, 2, 3};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool size_test(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
struct linked_list list2;
|
||||
lb_linked_list_init(&list2);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
result = result && (lb_linked_list_size(&list) == 4 && lb_linked_list_size(&list2) == 0 &&
|
||||
lb_linked_list_size(NULL) == -1);
|
||||
|
||||
lb_linked_list_remove_by_idx(&list, 0);
|
||||
result = result && (lb_linked_list_size(&list) == 3);
|
||||
insert_val(&list, 0, 0);
|
||||
|
||||
int val[] = {0, 1, 2, 3};
|
||||
result = result && assert_list(&list, val, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool push_pop_front_test(void)
|
||||
{
|
||||
struct linked_list_node *node;
|
||||
bool result = TRUE;
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
push_front_val(&list, 1);
|
||||
push_front_val(&list, 2);
|
||||
push_front_val(&list, 3);
|
||||
push_front_val(&list, 4);
|
||||
|
||||
//4321==1234
|
||||
int val1[] = {4, 3, 2, 1};
|
||||
result = result && assert_list(&list, val1, 4);
|
||||
|
||||
node = lb_linked_list_pop_front(&list);
|
||||
//321==123
|
||||
int val2[] = {3, 2, 1};
|
||||
result = result && assert_list(&list, val2, 3) && OBTAIN_STRUCT_ADDR(node, my_list_node, lnode)->val == 4;
|
||||
|
||||
lb_linked_list_pop_front(&list);
|
||||
lb_linked_list_pop_front(&list);
|
||||
node = lb_linked_list_pop_front(&list);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0) && OBTAIN_STRUCT_ADDR(node, my_list_node, lnode)->val == 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool push_pop_back_test(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
struct linked_list_node *node;
|
||||
|
||||
push_back_val(&list, 1);
|
||||
push_back_val(&list, 2);
|
||||
push_back_val(&list, 3);
|
||||
push_back_val(&list, 4);
|
||||
|
||||
//1234==4321
|
||||
int val1[] = {1, 2, 3, 4};
|
||||
result = result && assert_list(&list, val1, 4);
|
||||
|
||||
node = lb_linked_list_pop_back(&list);
|
||||
//123==321
|
||||
int val2[] = {1, 2, 3};
|
||||
result = result && assert_list(&list, val2, 3) && OBTAIN_STRUCT_ADDR(node, my_list_node, lnode)->val == 4;
|
||||
|
||||
lb_linked_list_pop_back(&list);
|
||||
node = lb_linked_list_pop_back(&list);
|
||||
lb_linked_list_pop_back(&list);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0) && OBTAIN_STRUCT_ADDR(node, my_list_node, lnode)->val == 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool search_test(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct linked_list list;
|
||||
lb_linked_list_init(&list);
|
||||
|
||||
push_back_val(&list, 1);
|
||||
push_back_val(&list, 2);
|
||||
push_back_val(&list, 3);
|
||||
push_back_val(&list, 4);
|
||||
|
||||
int val1[] = {1, 2, 3, 4};
|
||||
result = result && assert_list(&list, val1, 4);
|
||||
|
||||
result = result && (lb_linked_list_search(&list, (void *) 4, equals) != NULL);
|
||||
result = result && (lb_linked_list_search(&list, (void *) 3, equals) != NULL);
|
||||
result = result && (lb_linked_list_search(&list, (void *) 2, equals) != NULL);
|
||||
result = result && (lb_linked_list_search(&list, (void *) 1, equals) != NULL);
|
||||
|
||||
result = result && (lb_linked_list_search(&list, NULL, equals) == NULL);
|
||||
result = result && (lb_linked_list_search(NULL, (void *) 1, equals) == NULL);
|
||||
|
||||
result = result && assert_list(&list, val1, 4);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void SXAPI linked_list_test(void)
|
||||
{
|
||||
test_begin("Linked list test");
|
||||
run_case("insert_test_beginning", insert_test_beginning());
|
||||
run_case("insert_test_middle", insert_test_middle());
|
||||
run_case("insert_test_end", insert_test_end());
|
||||
run_case("insert_test_invalid", insert_test_invalid());
|
||||
|
||||
run_case("remove_test_beginning", remove_test_beginning());
|
||||
run_case("remove_test_middle", remove_test_middle());
|
||||
run_case("remove_test_end", remove_test_end());
|
||||
run_case("remove_test_invalid", remove_test_invalid());
|
||||
|
||||
run_case("size_test", size_test());
|
||||
|
||||
run_case("remove_test_all", remove_test_all());
|
||||
|
||||
run_case("push_pop_front_test", push_pop_front_test());
|
||||
run_case("push_pop_back_test", push_pop_back_test());
|
||||
|
||||
run_case("search_test", search_test());
|
||||
test_end();
|
||||
}
|
||||
|
|
@ -0,0 +1,496 @@
|
|||
#include "test_main.h"
|
||||
#include "test_case.h"
|
||||
#include "lb.h"
|
||||
#include <stdio.h>
|
||||
|
||||
struct test_list_node
|
||||
{
|
||||
struct llist_node lnode;
|
||||
int32 val;
|
||||
};
|
||||
|
||||
static bool
|
||||
validate_list(struct llist *list)
|
||||
{
|
||||
bool result = TRUE;
|
||||
// list_head_test
|
||||
if (list->head != NULL)
|
||||
{
|
||||
result = result && (list->head->prev == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result && (list->tail == NULL);
|
||||
}
|
||||
|
||||
if (list->tail != NULL)
|
||||
{
|
||||
result = result && (list->tail->next == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result && (list->head == NULL);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
print_list(struct llist *list)
|
||||
{
|
||||
#ifdef TDBG
|
||||
struct llist_node *node = lb_llist_first(list);
|
||||
|
||||
while (node != NULL)
|
||||
{
|
||||
struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode);
|
||||
printf("%d->", enode->val);
|
||||
node = lb_llist_next(node);
|
||||
}
|
||||
printf("[END]\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
check_list_elements(struct llist *list, int val[], int size)
|
||||
{
|
||||
struct llist_node *node = list->head;
|
||||
bool ret = TRUE;
|
||||
int i = 0;
|
||||
while (node != NULL && i < size)
|
||||
{
|
||||
struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode);
|
||||
if (enode->val != val[i])
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
node = lb_llist_next(node);
|
||||
}
|
||||
|
||||
if(ret)
|
||||
{
|
||||
if (i != size)
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret)
|
||||
{
|
||||
node = lb_llist_last(list);
|
||||
while (node != NULL && i >= 0)
|
||||
{
|
||||
struct test_list_node *enode = OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode);
|
||||
if (enode->val != val[i - 1])
|
||||
{
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
node = lb_llist_prev(node);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret)
|
||||
{
|
||||
ret = ret && (i == 0);
|
||||
}
|
||||
|
||||
#ifdef TDBG
|
||||
if (!ret)
|
||||
{
|
||||
printf("[LLIST ASSERT] Expected: ");
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
printf("%d-", val[i]);
|
||||
}
|
||||
printf("\n Got:");
|
||||
print_list(list);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
assert_list(struct llist *list, int val[], int size)
|
||||
{
|
||||
struct llist_node *node = lb_llist_first(list);
|
||||
int i = 0;
|
||||
|
||||
if (!validate_list(list))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return check_list_elements(list, val, size);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_val(struct llist *list, int index, int val)
|
||||
{
|
||||
struct test_list_node *a = (struct test_list_node *) talloc(sizeof(struct test_list_node));
|
||||
a->val = val;
|
||||
lb_llist_insert_by_idx(list, index, &a->lnode);
|
||||
}
|
||||
|
||||
static void
|
||||
push_back_val(struct llist *list, int val)
|
||||
{
|
||||
struct test_list_node *a = (struct test_list_node *) talloc(sizeof(struct test_list_node));
|
||||
a->val = val;
|
||||
lb_llist_push_back(list, &a->lnode);
|
||||
}
|
||||
|
||||
static void
|
||||
push_front_val(struct llist *list, int val)
|
||||
{
|
||||
struct test_list_node *a = (struct test_list_node *) talloc(sizeof(struct test_list_node));
|
||||
a->val = val;
|
||||
lb_llist_push_front(list, &a->lnode);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
insert_test_beginning(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 3);
|
||||
|
||||
// 3210==0123
|
||||
int val[4] = {3, 2, 1, 0};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool
|
||||
insert_test_middle(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
|
||||
insert_val(&list, 1, 4);
|
||||
insert_val(&list, 1, 5);
|
||||
insert_val(&list, 2, 6);
|
||||
|
||||
int val[] = {2, 5, 6, 4, 1, 0};
|
||||
return assert_list(&list, val, 6);
|
||||
}
|
||||
|
||||
static bool
|
||||
insert_test_end(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
int val[] = {0, 1, 2, 3};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool
|
||||
insert_test_invalid(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 3);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 0);
|
||||
|
||||
// large index
|
||||
insert_val(&list, 5, 9);
|
||||
insert_val(&list, 6, 9);
|
||||
insert_val(&list, 999, 9);
|
||||
|
||||
// small index
|
||||
insert_val(&list, -1, 8);
|
||||
insert_val(&list, -2, 8);
|
||||
insert_val(&list, -999, 8);
|
||||
|
||||
/**
|
||||
* Since it's kernel library
|
||||
* Don't test NULL
|
||||
*/
|
||||
/*
|
||||
insert_val(NULL, 1, 4);
|
||||
lb_llist_insert_by_ref(NULL, list.head, list.tail);
|
||||
lb_llist_insert_by_ref(&list, list.head, NULL);
|
||||
*/
|
||||
|
||||
int val[] = {0, 1, 2, 3};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
remove_test_beginning(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 3);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
|
||||
// 10==01
|
||||
int val[] = {1, 0};
|
||||
return assert_list(&list, val, 2);
|
||||
}
|
||||
|
||||
static bool
|
||||
remove_test_middle(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 2);
|
||||
|
||||
insert_val(&list, 0, 3);
|
||||
insert_val(&list, 0, 4);
|
||||
insert_val(&list, 0, 5);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 1);
|
||||
lb_llist_remove_by_idx(&list, 2);
|
||||
|
||||
// 5310=====0135
|
||||
int val[] = {5, 3, 1, 0};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool
|
||||
remove_test_end(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 3);
|
||||
lb_llist_remove_by_idx(&list, 2);
|
||||
|
||||
int val[] = {0, 1};
|
||||
return assert_list(&list, val, 2);
|
||||
}
|
||||
|
||||
static bool
|
||||
remove_test_all(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 3);
|
||||
lb_llist_remove_by_idx(&list, 2);
|
||||
lb_llist_remove_by_idx(&list, 1);
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 1);
|
||||
lb_llist_remove_by_idx(&list, 1);
|
||||
lb_llist_remove_by_idx(&list, 1);
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
remove_test_invalid(void)
|
||||
{
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
insert_val(&list, 0, 3);
|
||||
insert_val(&list, 0, 2);
|
||||
insert_val(&list, 0, 1);
|
||||
insert_val(&list, 0, 0);
|
||||
|
||||
// large index
|
||||
lb_llist_remove_by_idx(&list, 5);
|
||||
lb_llist_remove_by_idx(&list, 6);
|
||||
lb_llist_remove_by_idx(&list, 999);
|
||||
|
||||
// small index
|
||||
lb_llist_remove_by_idx(&list, -1);
|
||||
lb_llist_remove_by_idx(&list, -2);
|
||||
lb_llist_remove_by_idx(&list, -999);
|
||||
|
||||
/**
|
||||
* Since it's kernel library
|
||||
* Don't test NULL
|
||||
*/
|
||||
/*
|
||||
lb_llist_remove_by_idx(NULL, 1);
|
||||
lb_llist_remove_by_ref(NULL, list.head);
|
||||
lb_llist_remove_by_ref(&list, NULL); */
|
||||
|
||||
// 0123=====3210
|
||||
int val[] = {0, 1, 2, 3};
|
||||
return assert_list(&list, val, 4);
|
||||
}
|
||||
|
||||
static bool
|
||||
size_test(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
struct llist list2;
|
||||
lb_llist_init(&list2);
|
||||
|
||||
insert_val(&list, 0, 0);
|
||||
insert_val(&list, 1, 1);
|
||||
insert_val(&list, 2, 2);
|
||||
insert_val(&list, 3, 3);
|
||||
|
||||
/**
|
||||
* Since it's kernel library
|
||||
* Don't test NULL
|
||||
*/
|
||||
/*
|
||||
* lb_llist_size(NULL) == -1
|
||||
*/
|
||||
result = result && (lb_llist_size(&list) == 4 && lb_llist_size(&list2) == 0);
|
||||
|
||||
lb_llist_remove_by_idx(&list, 0);
|
||||
result = result && (lb_llist_size(&list) == 3);
|
||||
insert_val(&list, 0, 0);
|
||||
|
||||
int val[] = {0, 1, 2, 3};
|
||||
result = result && assert_list(&list, val, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
push_pop_front_test(void)
|
||||
{
|
||||
struct llist_node *node;
|
||||
bool result = TRUE;
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
|
||||
push_front_val(&list, 1);
|
||||
push_front_val(&list, 2);
|
||||
push_front_val(&list, 3);
|
||||
push_front_val(&list, 4);
|
||||
|
||||
//4321==1234
|
||||
int val1[] = {4, 3, 2, 1};
|
||||
result = result && assert_list(&list, val1, 4);
|
||||
|
||||
node = lb_llist_pop_front(&list);
|
||||
//321==123
|
||||
int val2[] = {3, 2, 1};
|
||||
result = result && assert_list(&list, val2, 3) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 4;
|
||||
|
||||
lb_llist_pop_front(&list);
|
||||
lb_llist_pop_front(&list);
|
||||
node = lb_llist_pop_front(&list);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
push_pop_back_test(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
struct llist list;
|
||||
lb_llist_init(&list);
|
||||
struct llist_node *node;
|
||||
|
||||
push_back_val(&list, 1);
|
||||
push_back_val(&list, 2);
|
||||
push_back_val(&list, 3);
|
||||
push_back_val(&list, 4);
|
||||
|
||||
//1234==4321
|
||||
int val1[] = {1, 2, 3, 4};
|
||||
result = result && assert_list(&list, val1, 4);
|
||||
|
||||
node = lb_llist_pop_back(&list);
|
||||
//123==321
|
||||
int val2[] = {1, 2, 3};
|
||||
result = result && assert_list(&list, val2, 3) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 4;
|
||||
|
||||
lb_llist_pop_back(&list);
|
||||
node = lb_llist_pop_back(&list);
|
||||
lb_llist_pop_back(&list);
|
||||
|
||||
result = result && assert_list(&list, NULL, 0) && OBTAIN_STRUCT_ADDR(node, struct test_list_node, lnode)->val == 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
linked_list_test(void)
|
||||
{
|
||||
test_begin("Linked list test");
|
||||
run_case("insert_test_beginning", insert_test_beginning());
|
||||
run_case("insert_test_middle", insert_test_middle());
|
||||
run_case("insert_test_end", insert_test_end());
|
||||
run_case("insert_test_invalid", insert_test_invalid());
|
||||
|
||||
run_case("remove_test_beginning", remove_test_beginning());
|
||||
run_case("remove_test_middle", remove_test_middle());
|
||||
run_case("remove_test_end", remove_test_end());
|
||||
run_case("remove_test_invalid", remove_test_invalid());
|
||||
|
||||
run_case("size_test", size_test());
|
||||
|
||||
run_case("remove_test_all", remove_test_all());
|
||||
|
||||
run_case("push_pop_front_test", push_pop_front_test());
|
||||
run_case("push_pop_back_test", push_pop_back_test());
|
||||
|
||||
test_end();
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
#include "driver.h"
|
||||
#include "lib/salloc.h"
|
||||
#include "test_main.h"
|
||||
#include "lb.h"
|
||||
#include "test_case.h"
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32 size;
|
||||
uint32 flags;
|
||||
uint32 size;
|
||||
uint32 flags;
|
||||
} salloc_header;
|
||||
|
||||
static const uint32 salloc_header_size = sizeof(salloc_header);
|
||||
|
@ -14,269 +14,269 @@ static char buffer[1024];
|
|||
|
||||
static bool salloc_init_test(void)
|
||||
{
|
||||
lb_salloc_init(buffer, 1024);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
return lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
lb_salloc_init(buffer, 1024);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
return lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
}
|
||||
|
||||
static bool salloc_basic_alloc(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
uint32 blk_size[] = {10 + salloc_header_size, 1024 - 10 - salloc_header_size};
|
||||
bool blk_free[] = {FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 2);
|
||||
return result;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
uint32 blk_size[] = {10 + salloc_header_size, 1024 - 10 - salloc_header_size};
|
||||
bool blk_free[] = {FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_full_alloc(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 1024 - salloc_header_size) != NULL);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {FALSE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 1024 - salloc_header_size) != NULL);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {FALSE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_overflow_alloc(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 1024 - salloc_header_size + 1) == NULL);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 1024 - salloc_header_size + 1) == NULL);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_multiple_alloc(void)
|
||||
{
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 3 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, FALSE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
result = result && (lb_salloc(buffer, 10) != NULL);
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 3 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, FALSE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_alloc_not_enough(void)
|
||||
{
|
||||
void *ptr;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, salloc_header_size + salloc_header_size + salloc_header_size - 1);
|
||||
ptr = lb_salloc(buffer, salloc_header_size);
|
||||
result = result && (ptr != NULL);
|
||||
uint32 blk_size[] = {salloc_header_size + salloc_header_size + salloc_header_size - 1};
|
||||
bool blk_free[] = {FALSE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
void *ptr;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, salloc_header_size + salloc_header_size + salloc_header_size - 1);
|
||||
ptr = lb_salloc(buffer, salloc_header_size);
|
||||
result = result && (ptr != NULL);
|
||||
uint32 blk_size[] = {salloc_header_size + salloc_header_size + salloc_header_size - 1};
|
||||
bool blk_free[] = {FALSE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool salloc_basic_free(void)
|
||||
{
|
||||
void *ptr;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr = lb_salloc(buffer, 10);
|
||||
result = result && (ptr != NULL);
|
||||
void *ptr;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr = lb_salloc(buffer, 10);
|
||||
result = result && (ptr != NULL);
|
||||
|
||||
lb_sfree(buffer, ptr);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
lb_sfree(buffer, ptr);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_full_free(void)
|
||||
{
|
||||
void *ptr;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr = lb_salloc(buffer, 1024 - salloc_header_size);
|
||||
result = result && (ptr != NULL);
|
||||
void *ptr;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr = lb_salloc(buffer, 1024 - salloc_header_size);
|
||||
result = result && (ptr != NULL);
|
||||
|
||||
lb_sfree(buffer, ptr);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
lb_sfree(buffer, ptr);
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_multiple_free(void)
|
||||
{
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr1);
|
||||
lb_sfree(buffer, ptr3);
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr1);
|
||||
lb_sfree(buffer, ptr3);
|
||||
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 4 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {TRUE, FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 5);
|
||||
return result;
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 4 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {TRUE, FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 5);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_free_join_tail(void)
|
||||
{
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr4);
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr4);
|
||||
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 3 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, FALSE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 3 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, FALSE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_free_join_head(void)
|
||||
{
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr1);
|
||||
lb_sfree(buffer, ptr2);
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr1);
|
||||
lb_sfree(buffer, ptr2);
|
||||
|
||||
uint32 blk_size[] = {2 * (10 + salloc_header_size),
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 4 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {TRUE, FALSE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
uint32 blk_size[] = {2 * (10 + salloc_header_size),
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 4 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {TRUE, FALSE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_free_join_mid(void)
|
||||
{
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr2);
|
||||
lb_sfree(buffer, ptr3);
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr2);
|
||||
lb_sfree(buffer, ptr3);
|
||||
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
2 * (10 + salloc_header_size),
|
||||
10 + salloc_header_size,
|
||||
1024 - 4 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
2 * (10 + salloc_header_size),
|
||||
10 + salloc_header_size,
|
||||
1024 - 4 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_free_join_consecutive(void)
|
||||
{
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
ptr5 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL) && (ptr5 != NULL);
|
||||
lb_sfree(buffer, ptr2);
|
||||
lb_sfree(buffer, ptr4);
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4, *ptr5;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
ptr5 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL) && (ptr5 != NULL);
|
||||
lb_sfree(buffer, ptr2);
|
||||
lb_sfree(buffer, ptr4);
|
||||
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 5 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 6);
|
||||
uint32 blk_size[] = {10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
10 + salloc_header_size,
|
||||
1024 - 5 * (10 + salloc_header_size)};
|
||||
bool blk_free[] = {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 6);
|
||||
|
||||
lb_sfree(buffer, ptr3);
|
||||
lb_sfree(buffer, ptr3);
|
||||
|
||||
uint32 blk_size2[] = {10 + salloc_header_size,
|
||||
3 * (10 + salloc_header_size),
|
||||
10 + salloc_header_size,
|
||||
1024 - 5 * (10 + salloc_header_size)};
|
||||
bool blk_free2[] = {FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size2, blk_free2, 4);
|
||||
return result;
|
||||
uint32 blk_size2[] = {10 + salloc_header_size,
|
||||
3 * (10 + salloc_header_size),
|
||||
10 + salloc_header_size,
|
||||
1024 - 5 * (10 + salloc_header_size)};
|
||||
bool blk_free2[] = {FALSE, TRUE, FALSE, TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size2, blk_free2, 4);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool salloc_free_all(void)
|
||||
{
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr1);
|
||||
lb_sfree(buffer, ptr2);
|
||||
lb_sfree(buffer, ptr3);
|
||||
lb_sfree(buffer, ptr4);
|
||||
void *ptr1, *ptr2, *ptr3, *ptr4;
|
||||
bool result = TRUE;
|
||||
lb_salloc_init(buffer, 1024);
|
||||
ptr1 = lb_salloc(buffer, 10);
|
||||
ptr2 = lb_salloc(buffer, 10);
|
||||
ptr3 = lb_salloc(buffer, 10);
|
||||
ptr4 = lb_salloc(buffer, 10);
|
||||
result = result && (ptr1 != NULL) && (ptr2 != NULL) && (ptr3 != NULL) && (ptr4 != NULL);
|
||||
lb_sfree(buffer, ptr1);
|
||||
lb_sfree(buffer, ptr2);
|
||||
lb_sfree(buffer, ptr3);
|
||||
lb_sfree(buffer, ptr4);
|
||||
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
uint32 blk_size[] = {1024};
|
||||
bool blk_free[] = {TRUE};
|
||||
result = result && lb_salloc_assert(buffer, blk_size, blk_free, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void SXAPI salloc_test(void)
|
||||
void salloc_test(void)
|
||||
{
|
||||
test_begin("salloc test");
|
||||
test_begin("salloc test");
|
||||
|
||||
run_case("salloc_init_test", salloc_init_test());
|
||||
run_case("salloc_init_test", salloc_init_test());
|
||||
|
||||
run_case("salloc_basic_alloc", salloc_basic_alloc());
|
||||
run_case("salloc_full_alloc", salloc_full_alloc());
|
||||
run_case("salloc_overflow_alloc", salloc_overflow_alloc());
|
||||
run_case("salloc_multiple_alloc", salloc_multiple_alloc());
|
||||
run_case("salloc_alloc_not_enough", salloc_alloc_not_enough());
|
||||
run_case("salloc_basic_alloc", salloc_basic_alloc());
|
||||
run_case("salloc_full_alloc", salloc_full_alloc());
|
||||
run_case("salloc_overflow_alloc", salloc_overflow_alloc());
|
||||
run_case("salloc_multiple_alloc", salloc_multiple_alloc());
|
||||
run_case("salloc_alloc_not_enough", salloc_alloc_not_enough());
|
||||
|
||||
run_case("salloc_basic_free", salloc_basic_free());
|
||||
run_case("salloc_full_free", salloc_full_free());
|
||||
run_case("salloc_multiple_free", salloc_multiple_free());
|
||||
run_case("salloc_free_join_tail", salloc_free_join_tail());
|
||||
run_case("salloc_free_join_head", salloc_free_join_head());
|
||||
run_case("salloc_free_join_mid", salloc_free_join_mid());
|
||||
run_case("salloc_free_join_consecutive", salloc_free_join_consecutive());
|
||||
run_case("salloc_free_all", salloc_free_all());
|
||||
run_case("salloc_basic_free", salloc_basic_free());
|
||||
run_case("salloc_full_free", salloc_full_free());
|
||||
run_case("salloc_multiple_free", salloc_multiple_free());
|
||||
run_case("salloc_free_join_tail", salloc_free_join_tail());
|
||||
run_case("salloc_free_join_head", salloc_free_join_head());
|
||||
run_case("salloc_free_join_mid", salloc_free_join_mid());
|
||||
run_case("salloc_free_join_consecutive", salloc_free_join_consecutive());
|
||||
run_case("salloc_free_all", salloc_free_all());
|
||||
|
||||
test_end();
|
||||
test_end();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
#include "test_main.h"
|
||||
#include "test_case.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define GAT_SIZE 256
|
||||
#define CASE_NUM 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *case_name;
|
||||
bool success;
|
||||
bool used;
|
||||
} case_info;
|
||||
|
||||
static case_info ginfo[CASE_NUM];
|
||||
static void *gat[GAT_SIZE];
|
||||
static char *test_name;
|
||||
|
||||
static void test_info(void)
|
||||
{
|
||||
printf("[TD-INFO][%s] - ", test_name);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void test_warning(void)
|
||||
{
|
||||
printf("[TD-WARN][%s] - ", test_name);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void test_error(void)
|
||||
{
|
||||
printf("[TD-ERR][%s] - ", test_name);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void gat_push(void *ptr)
|
||||
{
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
if (gat[i] == NULL)
|
||||
{
|
||||
gat[i] = ptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool gat_full(void)
|
||||
{
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
if (gat[i] == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void gat_free(void)
|
||||
{
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
if (gat[i] != NULL)
|
||||
{
|
||||
free(gat[i]);
|
||||
gat[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ginfo_push(char *case_name, bool success)
|
||||
{
|
||||
char *r_case_name = (case_name == NULL ? "Anonymous Case" : case_name);
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
if (!ginfo[i].used)
|
||||
{
|
||||
ginfo[i].case_name = r_case_name;
|
||||
ginfo[i].success = success;
|
||||
ginfo[i].used = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
test_warning();
|
||||
printf("GINFO full, [%s] result not recorded.\n", r_case_name);
|
||||
}
|
||||
|
||||
void test_begin(char *name)
|
||||
{
|
||||
test_name = (name == NULL ? "Anonymous Test" : name);
|
||||
for (int i = 0; i < GAT_SIZE; i++)
|
||||
{
|
||||
gat[i] = NULL;
|
||||
}
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
ginfo[i].used = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void test_end(void)
|
||||
{
|
||||
gat_free();
|
||||
int32 total = 0, failed = 0, success = 0;
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
if (ginfo[i].used)
|
||||
{
|
||||
total++;
|
||||
if (ginfo[i].success)
|
||||
{
|
||||
success++;
|
||||
}
|
||||
else
|
||||
{
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
test_info();
|
||||
printf("%s\n", failed > 0 ? "FAIL" : "PASS");
|
||||
printf(" %d cases executed. S: %d. F: %d.\n", total, success, failed);
|
||||
if (failed > 0)
|
||||
{
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
if (ginfo[i].used && !ginfo[i].success)
|
||||
{
|
||||
printf(" %s FAILED\n", ginfo[i].case_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < CASE_NUM; i++)
|
||||
{
|
||||
ginfo[i].used = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void *talloc(uint32 size)
|
||||
{
|
||||
if (!gat_full())
|
||||
{
|
||||
void *result = malloc(size);
|
||||
gat_push(result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
test_error();
|
||||
printf("GAT full, rejecting further allocations.\n");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void run_case(char *name, bool result)
|
||||
{
|
||||
ginfo_push(name, result);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
linked_list_test();
|
||||
salloc_test();
|
||||
avl_tree_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue