1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 04:27:45 +00:00

Move WindowServer to userspace.

This is a monster patch that required changing a whole bunch of things.
There are performance and stability issues all over the place, but it works.
Pretty cool, I have to admit :^)
This commit is contained in:
Andreas Kling 2019-02-17 00:13:47 +01:00
parent 0b1b21d622
commit 640360e958
41 changed files with 325 additions and 463 deletions

View file

@ -95,9 +95,9 @@ Region* BochsVGADevice::mmap(Process& process, LinearAddress preferred_laddr, si
0,
"BochsVGA Framebuffer",
true, true);
kprintf("BochsVGA: %s(%u) created Region{%p} for framebuffer P%x\n",
kprintf("BochsVGA: %s(%u) created Region{%p} with size %u for framebuffer P%x with laddr L%x\n",
process.name().characters(), process.pid(),
region, framebuffer_address().as_ptr());
region, region->size(), framebuffer_address().as_ptr(), region->laddr().get());
ASSERT(region);
return region;
}

View file

@ -10,6 +10,7 @@
#include <Kernel/Socket.h>
#include <Kernel/Process.h>
#include <Kernel/BlockDevice.h>
#include <Kernel/MemoryManager.h>
RetainPtr<FileDescriptor> FileDescriptor::create(RetainPtr<Inode>&& inode)
{
@ -54,6 +55,10 @@ FileDescriptor::FileDescriptor(RetainPtr<Socket>&& socket, SocketRole role)
FileDescriptor::~FileDescriptor()
{
if (m_socket) {
m_socket->close(m_socket_role);
m_socket = nullptr;
}
if (m_device) {
m_device->close();
m_device = nullptr;
@ -364,6 +369,7 @@ Region* FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offse
// FIXME: Implement mapping at a client-specified address. Most of the support is already in plcae.
ASSERT(laddr.as_ptr() == nullptr);
auto* region = process.allocate_file_backed_region(LinearAddress(), size, inode(), move(region_name), prot & PROT_READ, prot & PROT_WRITE);
region->page_in();
return region;
}

View file

@ -108,3 +108,20 @@ enum KeyCode : byte {
Key_Tilde,
Key_Backtick,
};
enum KeyModifier {
Mod_Alt = 0x01,
Mod_Ctrl = 0x02,
Mod_Shift = 0x04,
Is_Press = 0x80,
};
struct KeyEvent {
KeyCode key { Key_Invalid };
byte character { 0 };
byte flags { 0 };
bool alt() const { return flags & Mod_Alt; }
bool ctrl() const { return flags & Mod_Ctrl; }
bool shift() const { return flags & Mod_Shift; }
bool is_press() const { return flags & Is_Press; }
};

View file

@ -12,22 +12,7 @@ class KeyboardClient;
class Keyboard final : public IRQHandler, public CharacterDevice {
AK_MAKE_ETERNAL
public:
enum Modifier {
Mod_Alt = 0x01,
Mod_Ctrl = 0x02,
Mod_Shift = 0x04,
Is_Press = 0x80,
};
struct Event {
KeyCode key { Key_Invalid };
byte character { 0 };
byte flags { 0 };
bool alt() const { return flags & Mod_Alt; }
bool ctrl() const { return flags & Mod_Ctrl; }
bool shift() const { return flags & Mod_Shift; }
bool is_press() const { return flags & Is_Press; }
};
using Event = KeyEvent;
[[gnu::pure]] static Keyboard& the();

View file

@ -106,37 +106,54 @@ bool LocalSocket::connect(const sockaddr* address, socklen_t address_size, int&
return true;
}
void LocalSocket::close(SocketRole role)
{
if (role == SocketRole::Accepted)
m_server_closed = true;
else if (role == SocketRole::Connected)
m_client_closed = true;
}
bool LocalSocket::can_read(SocketRole role) const
{
if (m_bound && is_listening())
return can_accept();
if (role == SocketRole::Accepted)
return !m_for_server.is_empty();
else
return !m_for_client.is_empty();
return m_client_closed || !m_for_server.is_empty();
else if (role == SocketRole::Connected)
return m_server_closed || !m_for_client.is_empty();
ASSERT_NOT_REACHED();
}
ssize_t LocalSocket::read(SocketRole role, byte* buffer, size_t size)
{
if (role == SocketRole::Accepted)
return m_for_server.read(buffer, size);
else
else if (role == SocketRole::Connected)
return m_for_client.read(buffer, size);
ASSERT_NOT_REACHED();
}
ssize_t LocalSocket::write(SocketRole role, const byte* data, size_t size)
{
if (role == SocketRole::Accepted)
if (role == SocketRole::Accepted) {
if (m_client_closed)
return -EPIPE;
return m_for_client.write(data, size);
else
} else if (role == SocketRole::Connected) {
if (m_client_closed)
return -EPIPE;
return m_for_server.write(data, size);
}
ASSERT_NOT_REACHED();
}
bool LocalSocket::can_write(SocketRole role) const
{
if (role == SocketRole::Accepted)
return m_for_client.bytes_in_write_buffer() < 4096;
else
return m_for_server.bytes_in_write_buffer() < 4096;
return m_client_closed || m_for_client.bytes_in_write_buffer() < 4096;
else if (role == SocketRole::Connected)
return m_server_closed || m_for_server.bytes_in_write_buffer() < 4096;
ASSERT_NOT_REACHED();
}

View file

@ -13,7 +13,7 @@ public:
virtual bool bind(const sockaddr*, socklen_t, int& error) override;
virtual bool connect(const sockaddr*, socklen_t, int& error) override;
virtual bool get_address(sockaddr*, socklen_t*) override;
virtual void close(SocketRole) override;
virtual bool can_read(SocketRole) const override;
virtual ssize_t read(SocketRole, byte*, size_t) override;
virtual ssize_t write(SocketRole, const byte*, size_t) override;
@ -27,6 +27,8 @@ private:
RetainPtr<LocalSocket> m_peer;
bool m_bound { false };
bool m_server_closed { false };
bool m_client_closed { false };
sockaddr_un m_address;
DoubleBuffer m_for_client;

View file

@ -51,26 +51,6 @@ VFS_OBJS = \
FileDescriptor.o \
SyntheticFileSystem.o
SHAREDGRAPHICS_OBJS = \
../SharedGraphics/Rect.o \
../SharedGraphics/Painter.o \
../SharedGraphics/Font.o \
../SharedGraphics/Color.o \
../SharedGraphics/CharacterBitmap.o \
../SharedGraphics/GraphicsBitmap.o
WINDOWSERVER_OBJS = \
../WindowServer/WSMessageReceiver.o \
../WindowServer/WSMessageLoop.o \
../WindowServer/WSWindow.o \
../WindowServer/WSWindowManager.o \
../WindowServer/WSScreen.o \
../WindowServer/WSMenuBar.o \
../WindowServer/WSMenu.o \
../WindowServer/WSMenuItem.o \
../WindowServer/WSClientConnection.o \
../WindowServer/main.o
AK_OBJS = \
../AK/String.o \
../AK/StringImpl.o \
@ -78,7 +58,7 @@ AK_OBJS = \
../AK/FileSystemPath.o \
../AK/StdLibExtras.o
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS) $(WINDOWSERVER_OBJS) $(SHAREDGRAPHICS_OBJS)
OBJS = $(KERNEL_OBJS) $(VFS_OBJS) $(AK_OBJS)
NASM = nasm
KERNEL = kernel
@ -89,7 +69,7 @@ STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
KERNEL_FLAGS = -ffreestanding -fno-stack-protector -fno-ident -fno-builtin
WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings -Wimplicit-fallthrough
FLAVOR_FLAGS = -mregparm=3 -march=i386 -m32 -fno-exceptions -fno-rtti -fmerge-all-constants -fno-unroll-loops -fno-pie -fno-pic
OPTIMIZATION_FLAGS = -Oz -fno-asynchronous-unwind-tables -fno-omit-frame-pointer
OPTIMIZATION_FLAGS = -Os -fno-asynchronous-unwind-tables -fno-omit-frame-pointer
INCLUDE_FLAGS = -I.. -I.
#SUGGEST_FLAGS = -Wsuggest-final-types -Wsuggest-final-methods -Wsuggest-override #-Wsuggest-attribute=noreturn

View file

@ -581,9 +581,12 @@ bool MemoryManager::validate_user_write(const Process& process, LinearAddress la
RetainPtr<Region> Region::clone()
{
InterruptDisabler disabler;
if (m_shared || (m_readable && !m_writable)) {
dbgprintf("%s<%u> Region::clone(): sharing %s (L%x)\n",
current->name().characters(),
current->pid(),
m_name.characters(),
laddr().get());
// Create a new region backed by the same VMObject.
return adopt(*new Region(laddr(), size(), m_vmo.copy_ref(), m_offset_in_vmo, String(m_name), m_readable, m_writable));
}

View file

@ -142,6 +142,7 @@ public:
const VMObject& vmo() const { return *m_vmo; }
VMObject& vmo() { return *m_vmo; }
bool is_shared() const { return m_shared; }
void set_shared(bool shared) { m_shared = shared; }
bool is_bitmap() const { return m_is_bitmap; }

View file

@ -18,16 +18,17 @@
#include "Scheduler.h"
#include "FIFO.h"
#include "KSyms.h"
#include <WindowServer/WSMessageLoop.h>
#include <Kernel/Socket.h>
#include "MasterPTY.h"
#include "elf.h"
#include <AK/StringBuilder.h>
//#define DEBUG_IO
//#define TASK_DEBUG
//#define FORK_DEBUG
#define SIGNAL_DEBUG
#define MAX_PROCESS_GIDS 32
//#define SHARED_BUFFER_DEBUG
static const dword default_kernel_stack_size = 16384;
static const dword default_userspace_stack_size = 65536;
@ -49,7 +50,6 @@ void Process::initialize()
s_hostname = new String("courage");
s_hostname_lock = new Lock;
Scheduler::initialize();
new WSMessageLoop;
}
Vector<pid_t> Process::all_pids()
@ -167,11 +167,11 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
if ((dword)addr & ~PAGE_MASK)
return (void*)-EINVAL;
if (flags & MAP_ANONYMOUS) {
// FIXME: Implement mapping at a client-specified address. Most of the support is already in plcae.
ASSERT(addr == nullptr);
auto* region = allocate_region(LinearAddress(), size, "mmap", prot & PROT_READ, prot & PROT_WRITE, false);
auto* region = allocate_region(LinearAddress((dword)addr), size, "mmap", prot & PROT_READ, prot & PROT_WRITE, false);
if (!region)
return (void*)-ENOMEM;
if (flags & MAP_SHARED)
region->set_shared(true);
return region->laddr().as_ptr();
}
if (offset & ~PAGE_MASK)
@ -184,6 +184,8 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
auto* region = descriptor->mmap(*this, LinearAddress((dword)addr), offset, size, prot);
if (!region)
return (void*)-ENOMEM;
if (flags & MAP_SHARED)
region->set_shared(true);
return region->laddr().as_ptr();
}
@ -191,9 +193,9 @@ int Process::sys$munmap(void* addr, size_t size)
{
auto* region = region_from_range(LinearAddress((dword)addr), size);
if (!region)
return -1;
return -EINVAL;
if (!deallocate_region(*region))
return -1;
return -EINVAL;
return 0;
}
@ -2136,9 +2138,6 @@ void Process::finalize()
{
ASSERT(current == g_finalizer);
if (WSMessageLoop::the().running())
WSMessageLoop::the().notify_client_died(gui_client_id());
m_fds.clear();
m_tty = nullptr;
disown_all_shared_buffers();
@ -2367,13 +2366,17 @@ struct SharedBuffer {
{
if (m_pid1 == process.pid()) {
++m_pid1_retain_count;
if (!m_pid1_region)
if (!m_pid1_region) {
m_pid1_region = process.allocate_region_with_vmo(LinearAddress(), size(), m_vmo.copy_ref(), 0, "SharedBuffer", true, true);
m_pid1_region->set_shared(true);
}
return m_pid1_region->laddr().as_ptr();
} else if (m_pid2 == process.pid()) {
++m_pid2_retain_count;
if (!m_pid2_region)
if (!m_pid2_region) {
m_pid2_region = process.allocate_region_with_vmo(LinearAddress(), size(), m_vmo.copy_ref(), 0, "SharedBuffer", true, true);
m_pid2_region->set_shared(true);
}
return m_pid2_region->laddr().as_ptr();
}
return nullptr;
@ -2445,7 +2448,9 @@ void SharedBuffer::destroy_if_unused()
{
if (!m_pid1_retain_count && !m_pid2_retain_count) {
LOCKER(shared_buffers().lock());
kprintf("Destroying unused SharedBuffer{%p} (pid1: %d, pid2: %d)\n", this, m_pid1, m_pid2);
#ifdef SHARED_BUFFER_DEBUG
dbgprintf("Destroying unused SharedBuffer{%p} (pid1: %d, pid2: %d)\n", this, m_pid1, m_pid2);
#endif
shared_buffers().resource().remove(m_shared_buffer_id);
}
}
@ -2474,7 +2479,11 @@ int Process::sys$create_shared_buffer(pid_t peer_pid, size_t size, void** buffer
int shared_buffer_id = ++s_next_shared_buffer_id;
auto shared_buffer = make<SharedBuffer>(m_pid, peer_pid, size);
shared_buffer->m_pid1_region = allocate_region_with_vmo(LinearAddress(), shared_buffer->size(), shared_buffer->m_vmo.copy_ref(), 0, "SharedBuffer", true, true);
shared_buffer->m_pid1_region->set_shared(true);
*buffer = shared_buffer->m_pid1_region->laddr().as_ptr();
#ifdef SHARED_BUFFER_DEBUG
dbgprintf("%s(%u): Created shared buffer %d (%u bytes, vmo is %u) for sharing with %d\n", name().characters(), pid(),shared_buffer_id, size, shared_buffer->size(), peer_pid);
#endif
shared_buffers().resource().set(shared_buffer_id, move(shared_buffer));
return shared_buffer_id;
}
@ -2486,6 +2495,9 @@ int Process::sys$release_shared_buffer(int shared_buffer_id)
if (it == shared_buffers().resource().end())
return -EINVAL;
auto& shared_buffer = *(*it).value;
#ifdef SHARED_BUFFER_DEBUG
dbgprintf("%s(%u): Releasing shared buffer %d\n", name().characters(), pid(), shared_buffer_id);
#endif
shared_buffer.release(*this);
return 0;
}
@ -2499,5 +2511,8 @@ void* Process::sys$get_shared_buffer(int shared_buffer_id)
auto& shared_buffer = *(*it).value;
if (shared_buffer.pid1() != m_pid && shared_buffer.pid2() != m_pid)
return (void*)-EINVAL;
#ifdef SHARED_BUFFER_DEBUG
dbgprintf("%s(%u): Retaining shared buffer %d\n", name().characters(), pid(), shared_buffer_id);
#endif
return shared_buffer.retain(*this);
}

View file

@ -48,9 +48,6 @@ struct DisplayInfo {
class Process : public InlineLinkedListNode<Process>, public Weakable<Process> {
friend class InlineLinkedListNode<Process>;
friend class WSWindowManager; // FIXME: Make a better API for allocate_region().
friend class GraphicsBitmap; // FIXME: Make a better API for allocate_region().
friend class Font; //FIXME: This is beyond gross.
public:
static Process* create_kernel_process(String&& name, void (*entry)());
static Process* create_user_process(const String& path, uid_t, gid_t, pid_t ppid, int& error, Vector<String>&& arguments = Vector<String>(), Vector<String>&& environment = Vector<String>(), TTY* = nullptr);

View file

@ -28,7 +28,7 @@ public:
virtual bool connect(const sockaddr*, socklen_t, int& error) = 0;
virtual bool get_address(sockaddr*, socklen_t*) = 0;
virtual bool is_local() const { return false; }
virtual void close(SocketRole) = 0;
virtual bool can_read(SocketRole) const = 0;
virtual ssize_t read(SocketRole, byte*, size_t) = 0;
virtual ssize_t write(SocketRole, const byte*, size_t) = 0;

View file

@ -25,9 +25,9 @@
#include "BochsVGADevice.h"
//#define SPAWN_GUITEST
#define SPAWN_LAUNCHER
//#define SPAWN_LAUNCHER
//#define SPAWN_GUITEST2
#define SPAWN_FILE_MANAGER
//#define SPAWN_FILE_MANAGER
//#define SPAWN_FONTEDITOR
//#define SPAWN_MULTIPLE_SHELLS
//#define STRESS_TEST_SPAWNING
@ -101,6 +101,10 @@ VFS* vfs;
int error;
Process::create_user_process("/bin/WindowServer", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0);
if (error != 0) {
dbgprintf("error: %d\n", error);
}
//Process::create_user_process("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, move(environment), tty0);
Process::create_user_process("/bin/Terminal", (uid_t)100, (gid_t)100, (pid_t)0, error, { }, { }, tty0);
#ifdef SPAWN_GUITEST
@ -128,9 +132,6 @@ VFS* vfs;
Process::create_kernel_process("spawn_stress", spawn_stress);
#endif
extern void WindowServer_main();
Process::create_kernel_process("WindowServer", WindowServer_main);
current->sys$exit(0);
ASSERT_NOT_REACHED();
}

View file

@ -10,6 +10,8 @@ $make_cmd -C ../LibGUI clean && \
$make_cmd -C ../LibGUI && \
$make_cmd -C ../Userland clean && \
$make_cmd -C ../Userland && \
$make_cmd -C ../WindowServer clean && \
$make_cmd -C ../WindowServer && \
$make_cmd -C ../Applications/Terminal clean && \
$make_cmd -C ../Applications/Terminal && \
$make_cmd -C ../Applications/FontEditor clean && \

View file

@ -69,6 +69,7 @@ cp -v ../Applications/Launcher/Launcher mnt/bin/Launcher
cp -v ../Applications/Clock/Clock mnt/bin/Clock
cp -v ../Applications/FileManager/FileManager mnt/bin/FileManager
cp -v ../Applications/About/About mnt/bin/About
cp -v ../WindowServer/WindowServer mnt/bin/WindowServer
cp -v kernel.map mnt/
sh sync-local.sh
umount mnt