Change Semaphore -> ThreadBlocker
This was not a semaphore, I just named it one because I didn't know
what semaphore was. I have meant to change this sooner, but it was in
no way urgent :D
Implement SMP events. Processors can now be sent SMP events through
IPIs. SMP events can be sent either to a single processor or broadcasted
to every processor.
PageTable::{map_page,map_range,unmap_page,unmap_range}() now send SMP
event to invalidate TLB caches for the changed pages.
Scheduler no longer uses a global run queue. Each processor has its own
scheduler that keeps track of the load on the processor. Once every
second schedulers do load balancing. Schedulers have no access to other
processors' schedulers, they just see approximate loads. If scheduler
decides that it has too much load, it will send a thread to another
processor through a SMP event.
Schedulers are currently run using the timer interrupt on BSB. This
should be not the case, and each processor should use its LAPIC timer
for interrupts. There is no reason to broadcast SMP event to all
processors when BSB gets timer interrupt.
Old scheduler only achieved 20% idle load on qemu. That was probably a
very inefficient implementation. This new scheduler seems to average
around 1% idle load. This is much closer to what I would expect. On my
own laptop idle load seems to be only around 0.5% on each processor.
115 lines
2.7 KiB
C++
115 lines
2.7 KiB
C++
#pragma once
|
|
|
|
#include <BAN/ByteSpan.h>
|
|
|
|
#include <kernel/Device/Device.h>
|
|
#include <kernel/ThreadBlocker.h>
|
|
|
|
namespace Kernel
|
|
{
|
|
|
|
class InputDevice : public CharacterDevice, public BAN::Weakable<InputDevice>
|
|
{
|
|
public:
|
|
enum class Type
|
|
{
|
|
Mouse,
|
|
Keyboard,
|
|
};
|
|
|
|
public:
|
|
InputDevice(Type type);
|
|
|
|
BAN::StringView name() const final override { return m_name; }
|
|
dev_t rdev() const final override { return m_rdev; }
|
|
|
|
protected:
|
|
void add_event(BAN::ConstByteSpan);
|
|
|
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
|
|
bool can_read_impl() const override { SpinLockGuard _(m_event_lock); return m_event_count > 0; }
|
|
bool can_write_impl() const override { return false; }
|
|
bool has_error_impl() const override { return false; }
|
|
|
|
|
|
private:
|
|
BAN::ErrorOr<size_t> read_non_block(BAN::ByteSpan);
|
|
|
|
private:
|
|
const dev_t m_rdev;
|
|
const BAN::String m_name;
|
|
|
|
const Type m_type;
|
|
|
|
mutable SpinLock m_event_lock;
|
|
ThreadBlocker m_event_thread_blocker;
|
|
|
|
static constexpr size_t m_max_event_count { 128 };
|
|
|
|
BAN::Vector<uint8_t> m_event_buffer;
|
|
const size_t m_event_size;
|
|
size_t m_event_tail { 0 };
|
|
size_t m_event_head { 0 };
|
|
size_t m_event_count { 0 };
|
|
|
|
friend class KeyboardDevice;
|
|
friend class MouseDevice;
|
|
};
|
|
|
|
|
|
|
|
class KeyboardDevice : public CharacterDevice
|
|
{
|
|
public:
|
|
static BAN::ErrorOr<BAN::RefPtr<KeyboardDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
|
|
|
void notify() { m_thread_blocker.unblock(); }
|
|
|
|
private:
|
|
KeyboardDevice(mode_t mode, uid_t uid, gid_t gid);
|
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
|
|
bool can_read_impl() const override;
|
|
bool can_write_impl() const override { return false; }
|
|
bool has_error_impl() const override { return false; }
|
|
|
|
BAN::StringView name() const final override { return m_name; }
|
|
dev_t rdev() const final override { return m_rdev; }
|
|
|
|
private:
|
|
const dev_t m_rdev;
|
|
const BAN::StringView m_name;
|
|
ThreadBlocker m_thread_blocker;
|
|
|
|
friend class BAN::RefPtr<KeyboardDevice>;
|
|
};
|
|
|
|
class MouseDevice : public CharacterDevice
|
|
{
|
|
public:
|
|
static BAN::ErrorOr<BAN::RefPtr<MouseDevice>> create(mode_t mode, uid_t uid, gid_t gid);
|
|
|
|
void notify() { m_thread_blocker.unblock(); }
|
|
|
|
private:
|
|
MouseDevice(mode_t mode, uid_t uid, gid_t gid);
|
|
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
|
|
|
|
bool can_read_impl() const override;
|
|
bool can_write_impl() const override { return false; }
|
|
bool has_error_impl() const override { return false; }
|
|
|
|
BAN::StringView name() const final override { return m_name; }
|
|
dev_t rdev() const final override { return m_rdev; }
|
|
|
|
private:
|
|
const dev_t m_rdev;
|
|
const BAN::StringView m_name;
|
|
ThreadBlocker m_thread_blocker;
|
|
|
|
friend class BAN::RefPtr<MouseDevice>;
|
|
};
|
|
|
|
}
|