Skip to content

Commit

Permalink
kernel side malloc
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc-Ducret committed May 11, 2017
1 parent 8da59a1 commit 4edb787
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 29 deletions.
1 change: 1 addition & 0 deletions programs/lib/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ u32 rand() {
}

void lib_init() {
init_malloc();
create_channel_stream(1);
initCharTable();
init_error_msg();
Expand Down
3 changes: 1 addition & 2 deletions programs/lib/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ pid_t wait(int *status) {

void exit(int status) {
// Flushes all channels and leaves.
for(int i = 0; i < NUM_CHANNELS_PROC; i++)
flush(i);
flush(STDOUT);

asm volatile("\
movl $4, %%eax \n \
Expand Down
2 changes: 1 addition & 1 deletion programs/src/ls/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ int main(char *args) {
flush(STDOUT);
exit(EXIT_SUCCESS);
return 0;
}
}
5 changes: 2 additions & 3 deletions programs/src/malloc_test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

int main() {
printf("Hello!\n");
init_malloc();
u32 *x = (u32*) malloc(sizeof(u32));
*x = 0xFEE;
printf("x = %x, *x = %x\n", x, *x);
Expand All @@ -19,10 +18,10 @@ int main() {
printf("z = %x, *z = %x\n", z, *z);

u32 n = 0x80;
u32 m = 0x1800;
u32 m = 0x200000;
void ** pointers = (void **) malloc(n * sizeof(void **));
for(int i = 0; i < n; i ++) pointers[i] = NULL;
for(u32 ct = 0; ct < 0x1000; ct++) {
for(u32 ct = 0; ct < 0x10000; ct++) {
int i = rand() % n;
if(pointers[i]) free(pointers[i]);
pointers[i] = malloc(rand() % m);
Expand Down
3 changes: 2 additions & 1 deletion programs/src/ps/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ char *pad(int a) {

int main(char *args) {
if (*args) {
printf("%s\n", args);//TODO rm
too_many_args("ps");
}
process_info_t p;
Expand All @@ -54,4 +55,4 @@ int main(char *args) {
}
exit(EXIT_SUCCESS);
return 0;
}
}
15 changes: 13 additions & 2 deletions sources/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

syscall_fun_t syscall_fun[NUM_SYSCALLS];
volatile int no_process = 0;
int hanging_pd = 0;

list* malloc_list() {
static int base = 0;
Expand Down Expand Up @@ -170,6 +171,7 @@ void kill_process(pid_t pid) {
s->processes[pid].state = ZOMBIE;
pid_t pere = s->processes[pid].parent_id;

hanging_pd = 1;
//On trouve les processus fils de celui ci.
pid_t j;
for (j = 0; j < NUM_PROCESSES; j++) {
Expand All @@ -192,8 +194,6 @@ void kill_process(pid_t pid) {
//On enlève le processus de sa file
s->runqueues[MAX_PRIORITY] = filter(s->runqueues[MAX_PRIORITY], pid); //TODO priority?

//TODO clear PD

close(s->processes[pid].cwd);
}

Expand Down Expand Up @@ -673,6 +673,17 @@ void picosyscall(context_t *ctx) {
u32 did_init = 0;

void picotimer(context_t *ctx) {
if(hanging_pd) {
hanging_pd = 0;
for(int i = 0; i < NUM_PROCESSES; i ++) {
if(global_state.processes[i].state == FREE && global_state.processes[i].page_directory) {
if(i != global_state.curr_pid) {
free_page_directory(global_state.processes[i].page_directory);
global_state.processes[i].page_directory = NULL;
} else hanging_pd = 1;
}
}
}
// Update sleeping processes
state *s = &global_state;
//if (no_process)
Expand Down
1 change: 1 addition & 0 deletions sources/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void provideKeyEvent(u8 event) {
if(event < 0x80 && event == KEY_TAB) focus_next_process();
if(event < 0x80 && event == KEY_STAR) {
log_state(&global_state);
print_malloc();
asm("hlt");
}
else if(writeCursor != (readCursor-1) % BUFFER_SIZE) {
Expand Down
101 changes: 98 additions & 3 deletions sources/memory.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
#include "memory.h"
#include <stddef.h>
#include "printing.h"

//TODO Frame allocation !!!! REAL malloc...
#define HEAP_SIZE 0x2000000

volatile u32 free_address = (u32) &end;
volatile u32 kernel_mem_end = (u32) &end + 0x500000;
volatile u32 kernel_mem_end = (u32) &end + HEAP_SIZE + 1;

void* kmalloc_3(u32 size, int align, u32 *phys) {
//Simple linear malloc, whithout any free.
Expand Down Expand Up @@ -43,3 +42,99 @@ void* kmalloc_p(u32 size, u32 *phys) {
return kmalloc_3(size, 0, phys);
}

void *start_heap;
void *heap_pointer;
malloc_header_t *first_block;

void print_malloc() {
kprintf("heap: %x-%x\n", start_heap, heap_pointer);
}

void init_malloc() {
kprintf("Init malloc\n");
start_heap = kmalloc(HEAP_SIZE);
heap_pointer = start_heap;
first_block = NULL;
malloc(0);
}

void *expand_heap(int size) {
void *h = heap_pointer;
if(size) {
heap_pointer += size;
if(heap_pointer >= start_heap + HEAP_SIZE) {
kprintf("KERNEL HEAP OVERFLOW\n");
asm("cli\nhlt");
}
}
return h;
}

void shrink_heap(int size) {
heap_pointer -= size;
}

void *over_allign(void *p) {
return (void*) (((u32)p-1) | 0xFFF) + 1;
}

void *malloc(u32 size) {
size += sizeof(malloc_header_t);
malloc_header_t *prev_block = NULL;
for(malloc_header_t *block = first_block; block; block = block->next_block) {
void *potential_addr = over_allign((void *)block + block->size + sizeof(malloc_header_t))
- sizeof(malloc_header_t);
if(block->next_block && (u32) block->next_block >= (u32) potential_addr + size) {
malloc_header_t *new_block = (malloc_header_t *) (potential_addr);
memset(new_block, 0, size);
//kprintf("alloc at %x [s=%x] between %x and %x\n", new_block, size, (void*)block+block->size, block->next_block);
new_block->prev_block = block;
new_block->next_block = block->next_block;
new_block->size = size;
block->next_block->prev_block = new_block;
block->next_block = new_block;
if(((u32) new_block + sizeof(malloc_header_t)) & 0xFFF) {
kprintf("Malloc allign failure\n");
asm("cli\nhlt");
}
return (void *) new_block + sizeof(malloc_header_t);
}
prev_block = block;
}
malloc_header_t *new_block = (malloc_header_t *) (over_allign(heap_pointer + sizeof(malloc_header_t))
- sizeof(malloc_header_t));
expand_heap((u32) new_block + size - (u32) heap_pointer);
if(!new_block) return NULL;
memset(new_block, 0, size);
new_block->size = size;
new_block->next_block = NULL;
if(prev_block) {
prev_block->next_block = new_block;
new_block->prev_block = prev_block;
} else {
new_block->prev_block = NULL;
first_block = new_block;
}
if(((u32) new_block + sizeof(malloc_header_t)) & 0xFFF) {
kprintf("Malloc allign failure\n");
asm("cli\nhlt");
}
return (void *) new_block + sizeof(malloc_header_t);
}

void free(void *allocated) {
malloc_header_t *block = (malloc_header_t*) allocated - 1;
if(block->prev_block) {
block->prev_block->next_block = block->next_block;
if(block->next_block)
block->next_block->prev_block = block->prev_block;
else {
shrink_heap((u32) block + block->size - (u32) block->prev_block - block->prev_block->size);
}
} else {
kprintf("Malloc free first block\n");
asm("cli\nhlt");
shrink_heap(block->size);
first_block = NULL;
}
}
17 changes: 13 additions & 4 deletions sources/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@
#include "int.h"
extern u32 end;
volatile u32 free_address, kernel_mem_end;
void* kmalloc(u32 size);
void* kmalloc_a(u32 size);
void* kmalloc_p(u32 size, u32 *phys);
void* kmalloc_3(u32 size, int align, u32 *phys);

typedef struct malloc_header malloc_header_t;

struct malloc_header {

u32 size;
malloc_header_t *prev_block, *next_block;
};

void *malloc(u32 size);
void free(void *allocated);
void init_malloc();
void print_malloc();
// Start of the free space used for this kmalloc
#endif /* MEMORY_H */

44 changes: 31 additions & 13 deletions sources/paging.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ void set_frame(u32 frame_addr) {
}

void clear_frame(u32 frame_addr) {
if(frame_addr <= kernel_mem_end) return;
// Sets the corresponding frame as unused.
u32 frame = frame_addr / PAGE_SIZE;
u32 table_index = frame >> 5;
Expand All @@ -50,6 +51,10 @@ u32 new_frame() {
u32 value = frames[index];
for (offset = 0; offset < 32; offset++) {
if (!(value & 1)) {
if((index << 5) + offset == 0) {
kprintf("ALLOC ON FRAME 0!\n");
asm("hlt");
}
return (index << 5) + offset;
}
value = value >> 1;
Expand All @@ -74,6 +79,7 @@ void map_page(page_t* page, u32 phys_address, int is_kernel, int is_writable) {
u32 frame = phys_address ? phys_address >> 12 : new_frame();

if (frame == nb_frames) {
asm("cli");
kprintf("No more frames left. Not good.\n");
asm("hlt");
return;
Expand All @@ -97,7 +103,7 @@ void invalidate(u32 address) {
asm volatile("invlpg (%0)" ::"r" (address) : "memory");
}

void free_page(page_t * page, u32 address) {
void free_page(page_t *page, u32 address) {
// Frees this page, if not already done.

if (!page->present)
Expand All @@ -109,7 +115,19 @@ void free_page(page_t * page, u32 address) {
invalidate(address);
}

page_t *get_page(u32 address, int make, page_directory_t* directory) {
void free_page_table(page_table_t *table, u32 tindex) {
for(int i = 0; i < 0x400; i ++) free_page(&table->pages[i], ((tindex*0x400)+i)*0x1000);
}

void free_page_directory(page_directory_t *pd) {
for(int i = 0; i < 0x400; i ++) if(pd->tables[i]) {
free_page_table(pd->tables[i], i);
free(pd->tables[i]);
}
free(pd);
}

page_t *get_page(u32 address, int make, page_directory_t *directory) {
// Gets a pointer to the page entry.
// If make, creates the corresponding page table if it doesn't exist.
address = address >> 12; // Index of the page
Expand All @@ -121,13 +139,11 @@ page_t *get_page(u32 address, int make, page_directory_t* directory) {
return &(directory->tables[index]->pages[offset]);
} else if (make) {
// Creates the corresponding page table.
u32 tmp;
page_table_t* new_table = (page_table_t*)
kmalloc_3(sizeof(page_table_t), 1, &tmp);
page_table_t* new_table = (page_table_t*) malloc(sizeof(page_table_t));
memset(new_table, 0, sizeof(page_table_t));

directory->tables[index] = new_table;
directory->tablesPhysical[index].table_addr = tmp >> 12;
directory->tablesPhysical[index].table_addr = (u32) new_table >> 12;
directory->tablesPhysical[index].present = 1;
directory->tablesPhysical[index].accessed = 0;
directory->tablesPhysical[index].rw = 1;
Expand Down Expand Up @@ -155,16 +171,17 @@ void switch_to_default_page_directory() {
page_directory_t *get_identity() { return identity_pd; }

void init_paging(u32 mem_end) {
init_malloc();
// Init of frames table
memory_end = mem_end;
nb_frames = memory_end >> 12;
size_frames_table = nb_frames >> 5;
frames = (u32*) kmalloc(size_frames_table << 2);
frames = (u32*) malloc(size_frames_table << 2);
memset((u8*) frames, 0, size_frames_table << 2);

// Init of page directory
identity_pd = (page_directory_t*) kmalloc_a(sizeof(page_directory_t));
memset((u8*)identity_pd, 0, sizeof(page_directory_t));
identity_pd = (page_directory_t*) malloc(sizeof(page_directory_t));
memset(identity_pd, 0, sizeof(page_directory_t));

// Identity paging
// Allocates only what we need
Expand Down Expand Up @@ -202,7 +219,7 @@ int copy_bin(u32 buffer_code_addr, u32 user_code_len, page_directory_t *user_pd,
page_directory_t *init_user_page_dir(fd_t fd, char *args, page_directory_t *cur_pd) {
asm volatile ("mov %cr3, %eax \n"
"mov %eax, tmp ");
cur_pd = (page_directory_t*) (tmp - 0x1000); //TODO do better
cur_pd = (page_directory_t*) (tmp - 0x1000);

// Creates a new page directory and initializes it with specified binary.
void *user_code = (void *) USER_CODE_VIRTUAL - CODE_LEN;
Expand All @@ -214,7 +231,8 @@ page_directory_t *init_user_page_dir(fd_t fd, char *args, page_directory_t *cur_
return NULL;
}

page_directory_t *pd = kmalloc_a(sizeof(page_directory_t)); // TODO Real malloc ?
page_directory_t *pd = malloc(sizeof(page_directory_t));
memset(pd, 0, sizeof(page_directory_t)); //TODO rm
if (pd == NULL) {
int err = errno;
close(fd);
Expand Down Expand Up @@ -302,8 +320,8 @@ int check_address(void *address, int user, int write, page_directory_t *pd) {
}
if ((!page->user && user) || (!page->rw && write)) {
errno = EFAULT;
kprintf("Voila : address %x, page_user %d, page_write %d, user %d, write %d\n",
address, page->user, page->rw, user, write);
kprintf("Voila : address %x, page_user %d, page_write %d, user %d, write %d, eip %x\n",
address, page->user, page->rw, user, write, get_global_state()->processes[get_global_state()->curr_pid].saved_context.stack.eip);
asm("hlt");
return -1;
}
Expand Down
2 changes: 2 additions & 0 deletions sources/paging.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,7 @@ page_directory_t *get_identity();
void map_page(page_t *page, u32 phys_address, int is_kernel, int is_writable);
void free_page(page_t *page, u32 address);
int check_address(void *address, int user, int write, page_directory_t *pd);
void free_page_directory(page_directory_t *pd);

#endif /* PAGING_H */

0 comments on commit 4edb787

Please sign in to comment.