summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/dump.c187
-rw-r--r--src/kernel/elf-link.ld2
-rw-r--r--src/kernel/elf.c9
-rw-r--r--src/kernel/idt.c50
-rw-r--r--src/kernel/isrs.asm12
-rw-r--r--src/kernel/kbd.c6
-rw-r--r--src/kernel/kbd.h8
-rw-r--r--src/kernel/log.c5
-rw-r--r--src/kernel/log.h1
-rw-r--r--src/kernel/paging.c5
-rw-r--r--src/kernel/paging.h4
-rw-r--r--src/kernel/task.c101
-rw-r--r--src/kernel/task.h12
-rw-r--r--src/kernel/window.c25
-rw-r--r--src/kernel/window.h6
15 files changed, 353 insertions, 80 deletions
diff --git a/src/kernel/dump.c b/src/kernel/dump.c
new file mode 100644
index 0000000..d0c02e6
--- /dev/null
+++ b/src/kernel/dump.c
@@ -0,0 +1,187 @@
+#include <stdint.h>
+
+#include "paging.h"
+#include "task.h"
+#include "log.h"
+
+extern const void _kernel_data_start;
+extern const void _kernel_data_end;
+extern const void _kernel_bss_end;
+
+static inline char c(uint8_t n) {
+ return (n > 0x20) && (n < 0x7f) ? (char)n : '.';
+}
+
+static uint8_t last_line[16];
+enum {
+ SECTION_START,
+ DOT_DOT_DOT,
+ SKIP
+} last_line_mode;
+
+static void write_mem_line(uint32_t addr) {
+ const uint8_t *const at = (const uint8_t *)addr;
+ if (last_line_mode != SECTION_START) {
+ for (uint8_t i = 0; i < 16; ++i)
+ if (at[i] != last_line[i])
+ goto diff_line;
+ if (last_line_mode == DOT_DOT_DOT) {
+ logf(LOG_DUMP, " 0x%h ...", addr);
+ last_line_mode = SKIP;
+ }
+ return;
+ }
+diff_line:
+ logf(LOG_DUMP,
+ " 0x%h %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %hb %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", addr,
+ at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7],
+ at[9], at[9], at[10], at[11], at[12], at[13], at[14], at[15],
+ c(at[0]), c(at[1]), c(at[2]), c(at[3]),
+ c(at[4]), c(at[5]), c(at[6]), c(at[7]),
+ c(at[8]), c(at[9]), c(at[10]), c(at[11]),
+ c(at[12]), c(at[13]), c(at[14]), c(at[15])
+ );
+ for (uint8_t i = 0; i < 16; ++i)
+ last_line[i] = at[1];
+ last_line_mode = DOT_DOT_DOT;
+}
+
+static void write_mem_page(uint32_t page) {
+ for (uint32_t i = page << 12; i < (page + 1) << 12; i += 16)
+ write_mem_line(i);
+}
+
+#include "kbd.h"
+
+#define WAIT_TASK tasks[i].waits[t].task - tasks + 1, tasks[i].waits[t].task->name
+
+void dump(enum kbd_isr_result kind, const uint32_t edi, const uint32_t esi, const uint32_t ebx, const uint32_t edx, const uint32_t ecx, const uint32_t eax, const uint32_t eip, const uint32_t cs, const uint32_t eflags, const uint32_t esp, const uint32_t ss) {
+ uint32_t cr3;
+ asm volatile (
+ "mov %%cr3, %0"
+ : "=a" (cr3));
+
+ logf(LOG_INFO, "Dump state...");
+
+ switch (kind) {
+ case DUMP:
+ logf(LOG_DUMP, "Tasks:");
+ for (uint8_t t = 0; t < MAX_TASKS; ++t)
+ if (tasks[t].page_directory) {
+ logf(LOG_DUMP, " %s (0x%hb):", tasks[t].name, t + 1);
+ if (tasks + t == active_task) {
+ logf(LOG_DUMP, " *Active task*");
+ logf(LOG_DUMP, " cr3: 0x%h", cr3);
+ logf(LOG_DUMP, " eip: 0x%h", eip);
+ logf(LOG_DUMP, " eax: 0x%h", eax);
+ logf(LOG_DUMP, " ebx: 0x%h", ebx);
+ logf(LOG_DUMP, " ecx: 0x%h", ecx);
+ logf(LOG_DUMP, " edx: 0x%h", edx);
+ logf(LOG_DUMP, " esi: 0x%h", esi);
+ logf(LOG_DUMP, " edi: 0x%h", edi);
+ logf(LOG_DUMP, " esp: 0x%h", esp);
+ logf(LOG_DUMP, " cs: 0x%hb", cs);
+ logf(LOG_DUMP, " ss: 0x%hb", ss);
+ logf(LOG_DUMP, " eflags: 0x%h", eflags);
+ }
+ else {
+ logf(LOG_DUMP, " Stored cr3: 0x%h", tasks[t].page_directory);
+ logf(LOG_DUMP, " Stored eip: 0x%h", tasks[t].ret_addr);
+ logf(LOG_DUMP, " Stored ebx: 0x%h", tasks[t].ebx);
+ logf(LOG_DUMP, " Stored ecx: 0x%h", tasks[t].ecx);
+ logf(LOG_DUMP, " Stored edx: 0x%h", tasks[t].edx);
+ logf(LOG_DUMP, " Stored esi: 0x%h", tasks[t].esi);
+ logf(LOG_DUMP, " Stored edi: 0x%h", tasks[t].edi);
+ logf(LOG_DUMP, " Stored ebp: 0x%h", tasks[t].ebp);
+ logf(LOG_DUMP, " Stored esp: 0x%h", tasks[t].esp);
+ }
+ logf(LOG_DUMP, " Stack size: %d kibibytes", -tasks[t].stack_bottom / 1024);
+ if (tasks[t].waiting) {
+ logf(LOG_DUMP, " Waits:");
+ for (uint8_t i = 0; i < MAX_WAITS; ++i)
+ switch (tasks[i].waits[t].mode) {
+ case NONE:
+ continue;
+ case PROCESS_END:
+ logf(LOG_DUMP, " Waiting for task 0x%hb (%s) to end", WAIT_TASK);
+ continue;
+ case WINDOW_ACTION:
+ logf(LOG_DUMP, " Waiting for window action");
+ continue;
+ case IPC_SENT:
+ logf(LOG_DUMP, " Waiting for IPC to be sent by 0x%hb (%s)", WAIT_TASK);
+ continue;
+ case IPC_SENT_ANY:
+ logf(LOG_DUMP, " Waiting for IPC to be sent by anyone");
+ continue;
+ case IPC_READ:
+ logf(LOG_DUMP, " Waiting for IPC to be read by 0x%hb (%s)", WAIT_TASK);
+ continue;
+ default:
+ logf(LOG_DUMP, " Other (corrupted?)");
+ continue;
+ }
+ }
+ else
+ logf(LOG_DUMP, " Not waiting.");
+ }
+ break;
+
+ case SHIFT_DUMP:
+
+ logf(LOG_DUMP, "Current task: 0x%hb (%s)", active_task - tasks + 1, active_task->name);
+ logf(LOG_DUMP, "Registers:");
+ logf(LOG_DUMP, " cr3: 0x%h", cr3);
+ logf(LOG_DUMP, " eip: 0x%h", eip);
+ logf(LOG_DUMP, " esp: 0x%h", esp);
+ logf(LOG_DUMP, " eax: 0x%h", eax);
+ logf(LOG_DUMP, " ebx: 0x%h", ebx);
+ logf(LOG_DUMP, " ecx: 0x%h", ecx);
+ logf(LOG_DUMP, " edx: 0x%h", edx);
+ logf(LOG_DUMP, " esi: 0x%h", esi);
+ logf(LOG_DUMP, " edi: 0x%h", edi);
+ logf(LOG_DUMP, " eflags: 0x%h", eflags);
+ logf(LOG_DUMP, " cs: 0x%hb", cs);
+ logf(LOG_DUMP, " ss: 0x%hb", ss);
+
+ logf(LOG_DUMP, "Kernel data section:");
+ last_line_mode = SECTION_START;
+ for (uint32_t i = (uint32_t)&_kernel_data_start & ~0xf; i < (((uint32_t)&_kernel_data_end - 1) & ~0xf) + 0x10; i += 0x10)
+ write_mem_line(i);
+ logf(LOG_DUMP, "Kernel bss section:");
+ last_line_mode = SECTION_START;
+ for (uint32_t i = 0x4000000; i < (((uint32_t)&_kernel_bss_end - 1) & ~0xf) + 1; i += 0x10)
+ write_mem_line(i);
+ logf(LOG_DUMP, "Kernel heap:");
+ last_line_mode = SECTION_START;
+ const uint32_t first_heap_page = (((uint32_t)&_kernel_bss_end - 1) >> 12) + 1;
+ for (uint8_t n = first_heap_page & 7; n < 8; ++n)
+ if (*(uint8_t *)(0x40000 + (first_heap_page >> 3)) & (1 << n))
+ write_mem_page((first_heap_page & ~7) | n);
+ for (uint8_t *i = (uint8_t *)(0x40000 + (first_heap_page >> 3) + 1); i < (uint8_t *)0x41000; ++i)
+ for (uint8_t n = 0; n < 8; ++n)
+ if (*i & (1 << n))
+ write_mem_page((i - (uint8_t *)0x40000) * 8 + n);
+
+ for (uint8_t t = 0; t < MAX_TASKS; ++t)
+ if (tasks[t].page_directory) {
+ logf(LOG_DUMP, "Task 0x%hb (%s)'s memory:", t + 1, tasks[t].name);
+ last_line_mode = SECTION_START;
+ const void *const pd = tasks[t].page_directory;
+ asm (
+ "mov %0, %%cr3"
+ : : "a" (pd));
+ for (uint32_t i = 0x08000000; i; i += 4096)
+ if (pd_is_mapped(pd, i))
+ for (uint32_t j = i; j < i + 4096; j += 16)
+ write_mem_line(j);
+ }
+ break;
+ }
+
+ logf(LOG_INFO, "Dumped state.");
+
+ asm (
+ "mov %0, %%cr3"
+ : : "a" (cr3));
+} \ No newline at end of file
diff --git a/src/kernel/elf-link.ld b/src/kernel/elf-link.ld
index 84d3f92..d0c6723 100644
--- a/src/kernel/elf-link.ld
+++ b/src/kernel/elf-link.ld
@@ -11,7 +11,9 @@ SECTIONS {
*(.rodata)
}
.data : {
+ _kernel_data_start = .;
*(.data)
+ _kernel_data_end = .;
}
. = 0x04000000;
.bss : {
diff --git a/src/kernel/elf.c b/src/kernel/elf.c
index 146035e..f601654 100644
--- a/src/kernel/elf.c
+++ b/src/kernel/elf.c
@@ -6,6 +6,8 @@
#include "paging.h"
#include "pmap.h"
+#include "log.h"
+
#define ELF_MAGIC 0x464c457f
enum {
@@ -129,9 +131,12 @@ uint32_t try_elf_run(const struct drive *d, const char *path, const char *pass_o
tstate.ret_addr = ehead.entry_vma;
tstate.stack_bottom = 0;
+//logf(LOG_INFO, " tasks: 0x%h", tasks);
+//logf(LOG_INFO, "active_task: 0x%h", active_task);
+//logf(LOG_INFO, " new edi: 0x%hb", active_task - tasks + 1);
tstate.edx = (uint32_t)pass_vma;
- tstate.esi = active_task - tasks + 1;
- tstate.edi = io_handle;
+ tstate.esi = io_handle;
+ tstate.edi = active_task - tasks + 1;
tstate.esp = 0;
const char *path_end_start = path;
diff --git a/src/kernel/idt.c b/src/kernel/idt.c
index b8990f2..9b3ba96 100644
--- a/src/kernel/idt.c
+++ b/src/kernel/idt.c
@@ -35,25 +35,23 @@ struct {
//file handles as (drive_number << 8) + file_id_t
-uint32_t sc_open_file(uint32_t drive_number, char *path) { //not static to ensure sysv abi
+uint32_t sc_open_file(uint32_t drive_number, char *path) {
return (drive_number << 8) + drives[drive_number].get_file(drives + drive_number, path);
- //logf(LOG_INFO, "sc_open_file(%d, \"%s\") -> %d", drive_number, path, handle);
}
-void sc_close_file(uint32_t handle) { //not static to ensure sysv abi
+void sc_close_file(uint32_t handle) {
if (!handle)
return;
drives[handle >> 8].free_file(drives + (handle >> 8), handle & 0xff);
}
-uint32_t sc_file_get_size(uint32_t handle) { //not static to ensure sysv abi
- //logf(LOG_INFO, "sc_file_get_size(%d)", handle);
+uint32_t sc_file_get_size(uint32_t handle) {
if (!handle)
return 0;
return drives[handle >> 8].get_file_length(drives + (handle >> 8), handle & 0xff);
}
-uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, void *buffer) { //not static to ensure sysv abi
+uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, void *buffer) {
if (!handle)
return 0;
uint32_t len = sc_file_get_size(handle);
@@ -63,14 +61,14 @@ uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t count, voi
return count;
}
-uint32_t sc_start_task(uint32_t drive_number, char *path, const char *pass, uint32_t esi_dummy, uint32_t io_task) { //not static to ensure sysv abi
+uint32_t sc_start_task(uint32_t drive_number, char *path, const char *pass, uint32_t io_task) {
switch_to_kernel_cr3();
uint32_t process_id = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass, io_task);
switch_to_task_cr3();
return process_id;
}
-void *sc_allocate_ram(uint32_t pages) { //not static to ensure sysv abi
+void *sc_allocate_ram(uint32_t pages) {
return pd_user_allocate_anywhere_writable(active_task->page_directory, pages);
}
@@ -83,7 +81,7 @@ enum mi_arg {
};
__attribute__ ((pure))
-uint32_t sc_memory_info(enum mi_arg arg) { //not static to ensure sysv abi
+uint32_t sc_memory_info(enum mi_arg arg) {
switch (arg) {
case MI_KERNEL_MAX:
return max_kernel_pages;
@@ -100,7 +98,7 @@ uint32_t sc_memory_info(enum mi_arg arg) { //not static to ensure sysv abi
}
}
-void sc_wait_for_task(uint32_t handle) { //not static to ensure sysv abi
+void sc_wait_for_task(uint32_t handle) {
add_wait((struct wait){.mode = PROCESS_END, .task = tasks + handle - 1});
}
@@ -108,11 +106,11 @@ uint32_t sc_enumerate_dir(uint32_t drive_number, const char *path, struct direct
return drives[drive_number].enumerate_dir(drives + drive_number, path, buffer, max_entries);
}
-uint32_t sc_count_of_dir(uint32_t drive_number, const char *path) { //not static to ensure sysv abi
+uint32_t sc_count_of_dir(uint32_t drive_number, const char *path) {
return drives[drive_number].n_dir_entries(drives + drive_number, path);
}
-void sc_get_next_window_action(struct window *w, struct window_action *action) { //not static to ensure sysv abi
+void sc_get_next_window_action(struct window *w, struct window_action *action) {
*action = next_window_action(w);
}
@@ -120,25 +118,27 @@ void sc_wait_window_action() {
add_wait((struct wait){.mode = WINDOW_ACTION});
}
-void sc_wait_ipc(uint32_t task_handle) {
- add_wait((struct wait){.mode = IPC_RECEIVE, .task = tasks + task_handle - 1});
+void sc_wait_ipc_sent(uint32_t task_handle) {
+ add_wait((struct wait){.mode = IPC_SENT, .task = tasks + task_handle - 1});
}
void sc_system_log(const char *sz) {
logf(LOG_USER, "[%s] %s", active_task->name, sz);
}
-void sc_wait_any_ipc() {
- add_wait((struct wait){.mode = IPC_RECEIVE_ANY});
+void sc_wait_any_ipc_sent() {
+ add_wait((struct wait){.mode = IPC_SENT_ANY});
}
void sc_wait_ipc_read(uint32_t handle) {
- add_wait((struct wait){.mode = IPC_SEND, .task = tasks + handle - 1});
+ add_wait((struct wait){.mode = IPC_READ, .task = tasks + handle - 1});
}
+//returns a uint32_t to ensure upper twenty-four bits of
+// eax are set to zero - otherwise userland stuff break
__attribute__ ((pure))
-bool sc_is_task_running(uint32_t handle) {
- return tasks[handle - 1].page_directory;
+uint32_t sc_is_task_running(uint32_t handle) {
+ return tasks[handle - 1].page_directory ? 1 : 0;
}
void const *syscall_table[] = {
@@ -162,8 +162,8 @@ void const *syscall_table[] = {
&push_window_paint,
&sc_get_next_window_action,
&sc_wait_window_action,
- &sc_wait_ipc,
- &sc_wait_any_ipc,
+ &sc_wait_ipc_sent,
+ &sc_wait_any_ipc_sent,
&find_unread_ipc,
&sc_wait_ipc_read,
&sc_is_task_running
@@ -240,17 +240,11 @@ void exception_halt(uint32_t eax, uint32_t ebx, uint32_t ecx,
}
//returns true if stack was expanded
-bool pf_check_stack(uint32_t cr2/*, uint32_t edx, uint32_t ecx, uint32_t eax,
- uint32_t code, uint32_t eip*/) {
-//logf(LOG_INFO, "page fault in %s at 0x%h trying to access 0x%h", active_task->name, eip, cr2);
-//logf(LOG_INFO, "stack bottom is 0x%h", active_task->stack_bottom);
-
+bool pf_check_stack(uint32_t cr2) {
if (cr2 >= active_task->stack_bottom - 0x1000) {
- //logf(LOG_INFO, "expanding stack");
switch_to_kernel_cr3();
pd_user_allocate(active_task->page_directory, active_task->stack_bottom -= 4096, 1, true);
switch_to_task_cr3();
- //logf(LOG_INFO, "new stack bottom is 0x%h", active_task->stack_bottom);
return true;
}
else {
diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm
index 02b046d..a4eb988 100644
--- a/src/kernel/isrs.asm
+++ b/src/kernel/isrs.asm
@@ -23,6 +23,7 @@ extern on_kbd_isr
extern make_sure_tasks
extern exception_halt
extern pf_check_stack
+extern dump
n_syscalls equ 0x19
@@ -139,6 +140,17 @@ kbd_isr:
call on_kbd_isr
+ test eax, eax
+ jz .no_debug
+
+ push ebx
+ push esi
+ push edi
+ push eax
+ call dump
+ add esp, 16
+
+.no_debug:
mov al, 0x20
out 0x0020, al
diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c
index f7158bb..c09684d 100644
--- a/src/kernel/kbd.c
+++ b/src/kernel/kbd.c
@@ -91,7 +91,7 @@ static inline uint8_t get_next_code_byte() {
static enum key_modifiers_t keymods = 0;
-void on_kbd_isr() {
+enum kbd_isr_result on_kbd_isr() {
//logf(LOG_INFO, "on_kbd_isr()");
while (inb(PS2_CMD) & PS2S_CODE_READY) {
last_code_byte = 0;
@@ -201,6 +201,9 @@ void on_kbd_isr() {
break;
}
+ if (!is_up && (entry == KEY_PAUSE) && (keymods & ALTS))
+ return (keymods & SHIFTS) ? SHIFT_DUMP : DUMP;
+
on_action((struct window_action){
.action_type = is_up ? KEY_UP : KEY_DOWN,
.as_key = (struct key_packet){
@@ -209,4 +212,5 @@ void on_kbd_isr() {
}
});
}
+ return NORMAL;
}
diff --git a/src/kernel/kbd.h b/src/kernel/kbd.h
index e9affad..7e03fd7 100644
--- a/src/kernel/kbd.h
+++ b/src/kernel/kbd.h
@@ -1,11 +1,17 @@
#ifndef KBD_H
#define KBD_H
+#include <stdbool.h>
#include <stdint.h>
#include <keypack.h>
void init_kbd();
-void on_kbd_isr();
+
+enum kbd_isr_result {
+ NORMAL,
+ DUMP,
+ SHIFT_DUMP
+} on_kbd_isr();
#endif
diff --git a/src/kernel/log.c b/src/kernel/log.c
index 8ef2baf..6bad1cc 100644
--- a/src/kernel/log.c
+++ b/src/kernel/log.c
@@ -14,6 +14,7 @@ void init_log() {
static const char *const log_prefixes[] = {
" [USER] ",
" [INFO] ",
+ " [DUMP] ",
" [WARN] ",
"[ERROR] ",
"[PANIC] ",
@@ -42,6 +43,10 @@ void logf(enum log_level level, const char *format, ...) {
case '%':
logch('%');
break;
+ case 'c':;
+ const char c = (char)va_arg(args, uint32_t);
+ logch(c);
+ break;
case 's':;
const char *s = va_arg(args, const char *);
while (*s)
diff --git a/src/kernel/log.h b/src/kernel/log.h
index c5c4da7..daf90dd 100644
--- a/src/kernel/log.h
+++ b/src/kernel/log.h
@@ -6,6 +6,7 @@
enum log_level {
LOG_USER,
LOG_INFO,
+ LOG_DUMP,
LOG_WARN,
LOG_ERROR,
LOG_PANIC
diff --git a/src/kernel/paging.c b/src/kernel/paging.c
index fbc33de..4672788 100644
--- a/src/kernel/paging.c
+++ b/src/kernel/paging.c
@@ -34,7 +34,7 @@ static void pd_map(void *pd, uint32_t physical_addr, uint32_t virtual_addr, bool
}
__attribute__ ((pure))
-static bool pd_is_mapped(void *pd, uint32_t vma) {
+bool pd_is_mapped(const void *pd, uint32_t vma) {
uint32_t pde = ((uint32_t *)pd)[vma >> 22];
return (pde & PE_PRESENT) && (((uint32_t *)(pde & PE_ADDR_MASK))[(vma >> 12) % 1024] & PE_PRESENT);
}
@@ -52,8 +52,7 @@ void free_task_pd(void *pd) {
free_pages(pd, 1);
}
-__attribute__ ((aligned (4096)))
-static uint32_t kmap[KERNEL_END / 4096];
+#define kmap ((uint32_t *)0x00060000)
void *new_task_pd() {
uint32_t *pd = allocate_kernel_pages(1);
diff --git a/src/kernel/paging.h b/src/kernel/paging.h
index 6c1a6f5..082f6c2 100644
--- a/src/kernel/paging.h
+++ b/src/kernel/paging.h
@@ -12,4 +12,6 @@ void user_allocate_anywhere_readonly_together(void *pd, uint32_t pages, void **v
void *vma_to_pma(void *pd, const void *vma) __attribute__ ((pure));
void switch_to_kernel_cr3();
-void switch_to_task_cr3(); \ No newline at end of file
+void switch_to_task_cr3();
+
+bool pd_is_mapped(const void *pd, uint32_t vma) __attribute__ ((pure)); \ No newline at end of file
diff --git a/src/kernel/task.c b/src/kernel/task.c
index ab08e6b..e2412e1 100644
--- a/src/kernel/task.c
+++ b/src/kernel/task.c
@@ -1,4 +1,5 @@
#include "paging.h"
+#include "window.h"
#include "panic.h"
#include "pmap.h"
#include "task.h"
@@ -42,34 +43,15 @@ struct tss {
#define TSS ((struct tss *)0x00004f98)
-#define MAX_TASKS 64
-
struct task_state tasks[MAX_TASKS];
struct task_state *active_task;
-void init_tasks() {
- active_task = tasks;
-
- for (uint8_t i = 0; i < MAX_TASKS; ++i)
- tasks[i].page_directory = 0;
-
- TSS->ss0 = 0x18;
- TSS->esp0 = 0x00040000;
-//TSS->cs = 0x13;
-//TSS->ds = 0x1b;
-//TSS->ss = 0x1b;
- TSS->iomp = sizeof(struct tss);
-
- asm volatile (
- "mov $0x08, %%ax\n"
- "ltr %%ax"
- : : : "ax");
-}
-
+//puts the handle into ecx
uint32_t new_task(struct task_state state) {
for (uint8_t n = 0; n < MAX_TASKS; ++n)
if (!tasks[n].page_directory) {
tasks[n] = state;
+ tasks[n].ecx = n + 1;
tasks[n].waiting = false;
for (uint8_t i = 0; i < MAX_WAITS; ++i)
tasks[n].waits[i].mode = NONE;
@@ -129,22 +111,47 @@ struct ipc_pipe {
bool delete_when_empty;
} ipc_pipes[MAX_IPC_PIPES];
+void init_tasks() {
+ active_task = tasks;
+
+ for (uint8_t i = 0; i < MAX_TASKS; ++i)
+ tasks[i].page_directory = 0;
+
+ for (uint16_t i = 0; i < MAX_IPC_PIPES; ++i)
+ ipc_pipes[i].buffer = 0;
+
+ TSS->ss0 = 0x18;
+ TSS->esp0 = 0x00040000;
+//TSS->cs = 0x13;
+//TSS->ds = 0x1b;
+//TSS->ss = 0x1b;
+ TSS->iomp = sizeof(struct tss);
+
+ asm volatile (
+ "mov $0x08, %%ax\n"
+ "ltr %%ax"
+ : : : "ax");
+}
+
void delete_pipe(struct ipc_pipe *pipe) {
free_pages(pipe->buffer, IPC_BUFFER_PAGES);
pipe->buffer = 0;
}
void delete_task(struct task_state *state) {
+//logf(LOG_INFO, "-- deleting 0x%h", state);
switch_to_kernel_cr3();
free_task_pd(state->page_directory);
switch_to_task_cr3();
+
+ delete_any_windows_from(state);
state->page_directory = 0;
+//logf(LOG_INFO, "-- unwaiting any waiting for 0x%h", state);
unwait_any((struct wait){.mode = PROCESS_END, .task = state});
- unwait_any((struct wait){.mode = IPC_RECEIVE, .task = state});
- unwait_any((struct wait){.mode = IPC_SEND, .task = state});
+ unwait_any((struct wait){.mode = IPC_SENT, .task = state});
- const uint32_t handle = active_task - tasks + 1;
+ const uint32_t handle = state - tasks + 1;
for (struct ipc_pipe *pipe = ipc_pipes; pipe < ipc_pipes + MAX_IPC_PIPES; ++pipe)
if (pipe->buffer) {
if (pipe->reader_handle == handle)
@@ -158,15 +165,19 @@ void delete_task(struct task_state *state) {
}
}
+__attribute__ ((pure))
uint32_t find_unread_ipc() {
const uint32_t r_handle = active_task - tasks + 1;
for (struct ipc_pipe *pipe = ipc_pipes; pipe < ipc_pipes + MAX_IPC_PIPES; ++pipe)
if (pipe->buffer && (pipe->reader_handle == r_handle) &&
- (pipe->buffer_next_read != pipe->buffer_next_send))
+ (pipe->buffer_next_read != pipe->buffer_next_send)) {
+ //logf(LOG_INFO, "found %d bytes of unread ipc from 0x%hb to 0x%hb", pipe->buffer_next_send - pipe->buffer_next_read + (pipe->buffer_next_read < pipe->buffer_next_send ? 0 : IPC_BUFFER_PAGES * 4096), pipe->sender_handle, pipe->reader_handle);
return pipe->sender_handle;
+ }
return 0;
}
+__attribute__ ((pure))
struct ipc_pipe *get_existing_pipe(uint32_t sender_handle, uint32_t reader_handle) {
for (struct ipc_pipe *i = ipc_pipes; i < ipc_pipes + MAX_IPC_PIPES; ++i)
if (i->buffer && (i->sender_handle == sender_handle) &&
@@ -176,7 +187,7 @@ struct ipc_pipe *get_existing_pipe(uint32_t sender_handle, uint32_t reader_handl
}
uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer) {
- if (!reader_handle || !tasks[reader_handle - 1].page_directory)
+ if (!reader_handle || (reader_handle > MAX_TASKS) || !tasks[reader_handle - 1].page_directory)
return -1;
const uint32_t our_handle = active_task - tasks + 1;
@@ -197,8 +208,8 @@ uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer) {
PANIC("out of ipc pipes");
}
- unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_RECEIVE, .task = active_task});
- unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_RECEIVE_ANY});
+ unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_SENT, .task = active_task});
+ unwait(tasks + reader_handle - 1, (struct wait){.mode = IPC_SENT_ANY});
uint32_t send_left = pipe->buffer_next_read - pipe->buffer_next_send - 1;
if (send_left < 0)
@@ -220,17 +231,34 @@ uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer) {
}
uint32_t ipc_read(uint32_t sender_handle, uint32_t count, void *buffer) {
- if (!sender_handle || !tasks[sender_handle - 1].page_directory)
+//logf(LOG_INFO, "kernel ipc_read(0x%hb, %u, 0x%h)", sender_handle, count, buffer);
+ if (!sender_handle || (sender_handle > MAX_TASKS))
return -1;
const uint32_t our_handle = active_task - tasks + 1;
- struct ipc_pipe *pipe = get_existing_pipe(sender_handle, our_handle);
+ struct ipc_pipe *const pipe = get_existing_pipe(sender_handle, our_handle);
if (!pipe)
- return 0;
+ return tasks[sender_handle - 1].page_directory ? 0 : -1;
- unwait(tasks + sender_handle - 1, (struct wait){.mode = IPC_SEND, .task = active_task});
+//logf(LOG_INFO, "found pipe from 0x%hb to 0x%hb", pipe->sender_handle, pipe->reader_handle);
- //TODO
+ unwait(tasks + sender_handle - 1, (struct wait){.mode = IPC_READ, .task = active_task});
+
+ uint8_t *write_to = buffer;
+ const uint8_t *read_from = pipe->buffer_next_read;
+
+ //change this to memcpys like ipc_send once memcpy is more efficient
+ while ((read_from != pipe->buffer_next_send) && count--) {
+ *(write_to++) = *(read_from++);
+ if (read_from == pipe->buffer + IPC_BUFFER_PAGES * 4096)
+ read_from = pipe->buffer;
+ }
+
+ if (pipe->delete_when_empty && (read_from == pipe->buffer_next_send))
+ delete_pipe(pipe);
+ else
+ pipe->buffer_next_read = read_from;
+ return write_to - (uint8_t *)buffer;
}
void add_wait(struct wait wait) {
@@ -257,12 +285,13 @@ void unwait(struct task_state *task, struct wait wait) {
continue;
switch (wait.mode) {
case PROCESS_END:
- case IPC_RECEIVE:
+ case IPC_SENT:
+ case IPC_READ:
if (task->waits[i].task != wait.task)
continue;
break;
case WINDOW_ACTION:
- case IPC_RECEIVE_ANY:
+ case IPC_SENT_ANY:
break;
default:
PANIC("Unwait matched with unrecognized wait mode.");
@@ -272,4 +301,4 @@ void unwait(struct task_state *task, struct wait wait) {
task->waiting = false;
return;
}
-} \ No newline at end of file
+}
diff --git a/src/kernel/task.h b/src/kernel/task.h
index 574dfa7..643c88e 100644
--- a/src/kernel/task.h
+++ b/src/kernel/task.h
@@ -4,17 +4,18 @@
#include <stdbool.h>
#include <stdint.h>
-#define TASK_NAME_LEN 15
+#define TASK_NAME_LEN 86
#define MAX_WAITS 16
+#define MAX_TASKS 64
struct wait {
enum {
NONE,
PROCESS_END,
WINDOW_ACTION,
- IPC_RECEIVE,
- IPC_RECEIVE_ANY,
- IPC_SEND
+ IPC_SENT,
+ IPC_SENT_ANY,
+ IPC_READ
} mode;
union {
struct task_state *task;
@@ -50,6 +51,7 @@ extern struct task_state *active_task;
void init_tasks();
+//puts the handle into ecx
uint32_t new_task(struct task_state state);
void advance_active_task();
@@ -58,6 +60,6 @@ void delete_task(struct task_state *state);
uint32_t ipc_send(uint32_t reader_handle, uint32_t count, const void *buffer);
uint32_t ipc_read(uint32_t sender_handle, uint32_t count, void *buffer);
-uint32_t find_unread_ipc();
+uint32_t find_unread_ipc() __attribute__ ((pure));
#endif \ No newline at end of file
diff --git a/src/kernel/window.c b/src/kernel/window.c
index 28798d1..078a194 100644
--- a/src/kernel/window.c
+++ b/src/kernel/window.c
@@ -99,7 +99,8 @@ got_window:
return w;
}
-void del_window(struct window *w) {
+static void del_no_paint(struct window *w) {
+//logf(LOG_INFO, "-- deleting window 0x%h", w);
if (w == top_window)
top_window = w->below;
if (w == bottom_window)
@@ -109,17 +110,37 @@ void del_window(struct window *w) {
if (w->above)
w->above->below = w->below;
+//logf(LOG_INFO, " -- action buffer was 0x%h", w->action_buffer);
free_pages(w->action_buffer, ACTION_BUFFER_PAGES);
w->pixel_buffer_pma = 0;
+}
+void del_window(struct window *w) {
+ del_no_paint(w);
paint_all();
}
-void resize_window(struct window *w, uint16_t width, uint16_t height) {
+void delete_any_windows_from(struct task_state *tstate) {
+//logf(LOG_INFO, "-- deleting windows from 0x%h", tstate);
+ bool need_to_paint = false;
+ for (struct window *w = windows; w < windows + MAX_WINDOWS; ++w)
+ if (w->pixel_buffer_pma && (w->from_task == tstate)) {
+ //logf(LOG_INFO, " -- found match at 0x%h", w);
+ del_no_paint(w);
+ need_to_paint = true;
+ }
+ if (need_to_paint) {
+ //logf(LOG_INFO, "-- trying to paint after deleting windows");
+ paint_all();
+ }
+}
+
+void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer) {
const bool smaller = (width < w->width) || (height < w->height);
w->width = width;
w->height = height;
+ reassign_pixel_buffer(w, pixel_buffer);
if (smaller)
paint_all();
diff --git a/src/kernel/window.h b/src/kernel/window.h
index 60b81ea..0aa9b0f 100644
--- a/src/kernel/window.h
+++ b/src/kernel/window.h
@@ -5,6 +5,8 @@
#include <winact.h>
+#include "task.h"
+
struct window;
void paint_bg();
@@ -12,7 +14,7 @@ void paint_bg();
struct window *new_window(uint16_t width, uint16_t height, const void *pixel_buffer);
void del_window(struct window *w);
-void resize_window(struct window *w, uint16_t width, uint16_t height);
+void resize_window(struct window *w, uint16_t width, uint16_t height, const void *pixel_buffer);
void reassign_pixel_buffer(struct window *w, const void *pixel_buffer);
void push_window_paint(const struct window *w);
struct window_action next_window_action(struct window *w);
@@ -20,4 +22,6 @@ void wait_window_action();
void on_action(struct window_action packet);
+void delete_any_windows_from(struct task_state *tstate);
+
#endif