From: Minep Date: Tue, 3 May 2022 14:22:16 +0000 (+0100) Subject: Implement (half) simple semaphore & mutex lock, and ... X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/a0655e5d30f3cdc73b1aaaa4825d8fae9f92ce4a?hp=9440be3a5115a91dcdf8dff05a361cac4b6cea29 Implement (half) simple semaphore & mutex lock, and ... Use vga cursor. Address the issue of spurious IRQ#1 which interference key hanlder when receiving the command response byte. Refactoring and commentings. --- diff --git a/lunaix-os/includes/lunaix/ds/mutex.h b/lunaix-os/includes/lunaix/ds/mutex.h new file mode 100644 index 0000000..5e166e5 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/mutex.h @@ -0,0 +1,26 @@ +#ifndef __LUNAIX_MUTEX_H +#define __LUNAIX_MUTEX_H + +#include "semaphore.h" + +// TODO: implement mutex lock + +typedef struct sem_t mutex_t; + +static inline void mutex_init(mutex_t *mutex) { + sem_init(mutex, 1); +} + +static inline unsigned int mutex_on_hold(mutex_t *mutex) { + return !atomic_load(&mutex->counter); +} + +static inline void mutex_lock(mutex_t *mutex) { + sem_wait(mutex); +} + +static inline void mutex_unlock(mutex_t *mutex) { + sem_post(mutex); +} + +#endif /* __LUNAIX_MUTEX_H */ diff --git a/lunaix-os/includes/lunaix/ds/semaphore.h b/lunaix-os/includes/lunaix/ds/semaphore.h new file mode 100644 index 0000000..e202d14 --- /dev/null +++ b/lunaix-os/includes/lunaix/ds/semaphore.h @@ -0,0 +1,17 @@ +#ifndef __LUNAIX_SEMAPHORE_H +#define __LUNAIX_SEMAPHORE_H + +#include + +struct sem_t { + _Atomic unsigned int counter; + // FUTURE: might need a waiting list +}; + +void sem_init(struct sem_t *sem, unsigned int initial); + +void sem_wait(struct sem_t *sem); + +void sem_post(struct sem_t *sem); + +#endif /* __LUNAIX_SEMAPHORE_H */ diff --git a/lunaix-os/includes/lunaix/keyboard.h b/lunaix-os/includes/lunaix/keyboard.h index c439b6f..7f13088 100644 --- a/lunaix-os/includes/lunaix/keyboard.h +++ b/lunaix-os/includes/lunaix/keyboard.h @@ -94,6 +94,6 @@ struct kdb_keyinfo_pkt { time_t timestamp; }; -struct kdb_keyinfo_pkt* kbd_try_read_one(); +int kbd_recv_key(struct kdb_keyinfo_pkt* key_event); #endif /* __LUNAIX_KEYBOARD_H */ diff --git a/lunaix-os/includes/lunaix/peripheral/ps2kbd.h b/lunaix-os/includes/lunaix/peripheral/ps2kbd.h index a63ffdc..d373aa8 100644 --- a/lunaix-os/includes/lunaix/peripheral/ps2kbd.h +++ b/lunaix-os/includes/lunaix/peripheral/ps2kbd.h @@ -3,6 +3,8 @@ #include #include +#include + #define PS2_PORT_ENC_DATA 0x60 #define PS2_PORT_ENC_CMDREG 0x60 @@ -64,16 +66,14 @@ struct ps2_cmd_queue { struct ps2_cmd cmd_queue[PS2_CMD_QUEUE_SIZE]; int queue_ptr; int queue_len; - // FIXME: replace lock with something specialized. - volatile char lock; + mutex_t mutex; }; struct ps2_key_buffer { struct kdb_keyinfo_pkt buffer[PS2_KBD_RECV_BUFFER_SIZE]; int read_ptr; int buffered_len; - // FIXME: replace lock with something specialized. - volatile char lock; + mutex_t mutex; }; /** diff --git a/lunaix-os/includes/lunaix/tty/tty.h b/lunaix-os/includes/lunaix/tty/tty.h index 28ad83d..cbb3924 100644 --- a/lunaix-os/includes/lunaix/tty/tty.h +++ b/lunaix-os/includes/lunaix/tty/tty.h @@ -52,5 +52,9 @@ tty_get_cpos(unsigned int* x, unsigned int* y); vga_attribute tty_get_theme(); +void tty_set_cursor(unsigned char x, unsigned char y); + +void tty_sync_cursor(); + #endif /* __LUNAIX_TTY_H */ diff --git a/lunaix-os/kernel/ds/semaphore.c b/lunaix-os/kernel/ds/semaphore.c new file mode 100644 index 0000000..21d0e33 --- /dev/null +++ b/lunaix-os/kernel/ds/semaphore.c @@ -0,0 +1,17 @@ +#include + +void sem_init(struct sem_t *sem, unsigned int initial) { + sem->counter = ATOMIC_VAR_INIT(initial); +} + +void sem_wait(struct sem_t *sem) { + while (!atomic_load(&sem->counter)) { + // TODO: yield the cpu + } + atomic_fetch_sub(&sem->counter, 1); +} + +void sem_post(struct sem_t *sem) { + atomic_fetch_add(&sem->counter, 1); + // TODO: wake up a thread +} \ No newline at end of file diff --git a/lunaix-os/kernel/k_main.c b/lunaix-os/kernel/k_main.c index fe5645f..c3819d9 100644 --- a/lunaix-os/kernel/k_main.c +++ b/lunaix-os/kernel/k_main.c @@ -55,16 +55,16 @@ _kernel_main() // timer_run_second(1, test_timer, NULL, TIMER_MODE_PERIODIC); + struct kdb_keyinfo_pkt keyevent; while (1) { - struct kdb_keyinfo_pkt* keyevent = kbd_try_read_one(); - if (!keyevent) { + if (!kbd_recv_key(&keyevent)) { continue; } - if ((keyevent->state & KBD_KEY_FPRESSED) && (keyevent->keycode & 0xff00) <= KEYPAD) { - tty_put_char((char)(keyevent->keycode & 0x00ff)); + if ((keyevent.state & KBD_KEY_FPRESSED) && (keyevent.keycode & 0xff00) <= KEYPAD) { + tty_put_char((char)(keyevent.keycode & 0x00ff)); + tty_sync_cursor(); } - lxfree(keyevent); } spin(); diff --git a/lunaix-os/kernel/mm/kalloc.c b/lunaix-os/kernel/mm/kalloc.c index e9f0564..16c1d82 100644 --- a/lunaix-os/kernel/mm/kalloc.c +++ b/lunaix-os/kernel/mm/kalloc.c @@ -23,6 +23,7 @@ extern uint8_t __kernel_heap_start; +// FIXME: This should go to PCB once we're started to support multitasking static heap_context_t __kalloc_kheap; void* diff --git a/lunaix-os/kernel/peripheral/ps2kbd.c b/lunaix-os/kernel/peripheral/ps2kbd.c index fc4151a..4e7fb63 100644 --- a/lunaix-os/kernel/peripheral/ps2kbd.c +++ b/lunaix-os/kernel/peripheral/ps2kbd.c @@ -3,14 +3,13 @@ #include #include #include -#include #include - #include -#include #include +#include + #define PS2_DEV_CMD_MAX_ATTEMPTS 5 LOG_MODULE("PS2KBD"); @@ -68,20 +67,18 @@ static kbd_keycode_t scancode_set2_shift[] = { #define KBD_STATE_KWAIT 0x00 #define KBD_STATE_KSPECIAL 0x01 #define KBD_STATE_KRELEASED 0x02 -// #define KBD_STATE_CMDPROCS 0x80 +#define KBD_STATE_CMDPROCS 0x40 void intr_ps2_kbd_handler(const isr_param* param); static struct kdb_keyinfo_pkt* ps2_keybuffer_next_write(); // TODO: Abstract the bounded buffer out. void ps2_device_post_cmd(char cmd, char arg) { - // 不需要任何的类似lock cmpxchgl的骚操作。 - // 这条赋值表达式最多涉及一个内存引用(e.g., movl $1, (cmd_q.lock)),因此是原子的。 - cmd_q.lock = 1; + mutex_lock(&cmd_q.mutex); int index = (cmd_q.queue_ptr + cmd_q.queue_len) % PS2_CMD_QUEUE_SIZE; if (index == cmd_q.queue_ptr && cmd_q.queue_len) { // 队列已满! - cmd_q.lock = 0; + mutex_unlock(&cmd_q.mutex); return; } @@ -91,7 +88,7 @@ void ps2_device_post_cmd(char cmd, char arg) { cmd_q.queue_len++; // 释放锁,同理。 - cmd_q.lock = 0; + mutex_unlock(&cmd_q.mutex); } void ps2_kbd_init() { @@ -99,6 +96,11 @@ void ps2_kbd_init() { memset(&cmd_q, 0, sizeof(cmd_q)); memset(&key_buf, 0, sizeof(key_buf)); memset(&kbd_state, 0, sizeof(kbd_state)); + + mutex_init(&cmd_q.mutex); + mutex_init(&key_buf.mutex); + + kbd_state.translation_table = scancode_set2; kbd_state.state = KBD_STATE_KWAIT; @@ -163,11 +165,10 @@ void ps2_process_cmd(void* arg) { // 因此,我们这里仅仅进行判断。 // 会不会产生指令堆积?不会,因为指令发送的频率远远低于指令队列清空的频率。在目前,我们发送的唯一指令 // 就只是用来开关键盘上的LED灯(如CAPSLOCK)。 - if (!cmd_q.queue_len || cmd_q.lock) { + if (mutex_on_hold(&cmd_q.mutex) || !cmd_q.queue_len) { return; } - // kbd_state.state |= KBD_STATE_CMDPROCS; // 处理队列排头的指令 struct ps2_cmd *pending_cmd = &cmd_q.cmd_queue[cmd_q.queue_ptr]; char result; @@ -178,6 +179,7 @@ void ps2_process_cmd(void* arg) { // 则尝试最多五次 do { result = ps2_issue_dev_cmd(pending_cmd->cmd, pending_cmd->arg); + kbd_state.state += KBD_STATE_CMDPROCS; attempts++; } while(result == PS2_RESULT_NAK && attempts < PS2_DEV_CMD_MAX_ATTEMPTS); @@ -207,7 +209,7 @@ void kbd_buffer_key_event(kbd_keycode_t key, uint8_t scancode, kbd_kstate_t stat state = state | kbd_state.key_state; key = key & (0xffdf | -('a' > key || key > 'z' || !(state & KBD_KEY_FCAPSLKED))); - if (!key_buf.lock) { + if (!mutex_on_hold(&key_buf.mutex)) { struct kdb_keyinfo_pkt* keyevent_pkt = ps2_keybuffer_next_write(); *keyevent_pkt = (struct kdb_keyinfo_pkt) { .keycode = key, @@ -242,18 +244,14 @@ void intr_ps2_kbd_handler(const isr_param* param) { * 那么当ps2_process_cmd执行完后(内嵌在#APIC_TIMER_IV),CPU返回EOI给APIC,APIC紧接着将排在队里的IRQ#1发送给CPU * 造成误触发。也就是说,我们此时读入的scancode实则上是上一个指令的返回代码。 * - * Problem 1: + * Problem 1 (Fixed): * 但是这种方法有个问题,那就是,假若我们的某一个命令失败了一次,ps/2给出0xfe,我们重传,ps/2收到指令并给出0xfa。 * 那么这样一来,将会由两个连续的IRQ#1产生。而APIC是最多可以缓存两个IRQ,于是我们就会漏掉一个IRQ,依然会误触发。 + * Solution: + * 累加掩码 ;) */ - // FIXME: Address Problem #1 - // if ((kbd_state.state & KBD_STATE_CMDPROCS)) { - // kbd_state.state &= ~KBD_STATE_CMDPROCS; - // return; - // } - - // 目前还是使用该方法。。。 - if (scancode >= 0xfa) { + if ((kbd_state.state & 0xc0)) { + kbd_state.state -= KBD_STATE_CMDPROCS; return; } @@ -333,22 +331,20 @@ static void ps2_post_cmd(uint8_t port, char cmd, uint16_t arg) { } } -struct kdb_keyinfo_pkt* kbd_try_read_one() { +int kbd_recv_key(struct kdb_keyinfo_pkt* key_event) { if (!key_buf.buffered_len) { - return NULL; + return 0; } - key_buf.lock = 1; - struct kdb_keyinfo_pkt* pkt_copy = - (struct kdb_keyinfo_pkt*) lxmalloc(sizeof(struct kdb_keyinfo_pkt)); + mutex_lock(&key_buf.mutex); struct kdb_keyinfo_pkt* pkt_current = &key_buf.buffer[key_buf.read_ptr]; - *pkt_copy = *pkt_current; + *key_event = *pkt_current; key_buf.buffered_len--; key_buf.read_ptr = (key_buf.read_ptr + 1) % PS2_KBD_RECV_BUFFER_SIZE; - key_buf.lock = 0; - return pkt_copy; + mutex_unlock(&key_buf.mutex); + return 1; } static struct kdb_keyinfo_pkt* ps2_keybuffer_next_write() { diff --git a/lunaix-os/kernel/tty/tty.c b/lunaix-os/kernel/tty/tty.c index 4a20a77..c779ed5 100644 --- a/lunaix-os/kernel/tty/tty.c +++ b/lunaix-os/kernel/tty/tty.c @@ -2,6 +2,7 @@ #include #include #include +#include #define TTY_WIDTH 80 #define TTY_HEIGHT 25 @@ -11,11 +12,17 @@ static vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR; static vga_attribute tty_theme_color = VGA_COLOR_BLACK; static uint32_t tty_x = 0; -static uint16_t tty_y = 0; +static uint32_t tty_y = 0; void tty_init(void* vga_buf) { tty_vga_buffer = (vga_attribute*)vga_buf; tty_clear(); + + io_outb(0x3D4, 0x0A); + io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13); + + io_outb(0x3D4, 0x0B); + io_outb(0x3D5, (io_inb(0x3D5) & 0xE0) | 15); } void tty_set_buffer(void* vga_buf) { @@ -60,6 +67,22 @@ tty_put_char(char chr) } } +void tty_sync_cursor() { + tty_set_cursor(tty_x, tty_y); +} + + +void tty_set_cursor(uint8_t x, uint8_t y) { + if (x >= TTY_WIDTH || y >= TTY_HEIGHT) { + x = y = 0; + } + uint32_t pos = y * TTY_WIDTH + x; + io_outb(0x3D4, 14); + io_outb(0x3D5, pos / 256); + io_outb(0x3D4, 15); + io_outb(0x3D5, pos % 256); +} + void tty_put_str(char* str) { @@ -67,6 +90,7 @@ tty_put_str(char* str) tty_put_char(*str); str++; } + tty_sync_cursor(); } void