1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 18:18:12 +00:00

Rework WindowServer to use select() in its main event loop.

The system can finally idle without burning CPU. :^)

There are some issues with scheduling making the mouse cursor sloppy
and unresponsive that need to be dealt with.
This commit is contained in:
Andreas Kling 2019-01-16 17:20:58 +01:00
parent f7ca6d254d
commit 4fef895eda
15 changed files with 121 additions and 33 deletions

View file

@ -125,7 +125,12 @@ ssize_t Keyboard::read(Process&, byte* buffer, size_t size)
while ((size_t)nread < size) {
if (m_queue.is_empty())
break;
buffer[nread++] = m_queue.dequeue().character;
// Don't return partial data frames.
if ((size - nread) < 2)
break;
auto key = m_queue.dequeue();
buffer[nread++] = key.character;
buffer[nread++] = key.modifiers;
}
return nread;
}

View file

@ -32,16 +32,16 @@ public:
void set_client(KeyboardClient* client) { m_client = client; }
// ^CharacterDevice
virtual ssize_t read(Process&, byte* buffer, size_t) override;
virtual bool can_read(Process&) const override;
virtual ssize_t write(Process&, const byte* buffer, size_t) override;
virtual bool can_write(Process&) const override { return true; }
private:
// ^IRQHandler
virtual void handle_irq() override;
// ^CharacterDevice
virtual ssize_t read(Process&, byte* buffer, size_t) override;
virtual ssize_t write(Process&, const byte* buffer, size_t) override;
virtual bool can_read(Process&) const override;
virtual bool can_write(Process&) const override { return true; }
void emit(byte);
KeyboardClient* m_client { nullptr };

View file

@ -537,7 +537,7 @@ bool MemoryManager::validate_user_read(const Process& process, LinearAddress lad
auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
if (!pte.is_present())
return false;
if (!pte.is_user_allowed())
if (process.isRing3() && !pte.is_user_allowed())
return false;
return true;
}
@ -552,7 +552,7 @@ bool MemoryManager::validate_user_write(const Process& process, LinearAddress la
auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
if (!pte.is_present())
return false;
if (!pte.is_user_allowed())
if (process.isRing3() && !pte.is_user_allowed())
return false;
if (!pte.is_writable())
return false;

View file

@ -129,6 +129,7 @@ ssize_t PS2MouseDevice::read(Process&, byte* buffer, size_t size)
while ((size_t)nread < size) {
if (m_queue.is_empty())
break;
// FIXME: Don't return partial data frames.
buffer[nread++] = m_queue.dequeue();
}
return nread;

View file

@ -1295,6 +1295,7 @@ int Process::sys$open(const char* path, int options)
if (number_of_open_file_descriptors() >= m_max_open_file_descriptors)
return -EMFILE;
int error = -EWHYTHO;
ASSERT(cwd_inode());
auto descriptor = VFS::the().open(path, error, options, cwd_inode()->identifier());
if (!descriptor)
return error;
@ -1960,8 +1961,15 @@ int Process::sys$select(const Syscall::SC_select_params* params)
transfer_fds(writefds, m_select_write_fds);
transfer_fds(readfds, m_select_read_fds);
block(BlockedSelect);
Scheduler::yield();
#ifdef DEBUG_IO
dbgprintf("%s<%u> selecting on (read:%u, write:%u)\n", name().characters(), pid(), m_select_read_fds.size(), m_select_write_fds.size());
#endif
if (!m_wakeup_requested) {
block(BlockedSelect);
Scheduler::yield();
}
m_wakeup_requested = false;
int markedfds = 0;
@ -1989,3 +1997,11 @@ int Process::sys$select(const Syscall::SC_select_params* params)
return markedfds;
}
Inode* Process::cwd_inode()
{
// FIXME: This is retarded factoring.
if (!m_cwd)
m_cwd = VFS::the().root_inode();
return m_cwd.ptr();
}

View file

@ -236,7 +236,7 @@ public:
template<typename T> bool validate_read_typed(T* value, size_t count = 1) { return validate_read(value, sizeof(T) * count); }
template<typename T> bool validate_write_typed(T* value, size_t count = 1) { return validate_write(value, sizeof(T) * count); }
Inode* cwd_inode() { return m_cwd.ptr(); }
Inode* cwd_inode();
Inode* executable_inode() { return m_executable.ptr(); }
size_t number_of_open_file_descriptors() const;
@ -256,6 +256,9 @@ public:
Vector<GUI_Event>& gui_events() { return m_gui_events; }
SpinLock& gui_events_lock() { return m_gui_events_lock; }
bool wakeup_requested() { return m_wakeup_requested; }
void request_wakeup() { m_wakeup_requested = true; }
private:
friend class MemoryManager;
friend class Scheduler;
@ -357,6 +360,8 @@ private:
Vector<GUI_Event> m_gui_events;
SpinLock m_gui_events_lock;
int m_next_window_id { 1 };
dword m_wakeup_requested { false };
};
extern Process* current;

View file

@ -108,8 +108,7 @@ int Process::gui$invalidate_window(int window_id)
if (it == m_windows.end())
return -EBADWINDOW;
auto& window = *(*it).value;
// FIXME: This should queue up a message that the window server process can read.
// Poking into its data structures is not good.
WSEventLoop::the().post_event(&window, make<WSEvent>(WSEvent::WM_Invalidate));
WSEventLoop::the().server_process().request_wakeup();
return 0;
}

View file

@ -65,6 +65,11 @@ bool Scheduler::pick_next()
}
if (process.state() == Process::BlockedSelect) {
if (process.wakeup_requested()) {
process.m_wakeup_requested = false;
process.unblock();
return true;
}
for (int fd : process.m_select_read_fds) {
if (process.m_fds[fd].descriptor->can_read(process)) {
process.unblock();

View file

@ -37,6 +37,7 @@ VirtualConsole* tty3;
Keyboard* keyboard;
PS2MouseDevice* ps2mouse;
GUIEventDevice* gui_event_device;
VFS* vfs;
#ifdef STRESS_TEST_SPAWNING
static void spawn_stress() NORETURN;
@ -62,8 +63,6 @@ static void init_stage2()
{
Syscall::initialize();
auto vfs = make<VFS>();
auto dev_zero = make<ZeroDevice>();
vfs->register_character_device(*dev_zero);
@ -138,6 +137,9 @@ void init()
gdt_init();
idt_init();
VFS::initialize_globals();
vfs = new VFS;
keyboard = new Keyboard;
ps2mouse = new PS2MouseDevice;
gui_event_device = new GUIEventDevice;
@ -153,7 +155,6 @@ void init()
MemoryManager::initialize();
VFS::initialize_globals();
StringImpl::initialize_globals();
PIT::initialize();

View file

@ -8,6 +8,7 @@ mknod mnt/dev/tty0 c 4 0
mknod mnt/dev/tty1 c 4 1
mknod mnt/dev/tty2 c 4 2
mknod mnt/dev/tty3 c 4 3
mknod mnt/dev/keyboard c 85 1
mknod mnt/dev/psaux c 10 1
mknod mnt/dev/ptmx c 5 2
mknod mnt/dev/ptm0 c 10 0