diff --git a/boredos.iso b/boredos.iso index 09960fd..676f1ce 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/cmd.o b/build/cmd.o index 07e4fb5..b9d4a48 100644 Binary files a/build/cmd.o and b/build/cmd.o differ diff --git a/build/explorer.o b/build/explorer.o index a1ec968..57aac8c 100644 Binary files a/build/explorer.o and b/build/explorer.o differ diff --git a/build/idt.o b/build/idt.o index 2a0666e..251961c 100644 Binary files a/build/idt.o and b/build/idt.o differ diff --git a/build/main.o b/build/main.o index 5f3a988..cc7d430 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/ps2.o b/build/ps2.o index a756f0b..317c12e 100644 Binary files a/build/ps2.o and b/build/ps2.o differ diff --git a/src/kernel/elf.c b/src/kernel/elf.c index 9ce6acf..297b886 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -9,15 +9,9 @@ extern void serial_print(const char *s); extern void serial_write(const char *str); -static void print_hex(uint64_t n) { - char buf[17]; - char* x = "0123456789ABCDEF"; - buf[16] = 0; - for (int i=15; i>=0; i--) { buf[i] = x[n & 0xF]; n >>= 4; } - serial_write(buf); -} -uint64_t elf_load(const char *path, uint64_t user_pml4) { +uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size) { + if (out_load_size) *out_load_size = 0; FAT32_FileHandle *file = fat32_open(path, "r"); if (!file || !file->valid) { serial_write("[ELF] Error: Failed to open file "); @@ -113,6 +107,7 @@ uint64_t elf_load(const char *path, uint64_t user_pml4) { uint64_t phys_addr = v2p((uint64_t)bulk_phys + (p * 4096)); paging_map_page(user_pml4, vaddr, phys_addr, 0x07); } + if (out_load_size) *out_load_size += total_needed; } } diff --git a/src/kernel/elf.h b/src/kernel/elf.h index 06c8a34..20f286c 100644 --- a/src/kernel/elf.h +++ b/src/kernel/elf.h @@ -69,9 +69,10 @@ typedef struct { #define PF_R 4 #include +#include // Loads the ELF executable at 'path' using fat32 into the pagemap given by user_pml4. // Returns entry point address on success, or 0 on failure. -uint64_t elf_load(const char *path, uint64_t user_pml4); +uint64_t elf_load(const char *path, uint64_t user_pml4, size_t *out_load_size); #endif diff --git a/src/kernel/process.c b/src/kernel/process.c index 2e37864..f5ae52c 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -44,6 +44,7 @@ void process_init(void) { extern void mem_memcpy(void *dest, const void *src, size_t len); mem_memcpy(kernel_proc->name, "kernel", 7); kernel_proc->ticks = 0; + kernel_proc->used_memory = 32768; // Kernel stack kernel_proc->next = kernel_proc; // Circular linked list current_process = kernel_proc; @@ -168,7 +169,8 @@ process_t* process_create_elf(const char* filepath, const char* args_str) { new_proc->is_terminal_proc = false; // 2. Load ELF executable - uint64_t entry_point = elf_load(filepath, new_proc->pml4_phys); + size_t elf_load_size = 0; + uint64_t entry_point = elf_load(filepath, new_proc->pml4_phys, &elf_load_size); if (entry_point == 0) { serial_write("[PROCESS] Failed to load ELF: "); serial_write(filepath); @@ -307,6 +309,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) { new_proc->kernel_stack_alloc = kernel_stack; new_proc->user_stack_alloc = stack; new_proc->rsp = (uint64_t)stack_ptr; + new_proc->used_memory = elf_load_size + user_stack_size + 65536; // Initialize FPU state for new process asm volatile("fninit"); diff --git a/src/kernel/process.h b/src/kernel/process.h index 09812fe..843a50e 100644 --- a/src/kernel/process.h +++ b/src/kernel/process.h @@ -51,6 +51,7 @@ typedef struct process { char name[64]; uint64_t ticks; uint64_t sleep_until; + size_t used_memory; } __attribute__((aligned(16))) process_t; typedef struct { diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index f66ebe6..bbe3191 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -45,18 +45,12 @@ void syscall_init(void) { efer |= 1; // SCE bit is bit 0 wrmsr(MSR_EFER, efer); - // STAR MSR setup: - // Bits 32-47: Syscall CS and SS. CS = STAR[47:32], SS = STAR[47:32] + 8 (Kernel CS = 0x08) - // Bits 48-63: Sysret CS and SS. CS = STAR[63:48] + 16, SS = STAR[63:48] + 8. - // User Data must be Base+8, User Code must be Base+16. - // Our GDT: User Data = 0x1B, User Code = 0x23. - // Therefore Base = 0x13. + uint64_t star = ((uint64_t)0x08 << 32) | ((uint64_t)0x13 << 48); wrmsr(MSR_STAR, star); wrmsr(MSR_LSTAR, (uint64_t)syscall_entry); - // Mask Interrupts on SYSCALL (Clear IF bit in RFLAGS during syscall execution) wrmsr(MSR_FMASK, 0x200); } @@ -849,6 +843,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) { paging_map_page(proc->pml4_phys, page, v2p(phys_addr), 0x07); // PT_PRESENT | PT_RW | PT_USER phys_addr += 4096; } + proc->used_memory += (end_page - start_page); } } @@ -1120,7 +1115,19 @@ static uint64_t syscall_handler_inner(registers_t *regs) { if (!out) return 0; extern process_t processes[]; - extern int process_count; + + // Dynamically calculate kernel usage as: Total System Used - User Process Sum + MemStats stats = memory_get_stats(); + size_t total_used = stats.used_memory; + size_t user_used = 0; + for (int i = 0; i < 16; i++) { + if (processes[i].pid != 0xFFFFFFFF && processes[i].pid != 0) { + user_used += processes[i].used_memory; + } + } + if (total_used > user_used) processes[0].used_memory = total_used - user_used; + else processes[0].used_memory = 0; + int count = 0; for (int i = 0; i < 16; i++) { // MAX_PROCESSES is 16 if (processes[i].pid != 0xFFFFFFFF) { @@ -1129,19 +1136,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) { mem_memcpy(out[count].name, processes[i].name, 64); out[count].ticks = processes[i].ticks; - // Memory estimation: heap + stacks - size_t mem = 0; - if (processes[i].heap_end > processes[i].heap_start) - mem += (processes[i].heap_end - processes[i].heap_start); - - if (processes[i].pid == 0) { - mem = 32768; - } else { - if (processes[i].is_user) mem += 262144; // User stack - mem += 32768; // Kernel stack - } - - out[count].used_memory = mem; + out[count].used_memory = processes[i].used_memory; count++; if (count >= max_procs) break; diff --git a/src/kernel/userland/browser.c b/src/kernel/userland/browser.c index 085dbd1..996fc4f 100644 --- a/src/kernel/userland/browser.c +++ b/src/kernel/userland/browser.c @@ -601,6 +601,11 @@ static uint32_t parse_html_color(const char *str) { if (str_istarts_with(str, "yellow")) return 0xFFFFFF00; if (str_istarts_with(str, "gray")) return 0xFF808080; if (str_istarts_with(str, "purple")) return 0xFF800080; + if (str_istarts_with(str, "silver")) return 0xFFC0C0C0; + if (str_istarts_with(str, "maroon")) return 0xFF800000; + if (str_istarts_with(str, "navy")) return 0xFF000080; + if (str_istarts_with(str, "teal")) return 0xFF008080; + if (str_istarts_with(str, "olive")) return 0xFF808000; return COLOR_TEXT; } @@ -650,6 +655,27 @@ static void decode_html_entities(char *str) { if (str_istarts_with(src, "Á")) { *dst++ = (char)193; src += 8; continue; } if (str_istarts_with(src, "×")) { *dst++ = (char)215; src += 7; continue; } if (str_istarts_with(src, "÷")) { *dst++ = (char)247; src += 8; continue; } + if (str_istarts_with(src, "±")) { *dst++ = (char)177; src += 8; continue; } + if (str_istarts_with(src, "µ")) { *dst++ = (char)181; src += 7; continue; } + if (str_istarts_with(src, "¶")) { *dst++ = (char)182; src += 6; continue; } + if (str_istarts_with(src, "¦")) { *dst++ = (char)166; src += 8; continue; } + if (str_istarts_with(src, "§")) { *dst++ = (char)167; src += 6; continue; } + if (str_istarts_with(src, "¨")) { *dst++ = (char)168; src += 5; continue; } + if (str_istarts_with(src, "ª")) { *dst++ = (char)170; src += 6; continue; } + if (str_istarts_with(src, "«")) { *dst++ = (char)171; src += 7; continue; } + if (str_istarts_with(src, "¬")) { *dst++ = (char)172; src += 5; continue; } + if (str_istarts_with(src, "­")) { src += 5; continue; } // Soft hyphen, ignore + if (str_istarts_with(src, "¯")) { *dst++ = (char)175; src += 6; continue; } + if (str_istarts_with(src, "²")) { *dst++ = (char)178; src += 6; continue; } + if (str_istarts_with(src, "³")) { *dst++ = (char)179; src += 6; continue; } + if (str_istarts_with(src, "´")) { *dst++ = (char)180; src += 7; continue; } + if (str_istarts_with(src, "¸")) { *dst++ = (char)184; src += 7; continue; } + if (str_istarts_with(src, "¹")) { *dst++ = (char)185; src += 6; continue; } + if (str_istarts_with(src, "º")) { *dst++ = (char)186; src += 6; continue; } + if (str_istarts_with(src, "»")) { *dst++ = (char)187; src += 7; continue; } + if (str_istarts_with(src, "¼")) { *dst++ = (char)188; src += 8; continue; } + if (str_istarts_with(src, "½")) { *dst++ = (char)189; src += 8; continue; } + if (str_istarts_with(src, "¾")) { *dst++ = (char)190; src += 8; continue; } if (src[1] == '#') { int val = 0; @@ -704,12 +730,14 @@ static void parse_html(const char *html) { int list_type[16] = {0}; int list_index[16] = {0}; bool is_pre = false; + bool is_plaintext = false; + int table_col = 0; next_form_id = 1; bool inside_title = false; char page_title[256] = ""; while (html[i] && element_count < MAX_ELEMENTS) { - if (html[i] == '<') { + if (html[i] == '<' && !is_plaintext) { if (html[i+1] == '!' && html[i+2] == '-' && html[i+3] == '-') { i += 4; while (html[i] && !(html[i] == '-' && html[i+1] == '-' && html[i+2] == '>')) i++; @@ -730,7 +758,28 @@ static void parse_html(const char *html) { if (tag_name[0] == '/') { if (str_iequals(tag_name+1, "center")) { emit_br(); if (center_depth > 0) center_depth--; } - else if (str_iequals(tag_name+1, "table")) { emit_br(); if (table_depth > 0) table_depth--; } + else if (str_iequals(tag_name+1, "table")) { emit_br(); if (table_depth > 0) table_depth--; table_col = 0; } + else if (str_iequals(tag_name+1, "tr")) { emit_br(); table_col = 0; } + else if (str_iequals(tag_name+1, "td") || str_iequals(tag_name+1, "th")) { + table_col++; + if (table_col == 1) { + // Add spacer to align second column + RenderElement *el = &elements[element_count++]; + memset(el, 0, sizeof(RenderElement)); + el->tag = TAG_NONE; el->content[0] = ' '; el->content[1] = 0; + int current_x = cur_line_x; + for (int k=0; kw = target_x - current_x; + } else { + el->w = 10; + } + el->scale = current_scale; el->list_depth = list_depth; el->blockquote_depth = blockquote_depth; + } + if (str_iequals(tag_name+1, "th")) is_bold = false; + } + else if (str_iequals(tag_name+1, "caption")) { emit_br(); is_bold = false; if (center_depth > 0) center_depth--; } else if (str_iequals(tag_name+1, "blockquote")) { emit_br(); if (blockquote_depth > 0) blockquote_depth--; } else if (str_iequals(tag_name+1, "ul") || str_iequals(tag_name+1, "ol") || str_iequals(tag_name+1, "dl") || str_iequals(tag_name+1, "dir") || str_iequals(tag_name+1, "menu")) { emit_br(); if (list_depth > 0) list_depth--; } @@ -748,7 +797,7 @@ static void parse_html(const char *html) { } else if (str_iequals(tag_name+1, "a")) current_link[0] = 0; else if (str_iequals(tag_name+1, "p") || str_iequals(tag_name+1, "li") || str_iequals(tag_name+1, "div") || str_iequals(tag_name+1, "address")) emit_br(); - else if (str_iequals(tag_name+1, "pre")) { emit_br(); is_pre = false; } + else if (str_iequals(tag_name+1, "pre") || str_iequals(tag_name+1, "xmp") || str_iequals(tag_name+1, "listing")) { emit_br(); is_pre = false; } else if (str_iequals(tag_name+1, "font") || str_iequals(tag_name+1, "tt") || str_iequals(tag_name+1, "code") || str_iequals(tag_name+1, "samp") || str_iequals(tag_name+1, "kbd")) { if (font_ptr > 0) { font_ptr--; @@ -767,7 +816,19 @@ static void parse_html(const char *html) { } } else { if (str_iequals(tag_name, "center")) { emit_br(); center_depth++; } - else if (str_iequals(tag_name, "table")) { emit_br(); table_depth++; } + else if (str_iequals(tag_name, "table")) { emit_br(); table_depth++; table_col = 0; } + else if (str_iequals(tag_name, "tr")) { emit_br(); table_col = 0; } + else if (str_iequals(tag_name, "td") || str_iequals(tag_name, "th")) { + if (table_col > 0) { + RenderElement *el = &elements[element_count++]; + memset(el, 0, sizeof(RenderElement)); + el->tag = TAG_NONE; el->content[0] = ' '; el->content[1] = 0; el->w = 10; + el->h = ui_get_font_height_scaled(current_scale); + el->scale = current_scale; el->list_depth = list_depth; el->blockquote_depth = blockquote_depth; + } + if (str_iequals(tag_name, "th")) is_bold = true; + } + else if (str_iequals(tag_name, "caption")) { emit_br(); center_depth++; is_bold = true; } else if (str_iequals(tag_name, "blockquote")) { emit_br(); blockquote_depth++; } // Handle blockquote start else if (str_iequals(tag_name, "ul") || str_iequals(tag_name, "dir") || str_iequals(tag_name, "menu")) { emit_br(); list_type[list_depth] = 0; list_depth++; } @@ -787,16 +848,18 @@ static void parse_html(const char *html) { } else if (str_iequals(tag_name, "b") || str_iequals(tag_name, "strong")) is_bold = true; - else if (str_iequals(tag_name, "i") || str_iequals(tag_name, "em") || str_iequals(tag_name, "cite") || str_iequals(tag_name, "var")) is_italic = true; - else if (str_iequals(tag_name, "u")) is_underline = true; - else if (str_iequals(tag_name, "tt") || str_iequals(tag_name, "code") || str_iequals(tag_name, "samp") || str_iequals(tag_name, "kbd")) { + else if (str_iequals(tag_name, "i") || str_iequals(tag_name, "em") || str_iequals(tag_name, "cite") || str_iequals(tag_name, "var") || str_iequals(tag_name, "dfn")) is_italic = true; + else if (str_iequals(tag_name, "u") || str_iequals(tag_name, "s") || str_iequals(tag_name, "strike")) is_underline = true; + else if (str_iequals(tag_name, "tt") || str_iequals(tag_name, "code") || str_iequals(tag_name, "samp") || str_iequals(tag_name, "kbd") || str_iequals(tag_name, "xmp") || str_iequals(tag_name, "listing")) { if (font_ptr < MAX_FONT_STACK) { font_stack[font_ptr].color = current_color; font_stack[font_ptr].scale = current_scale; font_ptr++; } current_scale = 14.0f; + if (str_iequals(tag_name, "xmp") || str_iequals(tag_name, "listing")) { emit_br(); is_pre = true; } } + else if (str_iequals(tag_name, "plaintext")) { emit_br(); is_plaintext = true; is_pre = true; current_scale = 14.0f; } else if (str_iequals(tag_name, "address")) { emit_br(); } else if (str_iequals(tag_name, "html") || str_iequals(tag_name, "body")) skip_content = false; else if (str_iequals(tag_name, "head")) skip_content = true; @@ -1114,6 +1177,8 @@ static void parse_html_incremental(const char *html, int safe_len) { int current_form_id = inc_form_id; bool skip_content = inc_skip_content; bool is_pre = inc_is_pre; + bool is_plaintext = false; // We don't persist plaintext across incremental chunks easily + int table_col = 0; bool inside_title = inc_inside_title; char page_title[256]; { int k=0; while(current_page_title[k]) { page_title[k] = current_page_title[k]; k++; } page_title[k] = 0; } @@ -1121,7 +1186,7 @@ static void parse_html_incremental(const char *html, int safe_len) { #define EFF_CENTER ((center_depth > 0) && (table_depth == 0)) while (i < safe_len && html[i] && element_count < MAX_ELEMENTS) { - if (html[i] == '<') { + if (html[i] == '<' && !is_plaintext) { if (i + 3 < safe_len && html[i+1] == '!' && html[i+2] == '-' && html[i+3] == '-') { i += 4; while (i < safe_len && html[i] && !(i + 2 < safe_len && html[i] == '-' && html[i+1] == '-' && html[i+2] == '>')) i++; @@ -1142,7 +1207,23 @@ static void parse_html_incremental(const char *html, int safe_len) { if (tag_name[0] == '/') { if (str_iequals(tag_name+1, "center")) { emit_br(); if (center_depth > 0) center_depth--; } - else if (str_iequals(tag_name+1, "table")) { emit_br(); if (table_depth > 0) table_depth--; } + else if (str_iequals(tag_name+1, "table")) { emit_br(); if (table_depth > 0) table_depth--; table_col = 0; } + else if (str_iequals(tag_name+1, "tr")) { emit_br(); table_col = 0; } + else if (str_iequals(tag_name+1, "td") || str_iequals(tag_name+1, "th")) { + table_col++; + if (table_col == 1) { + RenderElement *el = &elements[element_count++]; + memset(el, 0, sizeof(RenderElement)); + el->tag = TAG_NONE; el->content[0] = ' '; el->content[1] = 0; + int current_x = cur_line_x; + for (int k=0; kw = target_x - current_x; else el->w = 10; + el->scale = current_scale; el->list_depth = list_depth; el->blockquote_depth = blockquote_depth; + } + if (str_iequals(tag_name+1, "th")) is_bold = false; + } + else if (str_iequals(tag_name+1, "caption")) { emit_br(); is_bold = false; if (center_depth > 0) center_depth--; } else if (str_iequals(tag_name+1, "blockquote")) { emit_br(); if (blockquote_depth > 0) blockquote_depth--; } else if (str_iequals(tag_name+1, "ul") || str_iequals(tag_name+1, "ol") || str_iequals(tag_name+1, "dl") || str_iequals(tag_name+1, "dir") || str_iequals(tag_name+1, "menu")) { emit_br(); if (list_depth > 0) list_depth--; } else if (str_iequals(tag_name+1, "dt")) { emit_br(); is_bold = false; } @@ -1155,7 +1236,7 @@ static void parse_html_incremental(const char *html, int safe_len) { else if (str_iequals(tag_name+1, "form")) { emit_br(); current_form_id = 0; current_form_action[0] = 0; } else if (str_iequals(tag_name+1, "a")) current_link[0] = 0; else if (str_iequals(tag_name+1, "p") || str_iequals(tag_name+1, "li") || str_iequals(tag_name+1, "div")) emit_br(); - else if (str_iequals(tag_name+1, "pre")) { emit_br(); is_pre = false; } + else if (str_iequals(tag_name+1, "pre") || str_iequals(tag_name+1, "xmp") || str_iequals(tag_name+1, "listing")) { emit_br(); is_pre = false; } else if (str_iequals(tag_name+1, "font") || str_iequals(tag_name+1, "tt") || str_iequals(tag_name+1, "code") || str_iequals(tag_name+1, "samp") || str_iequals(tag_name+1, "kbd")) { if (inc_font_ptr > 0) { inc_font_ptr--; @@ -1174,7 +1255,19 @@ static void parse_html_incremental(const char *html, int safe_len) { } } else { if (str_iequals(tag_name, "center")) { emit_br(); center_depth++; } - else if (str_iequals(tag_name, "table")) { emit_br(); table_depth++; } + else if (str_iequals(tag_name, "table")) { emit_br(); table_depth++; table_col = 0; } + else if (str_iequals(tag_name, "tr")) { emit_br(); table_col = 0; } + else if (str_iequals(tag_name, "td") || str_iequals(tag_name, "th")) { + if (table_col > 0) { + RenderElement *el = &elements[element_count++]; + memset(el, 0, sizeof(RenderElement)); + el->tag = TAG_NONE; el->content[0] = ' '; el->content[1] = 0; el->w = 10; + el->h = ui_get_font_height_scaled(current_scale); + el->scale = current_scale; el->list_depth = list_depth; el->blockquote_depth = blockquote_depth; + } + if (str_iequals(tag_name, "th")) is_bold = true; + } + else if (str_iequals(tag_name, "caption")) { emit_br(); center_depth++; is_bold = true; } else if (str_iequals(tag_name, "blockquote")) { emit_br(); blockquote_depth++; } else if (str_iequals(tag_name, "ul") || str_iequals(tag_name, "dir") || str_iequals(tag_name, "menu")) { emit_br(); list_type[list_depth] = 0; list_depth++; } else if (str_iequals(tag_name, "ol")) { emit_br(); list_type[list_depth] = 1; list_index[list_depth] = 1; list_depth++; } @@ -1186,17 +1279,19 @@ static void parse_html_incremental(const char *html, int safe_len) { el->w = ui_get_string_width_scaled(el->content, current_scale); el->h = ui_get_font_height_scaled(current_scale); el->color = current_color; el->centered = EFF_CENTER; el->bold = is_bold; el->italic = is_italic; el->underline = is_underline; el->scale = current_scale; el->list_depth = list_depth; el->blockquote_depth = blockquote_depth; } else if (str_iequals(tag_name, "b") || str_iequals(tag_name, "strong")) is_bold = true; - else if (str_iequals(tag_name, "i") || str_iequals(tag_name, "em") || str_iequals(tag_name, "cite") || str_iequals(tag_name, "var")) is_italic = true; - else if (str_iequals(tag_name, "u")) is_underline = true; + else if (str_iequals(tag_name, "i") || str_iequals(tag_name, "em") || str_iequals(tag_name, "cite") || str_iequals(tag_name, "var") || str_iequals(tag_name, "dfn")) is_italic = true; + else if (str_iequals(tag_name, "u") || str_iequals(tag_name, "s") || str_iequals(tag_name, "strike")) is_underline = true; else if (str_iequals(tag_name, "address")) emit_br(); - else if (str_iequals(tag_name, "tt") || str_iequals(tag_name, "code") || str_iequals(tag_name, "samp") || str_iequals(tag_name, "kbd")) { + else if (str_iequals(tag_name, "tt") || str_iequals(tag_name, "code") || str_iequals(tag_name, "samp") || str_iequals(tag_name, "kbd") || str_iequals(tag_name, "xmp") || str_iequals(tag_name, "listing")) { if (inc_font_ptr < MAX_FONT_STACK) { inc_font_stack[inc_font_ptr].color = current_color; inc_font_stack[inc_font_ptr].scale = current_scale; inc_font_ptr++; } current_scale = 14.0f; + if (str_iequals(tag_name, "xmp") || str_iequals(tag_name, "listing")) { emit_br(); is_pre = true; } } + else if (str_iequals(tag_name, "plaintext")) { emit_br(); is_plaintext = true; is_pre = true; current_scale = 14.0f; } else if (tag_name[0] == 'h' && tag_name[1] >= '1' && tag_name[1] <= '6') { emit_br(); emit_br(); is_bold = true; if (tag_name[1] == '1') base_scale = 32.0f; else if (tag_name[1] == '2') base_scale = 24.0f; else if (tag_name[1] == '3') base_scale = 20.0f; else base_scale = 18.0f; diff --git a/src/kernel/userland/taskman.c b/src/kernel/userland/taskman.c index 8657d02..2593c4b 100644 --- a/src/kernel/userland/taskman.c +++ b/src/kernel/userland/taskman.c @@ -106,20 +106,38 @@ static void draw_graph(int x, int y, int w, int h, int *data, uint32_t color, in } } -static void format_gib(uint64_t bytes, char *out) { - uint64_t gib_int = bytes / (1024 * 1024 * 1024); - uint64_t gib_frac = ((bytes % (1024 * 1024 * 1024)) * 100) / (1024 * 1024 * 1024); - - char s_int[16], s_frac[16]; - itoa((int)gib_int, s_int); - itoa((int)gib_frac, s_frac); - - out[0] = 0; - strcat(out, s_int); - strcat(out, "."); - if (gib_frac < 10) strcat(out, "0"); - strcat(out, s_frac); - strcat(out, " GiB"); +static void format_mem_smart(uint64_t bytes, char *out) { + if (bytes < 1024) { + itoa((int)bytes, out); + strcat(out, " B"); + } else if (bytes < 1024 * 1024) { + itoa((int)(bytes / 1024), out); + strcat(out, " KB"); + } else if (bytes < 1024 * 1024 * 1024) { + // Show MiB with two decimal places + uint64_t mib_int = bytes / (1024 * 1024); + uint64_t mib_frac = ((bytes % (1024 * 1024)) * 100) / (1024 * 1024); + char s_int[16], s_frac[16]; + itoa((int)mib_int, s_int); + itoa((int)mib_frac, s_frac); + strcpy(out, s_int); + strcat(out, "."); + if (mib_frac < 10) strcat(out, "0"); + strcat(out, s_frac); + strcat(out, " MiB"); + } else { + // Show GiB with two decimal places + uint64_t gib_int = bytes / (1024 * 1024 * 1024); + uint64_t gib_frac = ((bytes % (1024 * 1024 * 1024)) * 100) / (1024 * 1024 * 1024); + char s_int[16], s_frac[16]; + itoa((int)gib_int, s_int); + itoa((int)gib_frac, s_frac); + strcpy(out, s_int); + strcat(out, "."); + if (gib_frac < 10) strcat(out, "0"); + strcat(out, s_frac); + strcat(out, " GiB"); + } } static void draw_taskman(void) { @@ -161,9 +179,9 @@ static void draw_taskman(void) { draw_graph(205, 25, 185, 60, mem_history, COLOR_MEM, max_mem_kb); // Memory GiB usage - char s_used[24], s_total[24], mem_text[64]; - format_gib(used_mem_system, s_used); - format_gib(total_mem_system, s_total); + char s_used[32], s_total[32], mem_text[64]; + format_mem_smart(used_mem_system, s_used); + format_mem_smart(total_mem_system, s_total); mem_text[0] = 0; strcat(mem_text, s_used); strcat(mem_text, " / "); @@ -200,8 +218,7 @@ static void draw_taskman(void) { ui_draw_string(win_taskman, 65, ry + 6, name_disp, COLOR_DARK_TEXT); char m_str[32]; - itoa((int)(proc_list[i].used_memory / 1024), m_str); - strcat(m_str, " KB"); + format_mem_smart(proc_list[i].used_memory, m_str); ui_draw_string(win_taskman, 255, ry + 6, m_str, COLOR_DARK_TEXT); row++;