forked from Bananymous/banan-os
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/Array.h>
|
||||||
#include <BAN/UniqPtr.h>
|
#include <BAN/UniqPtr.h>
|
||||||
#include <kernel/Input/KeyEvent.h>
|
#include <kernel/Input/KeyEvent.h>
|
||||||
|
#include <kernel/Lock/SpinLock.h>
|
||||||
|
|
||||||
namespace Kernel::Input
|
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_normal;
|
||||||
BAN::Array<Key, 0xFF> m_keycode_to_key_shift;
|
BAN::Array<Key, 0xFF> m_keycode_to_key_shift;
|
||||||
BAN::Array<Key, 0xFF> m_keycode_to_key_altgr;
|
BAN::Array<Key, 0xFF> m_keycode_to_key_altgr;
|
||||||
|
SpinLock m_lock;
|
||||||
|
|
||||||
friend class BAN::UniqPtr<KeyboardLayout>;
|
friend class BAN::UniqPtr<KeyboardLayout>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,6 +64,7 @@ namespace Kernel::Input
|
||||||
|
|
||||||
BAN::CircularQueue<Command, 128> m_command_queue;
|
BAN::CircularQueue<Command, 128> m_command_queue;
|
||||||
uint64_t m_command_send_time { 0 };
|
uint64_t m_command_send_time { 0 };
|
||||||
|
SpinLock m_command_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace Kernel::Input
|
||||||
uint16_t m_modifiers { 0 };
|
uint16_t m_modifiers { 0 };
|
||||||
|
|
||||||
BAN::CircularQueue<KeyEvent, 50> m_event_queue;
|
BAN::CircularQueue<KeyEvent, 50> m_event_queue;
|
||||||
|
SpinLock m_event_lock;
|
||||||
|
|
||||||
PS2Keymap m_keymap;
|
PS2Keymap m_keymap;
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace Kernel::Input
|
||||||
uint8_t m_button_mask { 0x00 };
|
uint8_t m_button_mask { 0x00 };
|
||||||
|
|
||||||
BAN::CircularQueue<MouseEvent, 128> m_event_queue;
|
BAN::CircularQueue<MouseEvent, 128> m_event_queue;
|
||||||
|
SpinLock m_event_lock;
|
||||||
|
|
||||||
Semaphore m_semaphore;
|
Semaphore m_semaphore;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <BAN/HashMap.h>
|
#include <BAN/HashMap.h>
|
||||||
#include <kernel/CriticalScope.h>
|
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/Input/KeyboardLayout.h>
|
#include <kernel/Input/KeyboardLayout.h>
|
||||||
|
|
||||||
|
@ -74,6 +73,7 @@ namespace Kernel::Input
|
||||||
|
|
||||||
Key KeyboardLayout::get_key_from_event(KeyEvent event)
|
Key KeyboardLayout::get_key_from_event(KeyEvent event)
|
||||||
{
|
{
|
||||||
|
SpinLockGuard _(m_lock);
|
||||||
if (event.shift())
|
if (event.shift())
|
||||||
return m_keycode_to_key_shift[event.keycode];
|
return m_keycode_to_key_shift[event.keycode];
|
||||||
if (event.ralt())
|
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++)
|
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)
|
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/Controller.h>
|
||||||
#include <kernel/Input/PS2/Keyboard.h>
|
#include <kernel/Input/PS2/Keyboard.h>
|
||||||
#include <kernel/Input/PS2/Mouse.h>
|
#include <kernel/Input/PS2/Mouse.h>
|
||||||
#include <kernel/InterruptController.h>
|
|
||||||
#include <kernel/IO.h>
|
#include <kernel/IO.h>
|
||||||
#include <kernel/Timer/Timer.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)
|
BAN::ErrorOr<void> PS2Controller::send_byte(uint16_t port, uint8_t byte)
|
||||||
{
|
{
|
||||||
ASSERT(interrupts_enabled());
|
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms;
|
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms;
|
||||||
while (SystemTimer::get().ms_since_boot() < timeout)
|
while (SystemTimer::get().ms_since_boot() < timeout)
|
||||||
|
@ -36,7 +34,6 @@ namespace Kernel::Input
|
||||||
|
|
||||||
BAN::ErrorOr<uint8_t> PS2Controller::read_byte()
|
BAN::ErrorOr<uint8_t> PS2Controller::read_byte()
|
||||||
{
|
{
|
||||||
ASSERT(interrupts_enabled());
|
|
||||||
LockGuard _(m_mutex);
|
LockGuard _(m_mutex);
|
||||||
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms;
|
uint64_t timeout = SystemTimer::get().ms_since_boot() + s_ps2_timeout_ms;
|
||||||
while (SystemTimer::get().ms_since_boot() < timeout)
|
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)
|
bool PS2Controller::append_command_queue(PS2Device* device, uint8_t command, uint8_t response_size)
|
||||||
{
|
{
|
||||||
// NOTE: command queue push/pop must be done without interrupts
|
SpinLockGuard _(m_command_lock);
|
||||||
CriticalScope _;
|
|
||||||
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
|
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
|
||||||
{
|
{
|
||||||
dprintln("PS/2 command queue full");
|
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)
|
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
|
SpinLockGuard _(m_command_lock);
|
||||||
CriticalScope _;
|
|
||||||
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
|
if (m_command_queue.size() + 1 >= m_command_queue.capacity())
|
||||||
{
|
{
|
||||||
dprintln("PS/2 command queue full");
|
dprintln("PS/2 command queue full");
|
||||||
|
@ -141,7 +136,10 @@ namespace Kernel::Input
|
||||||
|
|
||||||
void PS2Controller::update_command_queue()
|
void PS2Controller::update_command_queue()
|
||||||
{
|
{
|
||||||
ASSERT(interrupts_enabled());
|
Command command_copy;
|
||||||
|
|
||||||
|
{
|
||||||
|
SpinLockGuard _(m_command_lock);
|
||||||
|
|
||||||
if (m_command_queue.empty())
|
if (m_command_queue.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -158,18 +156,18 @@ namespace Kernel::Input
|
||||||
}
|
}
|
||||||
ASSERT(command.send_index < command.out_count);
|
ASSERT(command.send_index < command.out_count);
|
||||||
command.state = Command::State::WaitingAck;
|
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_copy = command;
|
||||||
{
|
|
||||||
command.state = Command::State::Sending;
|
|
||||||
dwarnln_if(DEBUG_PS2, "PS/2 send command byte: {}", ret.error());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_command_send_time = SystemTimer::get().ms_since_boot();
|
||||||
|
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)
|
bool PS2Controller::handle_command_byte(PS2Device* device, uint8_t byte)
|
||||||
{
|
{
|
||||||
// NOTE: command queue push/pop must be done without interrupts
|
SpinLockGuard _(m_command_lock);
|
||||||
ASSERT(!interrupts_enabled());
|
|
||||||
|
|
||||||
if (m_command_queue.empty())
|
if (m_command_queue.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <kernel/CriticalScope.h>
|
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/Input/KeyboardLayout.h>
|
#include <kernel/Input/KeyboardLayout.h>
|
||||||
#include <kernel/Input/PS2/Config.h>
|
#include <kernel/Input/PS2/Config.h>
|
||||||
|
@ -165,6 +164,8 @@ namespace Kernel::Input
|
||||||
event.modifier = m_modifiers | (released ? 0 : KeyEvent::Modifier::Pressed);
|
event.modifier = m_modifiers | (released ? 0 : KeyEvent::Modifier::Pressed);
|
||||||
event.keycode = keycode.value();
|
event.keycode = keycode.value();
|
||||||
|
|
||||||
|
SpinLockGuard _(m_event_lock);
|
||||||
|
|
||||||
if (m_event_queue.full())
|
if (m_event_queue.full())
|
||||||
{
|
{
|
||||||
dwarnln("PS/2 event queue full");
|
dwarnln("PS/2 event queue full");
|
||||||
|
@ -192,20 +193,20 @@ namespace Kernel::Input
|
||||||
if (buffer.size() < sizeof(KeyEvent))
|
if (buffer.size() < sizeof(KeyEvent))
|
||||||
return BAN::Error::from_errno(ENOBUFS);
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
while (true)
|
auto state = m_event_lock.lock();
|
||||||
|
while (m_event_queue.empty())
|
||||||
{
|
{
|
||||||
if (m_event_queue.empty())
|
m_event_lock.unlock(state);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
||||||
|
state = m_event_lock.lock();
|
||||||
CriticalScope _;
|
}
|
||||||
if (m_event_queue.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
buffer.as<KeyEvent>() = m_event_queue.front();
|
buffer.as<KeyEvent>() = m_event_queue.front();
|
||||||
m_event_queue.pop();
|
m_event_queue.pop();
|
||||||
|
|
||||||
|
m_event_lock.unlock(state);
|
||||||
|
|
||||||
return sizeof(KeyEvent);
|
return sizeof(KeyEvent);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#include <BAN/ScopeGuard.h>
|
#include <BAN/ScopeGuard.h>
|
||||||
#include <kernel/CriticalScope.h>
|
|
||||||
#include <kernel/FS/DevFS/FileSystem.h>
|
#include <kernel/FS/DevFS/FileSystem.h>
|
||||||
#include <kernel/Input/PS2/Config.h>
|
#include <kernel/Input/PS2/Config.h>
|
||||||
#include <kernel/Input/PS2/Mouse.h>
|
#include <kernel/Input/PS2/Mouse.h>
|
||||||
|
@ -158,6 +157,8 @@ namespace Kernel::Input
|
||||||
event.scroll_event.scroll = rel_z;
|
event.scroll_event.scroll = rel_z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpinLockGuard _(m_event_lock);
|
||||||
|
|
||||||
for (int i = 0; i < event_count; i++)
|
for (int i = 0; i < event_count; i++)
|
||||||
{
|
{
|
||||||
if (m_event_queue.full())
|
if (m_event_queue.full())
|
||||||
|
@ -176,20 +177,20 @@ namespace Kernel::Input
|
||||||
if (buffer.size() < sizeof(MouseEvent))
|
if (buffer.size() < sizeof(MouseEvent))
|
||||||
return BAN::Error::from_errno(ENOBUFS);
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
while (true)
|
auto state = m_event_lock.lock();
|
||||||
|
while (m_event_queue.empty())
|
||||||
{
|
{
|
||||||
if (m_event_queue.empty())
|
m_event_lock.unlock(state);
|
||||||
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
TRY(Thread::current().block_or_eintr_indefinite(m_semaphore));
|
||||||
|
state = m_event_lock.lock();
|
||||||
CriticalScope _;
|
}
|
||||||
if (m_event_queue.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
buffer.as<MouseEvent>() = m_event_queue.front();
|
buffer.as<MouseEvent>() = m_event_queue.front();
|
||||||
m_event_queue.pop();
|
m_event_queue.pop();
|
||||||
|
|
||||||
|
m_event_lock.unlock(state);
|
||||||
|
|
||||||
return sizeof(MouseEvent);
|
return sizeof(MouseEvent);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue