From 6b2ee875d467ce1b5f9313e36f16740cba024f26 Mon Sep 17 00:00:00 2001 From: Kevin Lange Date: Tue, 10 Jan 2012 19:54:05 -0600 Subject: [PATCH] Interrupts on/off is a semaphore --- kernel/include/system.h | 7 +++++-- kernel/mem/mem.c | 2 +- kernel/misc/kprintf.c | 27 +++++++++++++++------------ kernel/sys/syscall.c | 5 ++--- kernel/sys/system.c | 1 + kernel/sys/task.c | 4 ++-- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/kernel/include/system.h b/kernel/include/system.h index 436742db..0b1191d2 100644 --- a/kernel/include/system.h +++ b/kernel/include/system.h @@ -18,8 +18,11 @@ #define asm __asm__ #define volatile __volatile__ -#define IRQ_OFF asm volatile ("cli") -#define IRQ_ON asm volatile ("sti") +extern unsigned int __irq_sem; + +#define IRQ_OFF { asm volatile ("cli"); __irq_sem++; } +#define IRQ_ON { if (__irq_sem > 0) __irq_sem--; if (!__irq_sem) asm volatile ("sti"); } +#define IRQ_RES { __irq_sem = 0; asm volatile ("sti"); } #define PAUSE asm volatile ("hlt") #define STOP while (1) { PAUSE; } diff --git a/kernel/mem/mem.c b/kernel/mem/mem.c index 292110ea..ea698bfc 100644 --- a/kernel/mem/mem.c +++ b/kernel/mem/mem.c @@ -7,7 +7,7 @@ #include #include -extern uintptr_t end; +extern void *end; uintptr_t placement_pointer = (uintptr_t)&end; uintptr_t heap_end = (uintptr_t)NULL; diff --git a/kernel/misc/kprintf.c b/kernel/misc/kprintf.c index eec678db..503eaff9 100644 --- a/kernel/misc/kprintf.c +++ b/kernel/misc/kprintf.c @@ -169,12 +169,19 @@ void kgets_handler( char ch ) { + IRQ_OFF; + if (current_process != kgets_client) { + /* Switch page directories into the caller so we can write to its buffers */ + switch_page_directory(kgets_client->thread.page_directory); + } if (kgets_special == 1) { if (ch == 91) { kgets_special = 2; + IRQ_ON; return; } kgets_special = 0; + IRQ_ON; return; } if (kgets_special == 2) { @@ -228,6 +235,7 @@ kgets_handler( break; } kgets_special = 0; + IRQ_ON; return; } @@ -235,6 +243,7 @@ kgets_handler( /* Backspace */ if (kgets_collected != 0) { if (kgets_offset == 0) { + IRQ_ON; return; } /* Clear the previous character */ kwrite(0x08); @@ -243,10 +252,6 @@ kgets_handler( if (kgets_offset != kgets_collected) { int remaining = kgets_collected - kgets_offset; for (int i = 0; i < remaining; ++i) { - if (current_process != kgets_client) { - /* Switch page directories into the caller so we can write to its buffers */ - switch_page_directory(kgets_client->thread.page_directory); - } kwrite(kgets_buffer[kgets_offset + i]); kgets_buffer[kgets_offset + i - 1] = kgets_buffer[kgets_offset + i]; } @@ -261,14 +266,11 @@ kgets_handler( redraw_cursor(); } else { /* Erase the end of the buffer */ - if (current_process != kgets_client) { - /* Switch page directories into the caller so we can write to its buffers */ - switch_page_directory(kgets_client->thread.page_directory); - } kgets_buffer[--kgets_collected] = '\0'; kgets_offset--; } } + IRQ_ON; return; } else if (ch == '\x0c') { kprintf("\033[H\033[2J"); @@ -276,6 +278,7 @@ kgets_handler( kgets_redraw_func(); } kgets_redraw_buffer(); + IRQ_ON; return; } else if (ch == '\t' && kgets_tab_complete_func) { if (current_process != kgets_client) { @@ -285,9 +288,11 @@ kgets_handler( kgets_tab_complete_func(kgets_buffer); kgets_collected = strlen(kgets_buffer); kgets_offset = kgets_collected; + IRQ_ON; return; } else if (ch == 27) { kgets_special = 1; + IRQ_ON; return; } else if (ch == '\n') { /* Newline finishes off the kgets() */ @@ -299,10 +304,10 @@ kgets_handler( } kwrite('\n'); kgets_newline = 1; + IRQ_ON; return; } /* Add this character to the buffer. */ if (kgets_offset != kgets_collected) { - IRQ_OFF; if (current_process != kgets_client) { /* Switch page directories into the caller so we can write to its buffers */ switch_page_directory(kgets_client->thread.page_directory); @@ -324,11 +329,9 @@ kgets_handler( kwrite(68); } redraw_cursor(); - IRQ_ON; } else { kwrite(ch); if (kgets_collected < kgets_want) { - IRQ_OFF; if (current_process != kgets_client) { /* Switch page directories into the caller so we can write to its buffers */ switch_page_directory(kgets_client->thread.page_directory); @@ -336,9 +339,9 @@ kgets_handler( kgets_buffer[kgets_collected] = ch; kgets_buffer[++kgets_collected] = '\0'; kgets_offset++; - IRQ_ON; } } + IRQ_ON; } void kgets_redraw_buffer() { diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 5d131641..daceb12d 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -44,9 +44,8 @@ static int exit(int retval) { static int read(int fd, char * ptr, int len) { #ifdef SPECIAL_CASE_STDIO if (fd == 0) { - IRQ_ON; + IRQ_RES; kgets(ptr, len); - IRQ_OFF; if (strlen(ptr) < (uint32_t)len) { int j = strlen(ptr); ptr[j] = '\n'; @@ -182,7 +181,7 @@ static int kbd_mode(int mode) { static int kbd_get() { /* If we're requesting keyboard input, we better damn well be getting it */ - IRQ_ON; + IRQ_RES; char x = kbd_last; kbd_last = 0; return (int)x; diff --git a/kernel/sys/system.c b/kernel/sys/system.c index 963852a6..20fc130e 100644 --- a/kernel/sys/system.c +++ b/kernel/sys/system.c @@ -9,6 +9,7 @@ */ #include +unsigned int __irq_sem = 0; void spin_lock(uint8_t volatile * lock) { while(__sync_lock_test_and_set(lock, 0x01)) { diff --git a/kernel/sys/task.c b/kernel/sys/task.c index 3e6839db..ffd01bc7 100644 --- a/kernel/sys/task.c +++ b/kernel/sys/task.c @@ -186,7 +186,7 @@ fork() { make_process_ready(new_proc); /* Reenable interrupts */ - IRQ_ON; + IRQ_RES; /* Return the child PID */ return new_proc->id; @@ -239,7 +239,7 @@ switch_task() { reap_process(proc); } } - IRQ_ON; + IRQ_RES; return; }