diff --git a/kernel/include/kernel/Input/KeyboardLayout.h b/kernel/include/kernel/Input/KeyboardLayout.h index 62fb7a96..9eea4131 100644 --- a/kernel/include/kernel/Input/KeyboardLayout.h +++ b/kernel/include/kernel/Input/KeyboardLayout.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace Kernel::Input { @@ -23,6 +24,7 @@ namespace Kernel::Input BAN::Array m_keycode_to_key_normal; BAN::Array m_keycode_to_key_shift; BAN::Array m_keycode_to_key_altgr; + SpinLock m_lock; friend class BAN::UniqPtr; }; diff --git a/kernel/include/kernel/Input/PS2/Controller.h b/kernel/include/kernel/Input/PS2/Controller.h index fc042e60..120a84a8 100644 --- a/kernel/include/kernel/Input/PS2/Controller.h +++ b/kernel/include/kernel/Input/PS2/Controller.h @@ -64,6 +64,7 @@ namespace Kernel::Input BAN::CircularQueue m_command_queue; uint64_t m_command_send_time { 0 }; + SpinLock m_command_lock; }; } diff --git a/kernel/include/kernel/Input/PS2/Keyboard.h b/kernel/include/kernel/Input/PS2/Keyboard.h index 2fcd915f..5b97e522 100644 --- a/kernel/include/kernel/Input/PS2/Keyboard.h +++ b/kernel/include/kernel/Input/PS2/Keyboard.h @@ -41,6 +41,7 @@ namespace Kernel::Input uint16_t m_modifiers { 0 }; BAN::CircularQueue m_event_queue; + SpinLock m_event_lock; PS2Keymap m_keymap; diff --git a/kernel/include/kernel/Input/PS2/Mouse.h b/kernel/include/kernel/Input/PS2/Mouse.h index f0977a2a..cc66d582 100644 --- a/kernel/include/kernel/Input/PS2/Mouse.h +++ b/kernel/include/kernel/Input/PS2/Mouse.h @@ -37,6 +37,7 @@ namespace Kernel::Input uint8_t m_button_mask { 0x00 }; BAN::CircularQueue m_event_queue; + SpinLock m_event_lock; Semaphore m_semaphore; diff --git a/kernel/kernel/Input/KeyboardLayout.cpp b/kernel/kernel/Input/KeyboardLayout.cpp index c8b6901d..603ce2e6 100644 --- a/kernel/kernel/Input/KeyboardLayout.cpp +++ b/kernel/kernel/Input/KeyboardLayout.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -74,6 +73,7 @@ namespace Kernel::Input Key KeyboardLayout::get_key_from_event(KeyEvent event) { + SpinLockGuard _(m_lock); if (event.shift()) return m_keycode_to_key_shift[event.keycode]; if (event.ralt()) @@ -256,7 +256,7 @@ namespace Kernel::Input } } - CriticalScope _; + SpinLockGuard _(m_lock); for (size_t i = 0; i < new_layout->m_keycode_to_key_normal.size(); i++) if (new_layout->m_keycode_to_key_normal[i] != Key::None) diff --git a/kernel/kernel/Input/PS2/Controller.cpp b/kernel/kernel/Input/PS2/Controller.cpp index 875a9d79..ec6f30f5 100644 --- a/kernel/kernel/Input/PS2/Controller.cpp +++ b/kernel/kernel/Input/PS2/Controller.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -21,7 +20,6 @@ namespace Kernel::Input BAN::ErrorOr PS2Controller::send_byte(uint16_t port, uint8_t byte) { - ASSERT(interrupts_enabled()); LockGuard _(m_mutex); uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms; while (SystemTimer::get().ms_since_boot() < timeout) @@ -36,7 +34,6 @@ namespace Kernel::Input BAN::ErrorOr PS2Controller::read_byte() { - ASSERT(interrupts_enabled()); LockGuard _(m_mutex); uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms; while (SystemTimer::get().ms_since_boot() < timeout) @@ -101,8 +98,7 @@ namespace Kernel::Input bool PS2Controller::append_command_queue(PS2Device* device, uint8_t command, uint8_t response_size) { - // NOTE: command queue push/pop must be done without interrupts - CriticalScope _; + SpinLockGuard _(m_command_lock); if (m_command_queue.size() + 1 >= m_command_queue.capacity()) { dprintln("PS/2 command queue full"); @@ -121,8 +117,7 @@ namespace Kernel::Input bool PS2Controller::append_command_queue(PS2Device* device, uint8_t command, uint8_t data, uint8_t response_size) { - // NOTE: command queue push/pop must be done without interrupts - CriticalScope _; + SpinLockGuard _(m_command_lock); if (m_command_queue.size() + 1 >= m_command_queue.capacity()) { dprintln("PS/2 command queue full"); @@ -141,35 +136,38 @@ namespace Kernel::Input void PS2Controller::update_command_queue() { - ASSERT(interrupts_enabled()); + Command command_copy; - if (m_command_queue.empty()) - return; - auto& command = m_command_queue.front(); - if (command.state == Command::State::WaitingResponse || command.state == Command::State::WaitingAck) { - if (SystemTimer::get().ms_since_boot() >= m_command_send_time + s_ps2_timeout_ms) + SpinLockGuard _(m_command_lock); + + if (m_command_queue.empty()) + return; + auto& command = m_command_queue.front(); + if (command.state == Command::State::WaitingResponse || command.state == Command::State::WaitingAck) { - dwarnln_if(DEBUG_PS2, "Command timedout"); - m_devices[command.device_index]->command_timedout(command.out_data, command.out_count); - m_command_queue.pop(); + if (SystemTimer::get().ms_since_boot() >= m_command_send_time + s_ps2_timeout_ms) + { + dwarnln_if(DEBUG_PS2, "Command timedout"); + m_devices[command.device_index]->command_timedout(command.out_data, command.out_count); + m_command_queue.pop(); + } + return; } - return; + ASSERT(command.send_index < command.out_count); + command.state = Command::State::WaitingAck; + + command_copy = command; } - ASSERT(command.send_index < command.out_count); - command.state = Command::State::WaitingAck; + m_command_send_time = SystemTimer::get().ms_since_boot(); - if (auto ret = device_send_byte(command.device_index, command.out_data[command.send_index]); ret.is_error()) - { - command.state = Command::State::Sending; + if (auto ret = device_send_byte(command_copy.device_index, command_copy.out_data[command_copy.send_index]); ret.is_error()) dwarnln_if(DEBUG_PS2, "PS/2 send command byte: {}", ret.error()); - } } bool PS2Controller::handle_command_byte(PS2Device* device, uint8_t byte) { - // NOTE: command queue push/pop must be done without interrupts - ASSERT(!interrupts_enabled()); + SpinLockGuard _(m_command_lock); if (m_command_queue.empty()) return false; diff --git a/kernel/kernel/Input/PS2/Keyboard.cpp b/kernel/kernel/Input/PS2/Keyboard.cpp index ae028f35..1e662611 100644 --- a/kernel/kernel/Input/PS2/Keyboard.cpp +++ b/kernel/kernel/Input/PS2/Keyboard.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -165,6 +164,8 @@ namespace Kernel::Input event.modifier = m_modifiers | (released ? 0 : KeyEvent::Modifier::Pressed); event.keycode = keycode.value(); + SpinLockGuard _(m_event_lock); + if (m_event_queue.full()) { dwarnln("PS/2 event queue full"); @@ -192,20 +193,20 @@ namespace Kernel::Input if (buffer.size() < sizeof(KeyEvent)) return BAN::Error::from_errno(ENOBUFS); - while (true) + auto state = m_event_lock.lock(); + while (m_event_queue.empty()) { - if (m_event_queue.empty()) - TRY(Thread::current().block_or_eintr_indefinite(m_semaphore)); - - CriticalScope _; - if (m_event_queue.empty()) - continue; - - buffer.as() = m_event_queue.front(); - m_event_queue.pop(); - - return sizeof(KeyEvent); + m_event_lock.unlock(state); + TRY(Thread::current().block_or_eintr_indefinite(m_semaphore)); + state = m_event_lock.lock(); } + + buffer.as() = m_event_queue.front(); + m_event_queue.pop(); + + m_event_lock.unlock(state); + + return sizeof(KeyEvent); } } diff --git a/kernel/kernel/Input/PS2/Mouse.cpp b/kernel/kernel/Input/PS2/Mouse.cpp index dfcc3ac0..decaea29 100644 --- a/kernel/kernel/Input/PS2/Mouse.cpp +++ b/kernel/kernel/Input/PS2/Mouse.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -158,6 +157,8 @@ namespace Kernel::Input event.scroll_event.scroll = rel_z; } + SpinLockGuard _(m_event_lock); + for (int i = 0; i < event_count; i++) { if (m_event_queue.full()) @@ -176,20 +177,20 @@ namespace Kernel::Input if (buffer.size() < sizeof(MouseEvent)) return BAN::Error::from_errno(ENOBUFS); - while (true) + auto state = m_event_lock.lock(); + while (m_event_queue.empty()) { - if (m_event_queue.empty()) - TRY(Thread::current().block_or_eintr_indefinite(m_semaphore)); - - CriticalScope _; - if (m_event_queue.empty()) - continue; - - buffer.as() = m_event_queue.front(); - m_event_queue.pop(); - - return sizeof(MouseEvent); + m_event_lock.unlock(state); + TRY(Thread::current().block_or_eintr_indefinite(m_semaphore)); + state = m_event_lock.lock(); } + + buffer.as() = m_event_queue.front(); + m_event_queue.pop(); + + m_event_lock.unlock(state); + + return sizeof(MouseEvent); } }