From c55bc80baa51dc1028cbbae8a02540cfe4c56557 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Wed, 5 Jul 2017 13:53:42 +0200 Subject: 'mem' command shows memory usage of kernel heap now implemented a malloc/free and memory manager (simplest possible implementation, just allocating linearly and never freeing) --- src/Makefile | 7 +++++-- src/kernel/kernel.c | 34 +++++++++++++++++++++++++++++++--- src/kernel/memorymanagement.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/kernel/memorymanagement.h | 16 ++++++++++++++++ src/libc/stdio.c | 40 ++++++++++++++++++++-------------------- src/libc/stdio.h | 4 +--- src/libc/stdlib.c | 19 +++++++++++++++++++ src/libc/stdlib.h | 9 +++++++++ 8 files changed, 141 insertions(+), 28 deletions(-) create mode 100644 src/kernel/memorymanagement.c create mode 100644 src/kernel/memorymanagement.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index c256605..d8b279f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -33,11 +33,11 @@ kernel.bin: kernel.elf kernel.sym: kernel.elf $(OBJCOPY) --only-keep-debug kernel.elf kernel.sym -kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o kernel/tasks.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o gui/widget.o gui/composite_widget.o gui/window.o gui/desktop.o gui/text_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o +kernel.elf: kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o kernel/memorymanagement.o kernel/tasks.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o gui/widget.o gui/composite_widget.o gui/window.o gui/desktop.o gui/text_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o $(LD) -o kernel.elf -N -n -Ttext 0x8800 --oformat elf32-i386 \ kernel/kernel.o kernel/kernel_asm.o \ kernel/console.o kernel/vgatext.o kernel/serial.o \ - kernel/tasks.o \ + kernel/memorymanagement.o kernel/tasks.o \ hardware/port.o hardware/port_asm.o \ hardware/interrupts.o hardware/interrupts_asm.o \ hardware/pci.o \ @@ -72,6 +72,9 @@ kernel/vgatext.o: kernel/vgatext.c kernel/vgatext.h kernel/serial.o: kernel/serial.c kernel/serial.h $(CC) $(CFLAGS) -c -o kernel/serial.o kernel/serial.c +kernel/memorymanagement.o: kernel/memorymanagement.c kernel/memorymanagement.h + $(CC) $(CFLAGS) -c -o kernel/memorymanagement.o kernel/memorymanagement.c + kernel/tasks.o: kernel/tasks.c kernel/tasks.h $(CC) $(CFLAGS) -c -o kernel/tasks.o kernel/tasks.c diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index a9802e1..a6594f6 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -42,6 +42,7 @@ typedef struct { vga_text_t vga_text; driver_manager_t driver_manager; task_manager_t task_manager; + memory_manager_t memory_manager; vga_t vga; mode_t mode; mouse_t mouse; @@ -60,6 +61,7 @@ static void refresh_screen( void ); static void switch_to_graphics_mode( global_context_t *global_context ); static void switch_to_text_mode( global_context_t *global_context ); static void print_task_status( global_context_t *global_context ); +static void print_memory_status( global_context_t *global_context ); // must be first entry in kernel.bin (0x8800) as stage 2 of // the boot loader expects the entry point to be here! @@ -78,13 +80,25 @@ void kernel_main( void ) console_init( &console ); console_add_vga_text_output( &console, &global_context.vga_text ); console_add_serial_output( &console, &serial ); - + // initialize the early console of the kernel - stdio_set_console( &console ); + __stdio_set_console( &console ); puts( "Started early kernel console" ); // TODO: get those values somehow from the boot loader printf( "Kernel code and data is at 0x%X, kernel stack at 0x%X\n", 0x8800, 0x90000 ); + // initialize memory management first, we may need it + // TODO: get memupper from multiboot header (but this needs + // a multiboot compliant entry function first) or use BIOS + // functions to determine size of memory, for now assume we + // have at least, for now use the memory above 1 MB, 64 MB + // heap is enough for what we are doing in the kernel + memory_manager_init( &global_context.memory_manager, 0x100000, 0xFFFF ); + __stdlib_set_memory_manager( &global_context.memory_manager ); + printf( "Kernel heap at 0x%X, size 0x%X\n", 0x100000, 0xFFFF ); + void *test = malloc( 2048 ); + free( test ); + // exit point in case of kernel panic, do this as soon as // possible, as soon we have an early console we can croak on if( setjmp( panic_jmp_buf ) > 0 ) { @@ -211,7 +225,7 @@ static void handle_keyboard_event( keyboard_event_t *event, void *context ) } else if( strcmp( buf, "halt" ) == 0 ) { longjmp( panic_jmp_buf, 0 ); } else if( strcmp( buf, "mem" ) == 0 ) { - // TODO: print memory usage + print_memory_status( global_context ); } else if( strcmp( buf, "task" ) == 0 ) { print_task_status( global_context ); } else if( strcmp( buf, "driver" ) == 0 ) { @@ -411,3 +425,17 @@ static void print_task_status( global_context_t *global_context ) } } +static void print_memory_status( global_context_t *global_context ) +{ + memory_manager_t *memory_manager = &global_context->memory_manager; + + printf( "heap memory size: %d\n", memory_manager->size ); + printf( "heap memory offset: 0x%X\n", memory_manager->offset ); + printf( "heap memory in use: %d\n", + memory_manager->free_ptr - memory_manager->offset ); + printf( "heap memory free: %d\n", + memory_manager->size - ( memory_manager->free_ptr - memory_manager->offset ) - 1 ); + +} + + diff --git a/src/kernel/memorymanagement.c b/src/kernel/memorymanagement.c new file mode 100644 index 0000000..dc2d160 --- /dev/null +++ b/src/kernel/memorymanagement.c @@ -0,0 +1,40 @@ +#include "memorymanagement.h" + +#include "string.h" + +#include "kernel.h" + +void memory_manager_init( memory_manager_t *memory_manager, size_t offset, size_t size ) +{ + memset( memory_manager, 0, sizeof( memory_manager_t ) ); + + memory_manager->offset = offset; + memory_manager->size = size; + memory_manager->free_ptr = offset; +} + +void *memory_manager_allocate( memory_manager_t *memory_manager, size_t size ) +{ + void *p = NULL; + + if( memory_manager->free_ptr - memory_manager->offset + size > memory_manager->size ) { + kernel_panic( "Heap allocation out of memory (requested %d bytes, available %d)", + size, size - ( memory_manager->free_ptr - memory_manager->offset ) - 1 ); + } + + p = (void *)memory_manager->free_ptr; + memory_manager->free_ptr += size; + + return p; +} + +void memory_manager_deallocate( memory_manager_t *memory_manager, void **p ) +{ + if( *p == NULL ) { + kernel_panic( "Double free of pointer 0x%X in heap", *p ); + } + + *p = NULL; +} + + diff --git a/src/kernel/memorymanagement.h b/src/kernel/memorymanagement.h new file mode 100644 index 0000000..16f0b29 --- /dev/null +++ b/src/kernel/memorymanagement.h @@ -0,0 +1,16 @@ +#ifndef MEMORYMANAGEMENT_H +#define MEMORYMANAGEMENT_H + +#include "stddef.h" + +typedef struct { + size_t offset; + size_t size; + uint32_t free_ptr; +} memory_manager_t; + +void memory_manager_init( memory_manager_t *memory_manager, size_t offset, size_t size ); +void *memory_manager_allocate( memory_manager_t *memory_manager, size_t size ); +void memory_manager_deallocate( memory_manager_t *memory_manager, void **p ); + +#endif // MEMORYMANAGEMENT_H diff --git a/src/libc/stdio.c b/src/libc/stdio.c index 1d53f7a..07a047e 100644 --- a/src/libc/stdio.c +++ b/src/libc/stdio.c @@ -3,16 +3,16 @@ #include "stdlib.h" #include "string.h" -console_t *global_console = NULL; +console_t *stdio_console = NULL; int puts( const char *s ) { - if( global_console == NULL ) { + if( stdio_console == NULL ) { return EOF; } - console_put_string( global_console, s ); - console_put_newline( global_console ); + console_put_string( stdio_console, s ); + console_put_newline( stdio_console ); return 1; } @@ -33,34 +33,34 @@ int vprintf( const char *format, va_list args ) const char *s = format; int n = 0; - if( global_console == NULL ) { + if( stdio_console == NULL ) { return -1; } while( *s != '\0' ) { switch( *s ) { case '\n': - console_put_newline( global_console ); + console_put_newline( stdio_console ); n++; break; case '%': s++; if( *s == '\0' ) { - console_put_string( global_console, "" ); - console_put_newline( global_console ); + console_put_string( stdio_console, "" ); + console_put_newline( stdio_console ); return -1; } switch( *s ) { case '%': - console_put_char( global_console, '%' ); + console_put_char( stdio_console, '%' ); break; case 'X': { char buf[19]; itoa( va_arg( args, int ), (char *)buf, 16 ); - console_put_string( global_console, buf ); + console_put_string( stdio_console, buf ); n += strlen( buf ); } break; @@ -68,30 +68,30 @@ int vprintf( const char *format, va_list args ) case 'd': { char buf[19]; itoa( va_arg( args, int ), (char *)buf, 10 ); - console_put_string( global_console, buf ); + console_put_string( stdio_console, buf ); n += strlen( buf ); } break; case 'c': - console_put_char( global_console, va_arg( args, int ) ); + console_put_char( stdio_console, va_arg( args, int ) ); break; case 's': - console_put_string( global_console, va_arg( args, const char * ) ); + console_put_string( stdio_console, va_arg( args, const char * ) ); break; default: - console_put_string( global_console, "" ); - console_put_newline( global_console ); + console_put_string( stdio_console, "" ); + console_put_newline( stdio_console ); } break; default: - console_put_char( global_console, *s ); + console_put_char( stdio_console, *s ); n++; } s++; @@ -100,7 +100,7 @@ int vprintf( const char *format, va_list args ) return n; } -void stdio_set_console( console_t *console ) +void __stdio_set_console( console_t *console ) { - global_console = console; + stdio_console = console; } diff --git a/src/libc/stdio.h b/src/libc/stdio.h index bc7fac0..dbf7ac7 100644 --- a/src/libc/stdio.h +++ b/src/libc/stdio.h @@ -9,12 +9,10 @@ #define EOF (-1) -extern console_t *global_console; - int puts( const char *s ); int printf( const char *format, ... ); int vprintf( const char *format, va_list args ); -void stdio_set_console( console_t *console ); +void __stdio_set_console( console_t *console ); #endif //STDIO_H diff --git a/src/libc/stdlib.c b/src/libc/stdlib.c index 46bdce8..9150431 100644 --- a/src/libc/stdlib.c +++ b/src/libc/stdlib.c @@ -45,4 +45,23 @@ char *itoa( int v, char *s, int base ) return s; } + +// TODO: we should have a global memory manager and one per +// user process later +static memory_manager_t *stdlib_memory_manager = NULL; +void *malloc( size_t size ) +{ + return memory_manager_allocate( stdlib_memory_manager, size ); +} + +void free( void *p ) +{ + memory_manager_deallocate( stdlib_memory_manager, &p ); +} + +void __stdlib_set_memory_manager( memory_manager_t *memory_manager ) +{ + stdlib_memory_manager = memory_manager; +} + diff --git a/src/libc/stdlib.h b/src/libc/stdlib.h index 331012e..ff6b67f 100644 --- a/src/libc/stdlib.h +++ b/src/libc/stdlib.h @@ -1,6 +1,15 @@ #ifndef STDLIB_H #define STDLIB_H +#include "stddef.h" + +#include "memorymanagement.h" + char *itoa( int v, char *s, int base ); +void *malloc( size_t size ); +void free( void *p ); + +void __stdlib_set_memory_manager( memory_manager_t *memory_manager ); + #endif // STDLIB_H -- cgit v1.2.3-54-g00ecf