From 9e96b66a089e40cfcc89fc53bbb77b8d32734f97 Mon Sep 17 00:00:00 2001 From: secXsQuared Date: Mon, 16 May 2016 00:34:41 -0700 Subject: [PATCH] Proc control block Primitive code for the allocation library --- Test/bit_operation.h | 26 +++++ Test/main.c | 203 ++++++++++++++++++++++++++++++++++++ x64/src/c/common/sys/kdef.h | 1 + x64/src/c/hal/mem.c | 9 +- x64/src/c/kernel/proc.c | 1 + x64/src/c/kernel/proc.h | 28 +++++ 6 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 Test/bit_operation.h create mode 100644 Test/main.c create mode 100644 x64/src/c/kernel/proc.c create mode 100644 x64/src/c/kernel/proc.h diff --git a/Test/bit_operation.h b/Test/bit_operation.h new file mode 100644 index 0000000..0802a6c --- /dev/null +++ b/Test/bit_operation.h @@ -0,0 +1,26 @@ +#ifndef _BIT_OPERATION_H_ +#define _BIT_OPERATION_H_ + +#include + +static inline uint64_t bit_mask_64(uint32_t bit) +{ + return (uint64_t)1 << bit; +} + +static inline uint32_t bit_mask_32(uint32_t bit) +{ + return (uint32_t)1 << bit; +} + +static inline uint64_t bit_field_mask_64(uint32_t low, uint32_t high) +{ + return ~(~(uint64_t)0 << high << 1) << low; +} + +static inline uint32_t bit_field_mask_32(uint32_t low, uint32_t high) +{ + return ~(~(uint32_t)0 << high << 1) << low; +} + +#endif diff --git a/Test/main.c b/Test/main.c new file mode 100644 index 0000000..6a96696 --- /dev/null +++ b/Test/main.c @@ -0,0 +1,203 @@ + +#include +#include +#include "bit_operation.h" + +typedef union { + uint32_t size; + uint32_t flags; +} alloc_header; + +#define ALLOC_FLAG_NUM 2 +#define ALLOC_HEADER_FLAG_FREE 0 +#define ALLOC_HEADER_FLAG_LAST 1 + + +void set_alloc_header_size(alloc_header* header, uint32_t size) +{ + // align the integer, ignoring overflowed bits + size <<= ALLOC_FLAG_NUM; + + // clear ALLOC_FLAG_NUM-th to 31-th bits + header->size &= ~bit_field_mask_32(ALLOC_FLAG_NUM, 31); + // set bits + header->size |= size; + return; +} + +uint32_t read_alloc_header_size(alloc_header* header) +{ + return header->size >> ALLOC_FLAG_NUM; +} + +uint32_t read_alloc_header_flag(alloc_header* header, uint32_t bit) +{ + return (header->flags & bit_mask_32(bit)) == 0 ? 0 : 1; +} + +void set_alloc_header_flag(alloc_header* header, uint32_t bit, uint32_t value) +{ + value &= bit_mask_32(1); + if(value == 1) + { + header->flags |= bit_mask_32(bit); + } + else + { + header->flags &= ~bit_mask_32(bit); + } + return; +} + +int init_alloc(void* base, unsigned int size) +{ + if(base != NULL && size >= sizeof(unsigned int)) + { + alloc_header* ptr = (alloc_header*)base; + set_alloc_header_size(ptr, size); + set_alloc_header_flag(ptr, ALLOC_HEADER_FLAG_FREE, 1); + set_alloc_header_flag(ptr, ALLOC_HEADER_FLAG_LAST, 1); + return 0; + } + return 1; +} + +void alloc_join_free(void *base) +{ + if(base != NULL) + { + char* c_ptr = (char*)base; + while(1) + { + uint32_t c_blk_free = read_alloc_header_flag((alloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE); + uint32_t c_blk_last = read_alloc_header_flag((alloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST); + uint32_t c_blk_size = read_alloc_header_size((alloc_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_t n_blk_free = read_alloc_header_flag((alloc_header *) n_ptr, ALLOC_HEADER_FLAG_FREE); + uint32_t n_blk_last = read_alloc_header_flag((alloc_header *) n_ptr, ALLOC_HEADER_FLAG_LAST); + uint32_t n_blk_size = read_alloc_header_size((alloc_header*)n_ptr); + + if (n_blk_free == 1) + { + // logically gone + set_alloc_header_size((alloc_header *) c_ptr, n_blk_size + c_blk_size); + set_alloc_header_flag((alloc_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; + } + } + } +} + +int kfree(void* base, void* ptr) +{ + if(base != NULL && ptr != NULL) + { + char* c_ptr = (char*)base; + while(1) + { + uint32_t cur_blk_free = read_alloc_header_flag((alloc_header *) c_ptr, ALLOC_HEADER_FLAG_FREE); + uint32_t cur_blk_last = read_alloc_header_flag((alloc_header *) c_ptr, ALLOC_HEADER_FLAG_LAST); + uint32_t cur_blk_size = read_alloc_header_size((alloc_header*)c_ptr); + if (cur_blk_free == 0 && ptr == c_ptr + sizeof(alloc_header)) + { + // we found the block, mark it as free + set_alloc_header_flag((alloc_header*)c_ptr, ALLOC_HEADER_FLAG_FREE, 1); + // merge blocks + alloc_join_free(base); + return 0; + } + + if(cur_blk_last == 1) + { + break; + } + else + { + c_ptr += cur_blk_size; + } + } + } + return 1; +} + +int kalloc(void* base, unsigned int size, void** ptr) +{ + if(base != NULL && size != 0 && ptr != NULL) + { + unsigned int total_size = size + sizeof(alloc_header); + char* c_ptr = (char*)base; + while(1) + { + uint32_t cur_blk_free = read_alloc_header_flag((alloc_header*)c_ptr, ALLOC_HEADER_FLAG_FREE); + uint32_t cur_blk_size = read_alloc_header_size((alloc_header*)c_ptr); + uint32_t cur_blk_last = read_alloc_header_flag((alloc_header*)c_ptr, ALLOC_HEADER_FLAG_LAST); + if(cur_blk_free == 0) + { + //if cur block not a free block + if(cur_blk_last == 1) + //if last one, break and fail. + break; + else + c_ptr += cur_blk_size; + } + else if(cur_blk_size >= total_size) + { + // we have a free block with enough size + if(total_size == cur_blk_size || + cur_blk_size - total_size <= sizeof(alloc_header)) + { + // since the space left is not enough for alloc_header + // we alloc the whole block + set_alloc_header_flag((alloc_header*)c_ptr, ALLOC_HEADER_FLAG_FREE, 0); + } + else + { + // we split the block here + // set properties for the first block + set_alloc_header_size((alloc_header*)c_ptr, total_size); + set_alloc_header_flag((alloc_header*)c_ptr, ALLOC_HEADER_FLAG_LAST, 0); + set_alloc_header_flag((alloc_header*)c_ptr, ALLOC_HEADER_FLAG_FREE, 0); + + // set properties for the second block + set_alloc_header_size((alloc_header*)(c_ptr + total_size), cur_blk_size - total_size); + set_alloc_header_flag((alloc_header*)(c_ptr + total_size), ALLOC_HEADER_FLAG_LAST, cur_blk_last); + set_alloc_header_flag((alloc_header*)(c_ptr + total_size), ALLOC_HEADER_FLAG_FREE, 1); + } + // return the pointer, skip the alloc header + *ptr = c_ptr + sizeof(alloc_header); + return 0; + } + } + } + // getting here means did not work + if(ptr != NULL) + *ptr = NULL; + return 1; +} + +char buffer[1024]; + + +int main() +{ + void *a = NULL, *b = NULL, *c = NULL, *d = NULL; + init_alloc(buffer, 1024); + kalloc(buffer, 10, &a); + kalloc(buffer, 10, &b); + kalloc(buffer, 10, &c); + kalloc(buffer, 10, &d); + return 0; +} \ No newline at end of file diff --git a/x64/src/c/common/sys/kdef.h b/x64/src/c/common/sys/kdef.h index d042442..6e3da12 100644 --- a/x64/src/c/common/sys/kdef.h +++ b/x64/src/c/common/sys/kdef.h @@ -3,6 +3,7 @@ #include #include +#include #define _KERNEL_ABI __attribute__((sysv_abi)) diff --git a/x64/src/c/hal/mem.c b/x64/src/c/hal/mem.c index 01b5595..187f956 100644 --- a/x64/src/c/hal/mem.c +++ b/x64/src/c/hal/mem.c @@ -2,9 +2,12 @@ #include "../common/sys/type.h" #include "mem.h" -#define kernel_heap_size 4096 +#define KERNEL_HEAP_SIZE 4096 + +char kernel_heap[KERNEL_HEAP_SIZE]; + char *_cur_heap = NULL; -extern char kernel_heap[kernel_heap_size]; +extern char kernel_heap[KERNEL_HEAP_SIZE]; void _KERNEL_ABI hal_write_pt_entry(void *const base, uint64_t const p_addr, uint64_t const attr) { @@ -141,7 +144,7 @@ void* _KERNEL_ABI hal_halloc(_IN size_t const size) { if (_cur_heap == NULL) _cur_heap = kernel_heap; - if (_cur_heap + size < kernel_heap + kernel_heap_size) + if (_cur_heap + size < kernel_heap + KERNEL_HEAP_SIZE) { _cur_heap = _cur_heap + size; return _cur_heap - size; diff --git a/x64/src/c/kernel/proc.c b/x64/src/c/kernel/proc.c new file mode 100644 index 0000000..c068df6 --- /dev/null +++ b/x64/src/c/kernel/proc.c @@ -0,0 +1 @@ +#include "proc.h" diff --git a/x64/src/c/kernel/proc.h b/x64/src/c/kernel/proc.h new file mode 100644 index 0000000..bd951dc --- /dev/null +++ b/x64/src/c/kernel/proc.h @@ -0,0 +1,28 @@ +// +// Created by Oscar on 2016-04-24. +// + +#ifndef _PROC_H +#define _PROC_H + + +#include "../common/sys/kdef.h" + +typedef struct __attribute__((packed)) +{ + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; +} process_context_t; + +typedef struct __attribute__((packed)) +{ + uint32_t process_id; + uint32_t priority; + process_context_t context; + +} process_control_block_t; + + +#endif