Prepare basic implementation of a sleep queue inside the keyboard driver

This commit is contained in:
Baptiste Wicht 2014-01-29 22:16:10 +01:00
parent cc37f73ba4
commit 86771ec0f0
4 changed files with 91 additions and 15 deletions

View File

@ -24,7 +24,7 @@ char get_char();
char key_to_ascii(uint8_t key); char key_to_ascii(uint8_t key);
char shift_key_to_ascii(uint8_t key); char shift_key_to_ascii(uint8_t key);
char get_char_blocking(); void get_char_blocking();
} }

View File

@ -0,0 +1,60 @@
//=======================================================================
// Copyright Baptiste Wicht 2013-2014.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
#ifndef SLEEP_QUEUE_H
#define SLEEP_QUEUE_H
#include "stl/queue.hpp"
#include "stl/lock_guard.hpp"
#include "spinlock.hpp"
#include "scheduler.hpp"
struct sleep_queue {
private:
mutable spinlock lock;
std::queue<scheduler::pid_t> queue;
public:
bool empty() const {
std::lock_guard<spinlock> l(lock);
return queue.empty();
}
scheduler::pid_t wake_up(){
std::lock_guard<spinlock> l(lock);
//Get the first process
auto pid = queue.top();
//Indicate to the scheduler that this process will be able
//to run
scheduler::unblock_process(pid);
//Remove the process from the queue
queue.pop();
return pid;
}
void sleep(){
std::lock_guard<spinlock> l(lock);
//Get the current process information
auto pid = scheduler::get_pid();
//This process will sleep
scheduler::block_process(pid);
//Enqueue the process in the sleep queue
queue.push(pid);
}
};
#endif

View File

@ -10,6 +10,7 @@
#include "kernel_utils.hpp" #include "kernel_utils.hpp"
#include "semaphore.hpp" #include "semaphore.hpp"
#include "spinlock.hpp" #include "spinlock.hpp"
#include "sleep_queue.hpp"
namespace { namespace {
@ -93,22 +94,31 @@ char shifted_qwertz[128] = {
const uint8_t BUFFER_SIZE = 64; const uint8_t BUFFER_SIZE = 64;
//TODO Encapsulate the buffer
char input_buffer[BUFFER_SIZE]; char input_buffer[BUFFER_SIZE];
volatile uint8_t start; volatile uint8_t start;
volatile uint8_t count; volatile uint8_t count;
spinlock lock; spinlock lock;
semaphore sem; sleep_queue queue;
void keyboard_handler(const interrupt::syscall_regs&){ void keyboard_handler(const interrupt::syscall_regs&){
auto key = static_cast<char>(in_byte(0x60)); auto key = static_cast<char>(in_byte(0x60));
std::lock_guard<spinlock> l(lock);
if(count == BUFFER_SIZE){ if(count == BUFFER_SIZE){
//The buffer is full, we loose the characters //The buffer is full, we loose the characters
} else { } else {
auto end = (start + count) % BUFFER_SIZE; if(queue.empty()){
input_buffer[end] = key; auto end = (start + count) % BUFFER_SIZE;
++count; input_buffer[end] = key;
++count;
} else {
auto pid = queue.wake_up();
//TODO Give key to process pid
}
} }
} }
@ -119,12 +129,23 @@ void keyboard::install_driver(){
start = 0; start = 0;
count = 0; count = 0;
sem.init(0);
} }
char keyboard::get_char_blocking(){ void keyboard::get_char_blocking(){
//TODO std::lock_guard<spinlock> l(lock);
if(count > 0){
auto key = input_buffer[start];
start = (start + 1) % BUFFER_SIZE;
--count;
auto pid = scheduler::current_pid();
//TODO Give key to process pid
} else {
//Wait for a char
queue.sleep();
}
} }
//TODO Once shell is user mode, can be removed //TODO Once shell is user mode, can be removed

View File

@ -24,11 +24,6 @@ void sc_print_digit(const interrupt::syscall_regs& regs){
k_print(regs.rbx); k_print(regs.rbx);
} }
void sc_get_char(const interrupt::syscall_regs& regs){
auto c = keyboard::get_char_blocking();
//TODO
}
} //End of anonymous namespace } //End of anonymous namespace
void system_call_entry(const interrupt::syscall_regs& regs){ void system_call_entry(const interrupt::syscall_regs& regs){
@ -48,7 +43,7 @@ void system_call_entry(const interrupt::syscall_regs& regs){
break; break;
case 3: case 3:
sc_get_char(regs); keyboard::get_char_blocking();
break; break;
case 0x666: case 0x666: