Kernel: Replace CriticalScopes with SpinLock in PS/2 and input code
This commit is contained in:
parent
ec0cb5fd54
commit
7f028f70d5
|
@ -3,6 +3,7 @@
|
|||
#include <BAN/Array.h>
|
||||
#include <BAN/UniqPtr.h>
|
||||
#include <kernel/Input/KeyEvent.h>
|
||||
#include <kernel/Lock/SpinLock.h>
|
||||
|
||||
namespace Kernel::Input
|
||||
{
|
||||
|
@ -23,6 +24,7 @@ namespace Kernel::Input
|
|||
BAN::Array<Key, 0xFF> m_keycode_to_key_normal;
|
||||
BAN::Array<Key, 0xFF> m_keycode_to_key_shift;
|
||||
BAN::Array<Key, 0xFF> m_keycode_to_key_altgr;
|
||||
SpinLock m_lock;
|
||||
|
||||
friend class BAN::UniqPtr<KeyboardLayout>;
|
||||
};
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace Kernel::Input
|
|||
|
||||
BAN::CircularQueue<Command, 128> m_command_queue;
|
||||
uint64_t m_command_send_time { 0 };
|
||||
SpinLock m_command_lock;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace Kernel::Input
|
|||
uint16_t m_modifiers { 0 };
|
||||
|
||||
BAN::CircularQueue<KeyEvent, 50> m_event_queue;
|
||||
SpinLock m_event_lock;
|
||||
|
||||
PS2Keymap m_keymap;
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace Kernel::Input
|
|||
uint8_t m_button_mask { 0x00 };
|
||||
|
||||
BAN::CircularQueue<MouseEvent, 128> m_event_queue;
|
||||
SpinLock m_event_lock;
|
||||
|
||||
Semaphore m_semaphore;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <BAN/HashMap.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/FS/VirtualFileSystem.h>
|
||||
#include <kernel/Input/KeyboardLayout.h>
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <kernel/Input/PS2/Controller.h>
|
||||
#include <kernel/Input/PS2/Keyboard.h>
|
||||
#include <kernel/Input/PS2/Mouse.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/IO.h>
|
||||
#include <kernel/Timer/Timer.h>
|
||||
|
||||
|
@ -21,7 +20,6 @@ namespace Kernel::Input
|
|||
|
||||
BAN::ErrorOr<void> 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<uint8_t> 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;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Input/KeyboardLayout.h>
|
||||
#include <kernel/Input/PS2/Config.h>
|
||||
|
@ -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<KeyEvent>() = 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<KeyEvent>() = m_event_queue.front();
|
||||
m_event_queue.pop();
|
||||
|
||||
m_event_lock.unlock(state);
|
||||
|
||||
return sizeof(KeyEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <BAN/ScopeGuard.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Input/PS2/Config.h>
|
||||
#include <kernel/Input/PS2/Mouse.h>
|
||||
|
@ -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<MouseEvent>() = 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<MouseEvent>() = m_event_queue.front();
|
||||
m_event_queue.pop();
|
||||
|
||||
m_event_lock.unlock(state);
|
||||
|
||||
return sizeof(MouseEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue