[pc] Make platform_read_key idle on wait queue.
Fixes hack in dgetc using arch_idle. Now platform_read_key uses a wait
queue to sleep until a key is available in the key buffer, allowing the
idle thread or other threads to run. Since the idle thread gets a chance
to run, idle time accounting is now unbroken.
diff --git a/platform/pc/debug.c b/platform/pc/debug.c
index 63652d8..b1d70ee 100644
--- a/platform/pc/debug.c
+++ b/platform/pc/debug.c
@@ -38,8 +38,8 @@
int dgetc(char *c, bool wait)
{
int ret = platform_read_key(c);
- if (ret < 0)
- arch_idle();
+ //if (ret < 0)
+ // arch_idle();
return ret;
}
diff --git a/platform/pc/keyboard.c b/platform/pc/keyboard.c
index 8b4d623..e0f6a7e 100644
--- a/platform/pc/keyboard.c
+++ b/platform/pc/keyboard.c
@@ -170,6 +170,8 @@
static uint8_t key_buffer[KEY_BUFFER_LEN];
static int key_buffer_in_ptr, key_buffer_out_ptr;
+static wait_queue_t key_buffer_wq;
+
static int inq(uint8_t data) {
int temp;
@@ -238,7 +240,11 @@
key_rshift ? 'R' : ' ');*/
if (keyCode != -1 && !keyUpBit) {
- inq(keyCode);
+ if (!inq(keyCode)) {
+ enter_critical_section();
+ wait_queue_wake_one(&key_buffer_wq, 1, 0);
+ exit_critical_section();
+ }
}
// update the last received code
@@ -346,15 +352,21 @@
{
int data;
- enter_critical_section();
- data = deq();
+ do {
+ enter_critical_section();
+ data = deq();
+
+ if (data != -1) {
+ *c = (char) data;
+ } else {
+ wait_queue_block(&key_buffer_wq, INFINITE_TIME);
+ exit_critical_section();
+ continue;
+ }
+ exit_critical_section();
+ } while(0);
- if (data != -1) {
- *c = (char) data;
- }
- exit_critical_section();
-
- return data == -1 ? -1 : 0;
+ return data; //data == -1 ? -1 : 0;
}
void platform_init_keyboard(void)
@@ -363,6 +375,8 @@
// clear in case of reinit
key_buffer_in_ptr = key_buffer_out_ptr = 0;
+
+ wait_queue_init(&key_buffer_wq);
i8042_flush();