diff options
author | Alex Auvolat <alex@adnab.me> | 2015-03-11 16:22:40 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2015-03-11 16:22:40 +0100 |
commit | 9b9ef5a2c0ec8e66c7da24c4229d89a90a10e914 (patch) | |
tree | 471cb88f003eb58ce84342f2e7ab7effda04ce2d | |
parent | a7ff74cdf2835625282491242ede57b05ceaa782 (diff) | |
download | kogata-9b9ef5a2c0ec8e66c7da24c4229d89a90a10e914.tar.gz kogata-9b9ef5a2c0ec8e66c7da24c4229d89a90a10e914.zip |
Bugfixing in progress. Strange bug: wait_on adds to waiters but later not in waiters.
-rw-r--r-- | src/common/include/proto/keyboard.h | 40 | ||||
-rw-r--r-- | src/common/libalgo/hashtbl.c | 4 | ||||
-rw-r--r-- | src/kernel/core/idt.c | 17 | ||||
-rw-r--r-- | src/kernel/core/thread.c | 41 | ||||
-rw-r--r-- | src/kernel/core/worker.c | 27 | ||||
-rw-r--r-- | src/kernel/dev/pckbd.c | 2 | ||||
-rw-r--r-- | src/kernel/include/thread.h | 2 | ||||
-rw-r--r-- | src/kernel/user/syscall.c | 6 | ||||
-rw-r--r-- | src/lib/include/gip.h | 3 | ||||
-rw-r--r-- | src/lib/libkogata/gip.c | 4 | ||||
-rw-r--r-- | src/lib/libkogata/mainloop.c | 4 | ||||
-rw-r--r-- | src/sysbin/giosrv/main.c | 17 | ||||
-rw-r--r-- | src/sysbin/login/main.c | 10 |
13 files changed, 127 insertions, 50 deletions
diff --git a/src/common/include/proto/keyboard.h b/src/common/include/proto/keyboard.h index 044946d..8d9543f 100644 --- a/src/common/include/proto/keyboard.h +++ b/src/common/include/proto/keyboard.h @@ -14,7 +14,45 @@ typedef struct { #define IOCTL_KBD_SET_LEDS 10 #define KBD_LED_SCROLLLOCK 1 -#define KBD_LED_NUMLOCK 1 +#define KBD_LED_NUMLOCK 2 #define KBD_LED_CAPSLOCK 4 +#define KBD_CODE_ESC 1 +#define KBD_CODE_RETURN 28 +#define KBD_CODE_BKSP 14 +#define KBD_CODE_UP 200 +#define KBD_CODE_DOWN 208 +#define KBD_CODE_LEFT 203 +#define KBD_CODE_RIGHT 205 +#define KBD_CODE_HOME 199 +#define KBD_CODE_END 207 +#define KBD_CODE_PGUP 201 +#define KBD_CODE_PGDOWN 209 + +#define KBD_CODE_LSHIFT 42 +#define KBD_CODE_RSHIFT 54 +#define KBD_CODE_CAPSLOCK 58 +#define KBD_CODE_LCTRL 29 +#define KBD_CODE_RCTRL 157 +#define KBD_CODE_LALT 56 +#define KBD_CODE_RALT 184 +#define KBD_CODE_SUPER 219 +#define KBD_CODE_MENU 221 +#define KBD_CODE_TAB 15 +#define KBD_CODE_INS 210 +#define KBD_CODE_DEL 211 + +#define KBD_CODE_F1 59 +#define KBD_CODE_F2 60 +#define KBD_CODE_F3 61 +#define KBD_CODE_F4 62 +#define KBD_CODE_F5 63 +#define KBD_CODE_F6 64 +#define KBD_CODE_F7 65 +#define KBD_CODE_F8 66 +#define KBD_CODE_F9 67 +#define KBD_CODE_F10 68 +#define KBD_CODE_F11 87 +#define KBD_CODE_F12 88 + /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/common/libalgo/hashtbl.c b/src/common/libalgo/hashtbl.c index f34c6d4..7192bd4 100644 --- a/src/common/libalgo/hashtbl.c +++ b/src/common/libalgo/hashtbl.c @@ -90,11 +90,11 @@ static void hashtbl_check_size(hashtbl_t *ht) { } bool hashtbl_add(hashtbl_t *ht, void* key, void* v) { - size_t slot = SLOT_OF_HASH(ht->hf(key), ht->size); - hashtbl_item_t *i = (hashtbl_item_t*)malloc(sizeof(hashtbl_item_t)); if (i == 0) return false; // OOM + size_t slot = SLOT_OF_HASH(ht->hf(key), ht->size); + // make sure item is not already present hashtbl_remove(ht, key); diff --git a/src/kernel/core/idt.c b/src/kernel/core/idt.c index f99460f..f3dd63b 100644 --- a/src/kernel/core/idt.c +++ b/src/kernel/core/idt.c @@ -91,6 +91,7 @@ static isr_handler_t ex_handlers[32] = {0}; /* Called in interrupt.s when an exception fires (interrupt 0 to 31) */ void idt_ex_handler(registers_t *regs) { + dbg_printf("Ex handler: %d\n", regs->int_no); if (ex_handlers[regs->int_no] != 0) { ex_handlers[regs->int_no](regs); } else { @@ -114,21 +115,21 @@ void idt_ex_handler(registers_t *regs) { void idt_irq_handler(registers_t *regs) { int st = enter_critical(CL_EXCL); // if someone tries to yield(), an assert will fail + dbg_printf("irq%d.", regs->err_code); + if (regs->err_code > 7) { outb(0xA0, 0x20); } outb(0x20, 0x20); - if (regs->err_code == 0) { - irq0_handler(regs, st); - } else { - /*dbg_printf("irq%d.", regs->err_code);*/ + if (irq_handlers[regs->err_code] != 0) { + irq_handlers[regs->err_code](regs); + } - if (irq_handlers[regs->err_code] != 0) { - irq_handlers[regs->err_code](regs); - } + exit_critical(st); - exit_critical(st); + if (regs->err_code == 0) { + threading_irq0_handler(); } // maybe exit diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 4e15c0e..ed2c185 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -19,7 +19,6 @@ void resume_context(saved_context_t *ctx); thread_t *current_thread = 0; static hashtbl_t *waiters = 0; // threads waiting on a ressource -STATIC_MUTEX(waiters_mutex); // ====================== // // THE PROGRAMMABLE TIMER // @@ -44,6 +43,8 @@ void set_pit_frequency(uint32_t freq) { int enter_critical(int level) { asm volatile("cli"); + /*dbg_printf(" >%d< ", level);*/ + if (current_thread == 0) return CL_EXCL; int prev_level = current_thread->critical_level; @@ -57,6 +58,8 @@ int enter_critical(int level) { void exit_critical(int prev_level) { asm volatile("cli"); + /*dbg_printf(" <%d> ", prev_level);*/ + if (current_thread == 0) return; if (prev_level < current_thread->critical_level) current_thread->critical_level = prev_level; @@ -117,6 +120,8 @@ void run_scheduler() { // At this point, interrupts are disabled // This function is expected NEVER TO RETURN + thread_t *prev_thread = current_thread; + if (current_thread != 0 && current_thread->state == T_STATE_RUNNING) { current_thread->last_ran = get_kernel_time(); if (current_thread->proc) current_thread->proc->last_ran = current_thread->last_ran; @@ -124,7 +129,7 @@ void run_scheduler() { } current_thread = dequeue_thread(); - /*dbg_printf("[0x%p]\n", current_thread);*/ + if (current_thread != prev_thread) dbg_printf("[0x%p]\n", current_thread); if (current_thread != 0) { thread_t *ptr = current_thread; @@ -221,11 +226,10 @@ void delete_thread(thread_t *t) { // SETUP CODE // // ========== // -void irq0_handler(registers_t *regs, int crit_level) { +void irq0_handler(registers_t *regs) { notify_time_pass(1000000 / TASK_SWITCH_FREQUENCY); - - exit_critical(crit_level); - +} +void threading_irq0_handler() { if (current_thread != 0 && current_thread->critical_level == CL_USER) { save_context_and_enter_scheduler(¤t_thread->ctx); } @@ -235,7 +239,7 @@ void threading_setup(entry_t cont, void* arg) { ASSERT(waiters != 0); set_pit_frequency(TASK_SWITCH_FREQUENCY); - // no need to set irq0 handler + idt_set_irq_handler(IRQ0, &irq0_handler); thread_t *t = new_thread(cont, arg); ASSERT(t != 0); @@ -265,7 +269,8 @@ void start_thread(thread_t *t) { } void yield() { - ASSERT(current_thread != 0 && current_thread->critical_level != CL_EXCL); + ASSERT(current_thread != 0); + ASSERT(current_thread->critical_level != CL_EXCL); save_context_and_enter_scheduler(¤t_thread->ctx); } @@ -275,10 +280,11 @@ bool wait_on(void* x) { } bool wait_on_many(void** x, size_t n) { - ASSERT(current_thread != 0 && current_thread->critical_level != CL_EXCL); + ASSERT(current_thread != 0); + ASSERT(current_thread->critical_level != CL_EXCL); ASSERT(n > 0); - mutex_lock(&waiters_mutex); + int st = enter_critical(CL_NOINT); // ---- Check we can wait on all the requested objects bool ok = true; @@ -291,34 +297,34 @@ bool wait_on_many(void** x, size_t n) { } } else if (prev_th != (void*)1) { ok = false; + break; } } if (!ok) { - mutex_unlock(&waiters_mutex); + exit_critical(st); return false; } // ---- Set ourselves as the waiting thread for all the requested objets - int st = enter_critical(CL_NOSWITCH); + dbg_printf("Wait on many: "); for (size_t i = 0; i < n; i++) { ASSERT(hashtbl_change(waiters, x[i], current_thread)); + dbg_printf("0x%p (0x%p) ", x[i], hashtbl_find(waiters, x[i])); } + dbg_printf("\n"); // ---- Go to sleep - mutex_unlock(&waiters_mutex); current_thread->state = T_STATE_PAUSED; save_context_and_enter_scheduler(¤t_thread->ctx); // ---- Remove ourselves from the list - mutex_lock(&waiters_mutex); for (size_t i = 0; i < n; i++) { ASSERT(hashtbl_change(waiters, x[i], (void*)1)); } - mutex_unlock(&waiters_mutex); exit_critical(st); // ---- Check that we weren't waked up because of a kill request @@ -368,15 +374,17 @@ void exit() { } bool resume_on(void* x) { + thread_t *thread; bool ret = false; - mutex_lock(&waiters_mutex); int st = enter_critical(CL_NOINT); thread = hashtbl_find(waiters, x); + dbg_printf("Resume on 0x%p : 0x%p\n", x, thread); + if (thread != 0 && thread != (void*)1) { if (thread->state == T_STATE_PAUSED) { thread->state = T_STATE_RUNNING; @@ -387,7 +395,6 @@ bool resume_on(void* x) { } } - mutex_unlock(&waiters_mutex); exit_critical(st); return ret; diff --git a/src/kernel/core/worker.c b/src/kernel/core/worker.c index cb7bf34..6852329 100644 --- a/src/kernel/core/worker.c +++ b/src/kernel/core/worker.c @@ -49,21 +49,24 @@ void worker_thread(void* x) { while (true) { mutex_lock(&tasks_mutex); - worker_task_t *t = btree_upper(tasks, &zero64); - next_task_time = (t == 0 ? UINT64_MAX : t->time); - if (t != 0 && t->time <= time) { - btree_remove_v(tasks, &t->time, t); + + worker_task_t *next_task = btree_upper(tasks, &zero64); + next_task_time = (next_task == 0 ? UINT64_MAX : next_task->time); + + if (next_task != 0 && next_task->time <= time) { + btree_remove_v(tasks, &next_task->time, next_task); } else { - t = 0; + next_task = 0; } + mutex_unlock(&tasks_mutex); - if (t != 0) { - prng_add_entropy((uint8_t*)&t, sizeof(t)); + if (next_task != 0) { + prng_add_entropy((uint8_t*)&next_task, sizeof(next_task)); // do task :-) - t->fun(t->data); - free(t); + next_task->fun(next_task->data); + free(next_task); } else { ASSERT(wait_on(current_thread)); } @@ -79,11 +82,12 @@ bool worker_push_in(int usecs, entry_t fun, void* data) { t->data = data; mutex_lock(&tasks_mutex); + btree_add(tasks, &t->time, t); - mutex_unlock(&tasks_mutex); - if (t->time < next_task_time) next_task_time = t->time; + mutex_unlock(&tasks_mutex); + return true; } @@ -95,6 +99,7 @@ void notify_time_pass(int usecs) { time += usecs; if (next_task_time <= time) { for (int i = 0; i < nworkers; i++) { + if (workers[i] == 0) continue; if (resume_on(workers[i])) break; } } diff --git a/src/kernel/dev/pckbd.c b/src/kernel/dev/pckbd.c index a911b85..8a4c002 100644 --- a/src/kernel/dev/pckbd.c +++ b/src/kernel/dev/pckbd.c @@ -105,7 +105,7 @@ size_t pckbd_read(fs_handle_t *h, size_t offset, size_t len, char *buf) { } int pckbd_poll(fs_handle_t *h, void** out_wait_obj) { - *out_wait_obj = &pckbd_buf; + if (out_wait_obj) *out_wait_obj = &pckbd_buf; return (pckbd_buf_used > 0 ? SEL_READ : 0); } diff --git a/src/kernel/include/thread.h b/src/kernel/include/thread.h index 4b140fa..698c4c6 100644 --- a/src/kernel/include/thread.h +++ b/src/kernel/include/thread.h @@ -46,7 +46,7 @@ thread_t *new_thread(entry_t entry, void* data); // thread is PAUSED, and must b void start_thread(thread_t *t); void delete_thread(thread_t *t); -void irq0_handler(registers_t *regs, int crit_level); +void threading_irq0_handler(); extern thread_t *current_thread; diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c index 3a67350..606ab3f 100644 --- a/src/kernel/user/syscall.c +++ b/src/kernel/user/syscall.c @@ -311,7 +311,7 @@ static uint32_t select_sc(sc_args_t args) { bool ret = false; - int st = enter_critical(CL_NOSWITCH); + int st = enter_critical(CL_NOINT); while (true) { // ---- Poll FDs, if any is ok then return it @@ -328,10 +328,10 @@ static uint32_t select_sc(sc_args_t args) { uint64_t time = get_kernel_time(); - // ---- If none of the handles given is a valid handle, return false - if (n_wait_objs == 0) break; // ---- If any is ok, return true if (ret) break; + // ---- If none of the handles given is a valid handle, return false + if (n_wait_objs == 0) break; // ---- If the timeout is over, return false if (timeout >= 0 && time - select_begin_time >= (uint64_t)timeout) break; diff --git a/src/lib/include/gip.h b/src/lib/include/gip.h index c2167c4..9c66091 100644 --- a/src/lib/include/gip.h +++ b/src/lib/include/gip.h @@ -16,7 +16,8 @@ typedef struct { noarg_gip_callback_t reset, initiate, ok, failure, enable_features, disable_features, - query_mode, set_mode, switch_buffer; + query_mode, set_mode, switch_buffer, + key_down, key_up; void (*buffer_info)(gip_handler_t *s, gip_msg_header *m, gip_buffer_info_msg *i); void (*mode_info)(gip_handler_t *s, gip_msg_header *m, gip_mode_info_msg *i); void (*buffer_damage)(gip_handler_t *s, gip_msg_header *m, gip_buffer_damage_msg *i); diff --git a/src/lib/libkogata/gip.c b/src/lib/libkogata/gip.c index 7fa1cca..852cc05 100644 --- a/src/lib/libkogata/gip.c +++ b/src/lib/libkogata/gip.c @@ -167,6 +167,10 @@ void giph_msg_header(mainloop_fd_t *fd) { mainloop_expect(fd, &h->mode_info_msg_buf, sizeof(gip_mode_info_msg), giph_mode_info); } else if (code == GIPN_BUFFER_DAMAGE) { mainloop_expect(fd, &h->buffer_damage_msg_buf, sizeof(gip_buffer_damage_msg), giph_buffer_damage); + } else if (code == GIPN_KEY_DOWN) { + use_cb = h->cb->key_down; + } else if (code == GIPN_KEY_UP) { + use_cb = h->cb->key_up; } else { use_cb = h->cb->unknown_msg; } diff --git a/src/lib/libkogata/mainloop.c b/src/lib/libkogata/mainloop.c index d8890e7..e7fdfa4 100644 --- a/src/lib/libkogata/mainloop.c +++ b/src/lib/libkogata/mainloop.c @@ -88,12 +88,14 @@ void mainloop_run() { } // ---- Do the select + dbg_printf("(mainloop) begin select\n"); bool ok = select(sel_arg, nfds, -1); if (!ok) { dbg_printf("(mainloop) Failed to select.\n"); free(sel_arg); return; } + dbg_printf("(mainloop) end select\n"); { // Parse result int i = 0; @@ -105,6 +107,7 @@ void mainloop_run() { fd->rd_buf_filled += read(fd->fd, 0, fd->rd_buf_expect_size - fd->rd_buf_filled, fd->rd_buf + fd->rd_buf_filled); if (fd->rd_buf_filled == fd->rd_buf_expect_size) { + dbg_printf("(mainloop) finish read %d\n", fd->rd_buf_expect_size); fd->rd_buf_filled = 0; ASSERT(fd->rd_on_full != 0); fd->rd_on_full(fd); @@ -116,6 +119,7 @@ void mainloop_run() { fd->wr_bufs[0].written += write(fd->fd, 0, remain_size, write_ptr); if (fd->wr_bufs[0].written == fd->wr_bufs[0].size) { + dbg_printf("(mainloop) finish write %d\n", fd->wr_bufs[0].size); if (fd->wr_bufs[0].must_free) free(fd->wr_bufs[0].buf); for (int i = 1; i < MAINLOOP_MAX_WR_BUFS; i++) { fd->wr_bufs[i-1] = fd->wr_bufs[i]; diff --git a/src/sysbin/giosrv/main.c b/src/sysbin/giosrv/main.c index c161bd6..6e3378b 100644 --- a/src/sysbin/giosrv/main.c +++ b/src/sysbin/giosrv/main.c @@ -39,9 +39,12 @@ gip_handler_callbacks_t giosrv_cb = { .buffer_damage = 0, .unknown_msg = unknown_msg, .fd_error = fd_error, + .key_down = 0, + .key_up = 0, }; giosrv_t srv; +gip_handler_t *gipsrv; // ---- KBD listener @@ -80,11 +83,11 @@ int main(int argc, char **argv) { dbg_printf("[giosrv] Running on FB %dx%d\n", srv.mode.width, srv.mode.height); // ---- GIP server setup - gip_handler_t *h = new_gip_handler(&giosrv_cb, &srv); - ASSERT(h != 0); + gipsrv = new_gip_handler(&giosrv_cb, &srv); + ASSERT(gipsrv != 0); - h->mainloop_item.fd = 1; - mainloop_add_fd(&h->mainloop_item); + gipsrv->mainloop_item.fd = 1; + mainloop_add_fd(&gipsrv->mainloop_item); // ---- Enter main loop mainloop_run(); @@ -153,7 +156,11 @@ void fd_error(gip_handler_t *h) { } void kbd_handle_event(mainloop_fd_t *fd) { - // TODO + gip_msg_header m; + m.arg = kbd.ev.scancode; + m.code = (kbd.ev.type == KBD_EVENT_KEYPRESS ? GIPN_KEY_DOWN : GIPN_KEY_UP); + + gip_notify(gipsrv, &m, 0); } void kbd_on_error(mainloop_fd_t *fd) { diff --git a/src/sysbin/login/main.c b/src/sysbin/login/main.c index 294ad76..e6e5290 100644 --- a/src/sysbin/login/main.c +++ b/src/sysbin/login/main.c @@ -15,6 +15,8 @@ typedef struct { } loginc_t; void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m); +void c_key_down(gip_handler_t *s, gip_msg_header *p); +void c_key_up(gip_handler_t *s, gip_msg_header *p); void c_unknown_msg(gip_handler_t *s, gip_msg_header *p); void c_fd_error(gip_handler_t *s); @@ -32,6 +34,8 @@ gip_handler_callbacks_t loginc_cb = { .buffer_info = c_buffer_info, .mode_info = 0, .buffer_damage = 0, + .key_down = c_key_down, + .key_up = c_key_up, .unknown_msg = c_unknown_msg, .fd_error = c_fd_error, }; @@ -98,6 +102,12 @@ void c_buffer_info(gip_handler_t *s, gip_msg_header *p, gip_buffer_info_msg *m) } } +void c_key_down(gip_handler_t *s, gip_msg_header *p) { +} + +void c_key_up(gip_handler_t *s, gip_msg_header *p) { +} + void c_unknown_msg(gip_handler_t *s, gip_msg_header *p) { // TODO } |