mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:38:11 +00:00
Kernel: Yet more work on bringing up POSIX SHM.
This commit is contained in:
parent
d6ff64db00
commit
60a819c14a
7 changed files with 97 additions and 9 deletions
|
@ -35,7 +35,7 @@ class CONSUMABLE(unconsumed) Retained {
|
||||||
public:
|
public:
|
||||||
enum AdoptTag { Adopt };
|
enum AdoptTag { Adopt };
|
||||||
|
|
||||||
RETURN_TYPESTATE(unconsumed) Retained(const T& object) : m_ptr(&object) { m_ptr->retain(); }
|
RETURN_TYPESTATE(unconsumed) Retained(const T& object) : m_ptr(const_cast<T*>(&object)) { m_ptr->retain(); }
|
||||||
RETURN_TYPESTATE(unconsumed) Retained(T& object) : m_ptr(&object) { m_ptr->retain(); }
|
RETURN_TYPESTATE(unconsumed) Retained(T& object) : m_ptr(&object) { m_ptr->retain(); }
|
||||||
template<typename U> RETURN_TYPESTATE(unconsumed) Retained(U& object) : m_ptr(&static_cast<T&>(object)) { m_ptr->retain(); }
|
template<typename U> RETURN_TYPESTATE(unconsumed) Retained(U& object) : m_ptr(&static_cast<T&>(object)) { m_ptr->retain(); }
|
||||||
RETURN_TYPESTATE(unconsumed) Retained(AdoptTag, T& object) : m_ptr(&object) { }
|
RETURN_TYPESTATE(unconsumed) Retained(AdoptTag, T& object) : m_ptr(&object) { }
|
||||||
|
|
|
@ -23,6 +23,11 @@ Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Device>&& device)
|
||||||
return adopt(*new FileDescriptor(move(device)));
|
return adopt(*new FileDescriptor(move(device)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<SharedMemory>&& shared_memory)
|
||||||
|
{
|
||||||
|
return adopt(*new FileDescriptor(move(shared_memory)));
|
||||||
|
}
|
||||||
|
|
||||||
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Socket>&& socket, SocketRole role)
|
Retained<FileDescriptor> FileDescriptor::create(RetainPtr<Socket>&& socket, SocketRole role)
|
||||||
{
|
{
|
||||||
return adopt(*new FileDescriptor(move(socket), role));
|
return adopt(*new FileDescriptor(move(socket), role));
|
||||||
|
@ -48,6 +53,11 @@ FileDescriptor::FileDescriptor(RetainPtr<Device>&& device)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileDescriptor::FileDescriptor(RetainPtr<SharedMemory>&& shared_memory)
|
||||||
|
: m_shared_memory(move(shared_memory))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
FileDescriptor::FileDescriptor(RetainPtr<Socket>&& socket, SocketRole role)
|
FileDescriptor::FileDescriptor(RetainPtr<Socket>&& socket, SocketRole role)
|
||||||
: m_socket(move(socket))
|
: m_socket(move(socket))
|
||||||
{
|
{
|
||||||
|
@ -397,6 +407,8 @@ bool FileDescriptor::supports_mmap() const
|
||||||
{
|
{
|
||||||
if (m_inode)
|
if (m_inode)
|
||||||
return true;
|
return true;
|
||||||
|
if (m_shared_memory)
|
||||||
|
return true;
|
||||||
if (m_device)
|
if (m_device)
|
||||||
return m_device->is_block_device();
|
return m_device->is_block_device();
|
||||||
return false;
|
return false;
|
||||||
|
@ -409,6 +421,12 @@ Region* FileDescriptor::mmap(Process& process, LinearAddress laddr, size_t offse
|
||||||
if (is_block_device())
|
if (is_block_device())
|
||||||
return static_cast<BlockDevice&>(*m_device).mmap(process, laddr, offset, size);
|
return static_cast<BlockDevice&>(*m_device).mmap(process, laddr, offset, size);
|
||||||
|
|
||||||
|
if (is_shared_memory()) {
|
||||||
|
if (!shared_memory()->vmo())
|
||||||
|
return nullptr;
|
||||||
|
return process.allocate_region_with_vmo(laddr, size, *shared_memory()->vmo(), offset, shared_memory()->name(), true, true);
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(m_inode);
|
ASSERT(m_inode);
|
||||||
// FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec.
|
// FIXME: If PROT_EXEC, check that the underlying file system isn't mounted noexec.
|
||||||
String region_name;
|
String region_name;
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
#include <AK/Retainable.h>
|
#include <AK/Retainable.h>
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <Kernel/Net/Socket.h>
|
#include <Kernel/Net/Socket.h>
|
||||||
|
#include <Kernel/SharedMemory.h>
|
||||||
|
|
||||||
class TTY;
|
class TTY;
|
||||||
class MasterPTY;
|
class MasterPTY;
|
||||||
class Process;
|
class Process;
|
||||||
class Region;
|
class Region;
|
||||||
class CharacterDevice;
|
class CharacterDevice;
|
||||||
class SharedMemory;
|
|
||||||
|
|
||||||
class FileDescriptor : public Retainable<FileDescriptor> {
|
class FileDescriptor : public Retainable<FileDescriptor> {
|
||||||
public:
|
public:
|
||||||
|
@ -23,6 +23,7 @@ public:
|
||||||
static Retained<FileDescriptor> create(RetainPtr<Socket>&&, SocketRole = SocketRole::None);
|
static Retained<FileDescriptor> create(RetainPtr<Socket>&&, SocketRole = SocketRole::None);
|
||||||
static Retained<FileDescriptor> create(RetainPtr<Inode>&&);
|
static Retained<FileDescriptor> create(RetainPtr<Inode>&&);
|
||||||
static Retained<FileDescriptor> create(RetainPtr<Device>&&);
|
static Retained<FileDescriptor> create(RetainPtr<Device>&&);
|
||||||
|
static Retained<FileDescriptor> create(RetainPtr<SharedMemory>&&);
|
||||||
static Retained<FileDescriptor> create_pipe_writer(FIFO&);
|
static Retained<FileDescriptor> create_pipe_writer(FIFO&);
|
||||||
static Retained<FileDescriptor> create_pipe_reader(FIFO&);
|
static Retained<FileDescriptor> create_pipe_reader(FIFO&);
|
||||||
~FileDescriptor();
|
~FileDescriptor();
|
||||||
|
@ -105,6 +106,7 @@ private:
|
||||||
FileDescriptor(RetainPtr<Socket>&&, SocketRole);
|
FileDescriptor(RetainPtr<Socket>&&, SocketRole);
|
||||||
explicit FileDescriptor(RetainPtr<Inode>&&);
|
explicit FileDescriptor(RetainPtr<Inode>&&);
|
||||||
explicit FileDescriptor(RetainPtr<Device>&&);
|
explicit FileDescriptor(RetainPtr<Device>&&);
|
||||||
|
explicit FileDescriptor(RetainPtr<SharedMemory>&&);
|
||||||
FileDescriptor(FIFO&, FIFO::Direction);
|
FileDescriptor(FIFO&, FIFO::Direction);
|
||||||
|
|
||||||
RetainPtr<Inode> m_inode;
|
RetainPtr<Inode> m_inode;
|
||||||
|
|
|
@ -58,6 +58,14 @@ public:
|
||||||
T& value() { ASSERT(!m_is_error); return *reinterpret_cast<T*>(&m_storage); }
|
T& value() { ASSERT(!m_is_error); return *reinterpret_cast<T*>(&m_storage); }
|
||||||
const T& value() const { ASSERT(!m_is_error); return *reinterpret_cast<T*>(&m_storage); }
|
const T& value() const { ASSERT(!m_is_error); return *reinterpret_cast<T*>(&m_storage); }
|
||||||
|
|
||||||
|
T release_value()
|
||||||
|
{
|
||||||
|
ASSERT(!m_is_error);
|
||||||
|
T released_value = *reinterpret_cast<T*>(&m_storage);
|
||||||
|
value().~T();
|
||||||
|
return released_value;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char m_storage[sizeof(T)] __attribute__((aligned(sizeof(T))));
|
char m_storage[sizeof(T)] __attribute__((aligned(sizeof(T))));
|
||||||
KResult m_error;
|
KResult m_error;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <Kernel/TTY/MasterPTY.h>
|
#include <Kernel/TTY/MasterPTY.h>
|
||||||
#include <Kernel/ELF/exec_elf.h>
|
#include <Kernel/ELF/exec_elf.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <Kernel/SharedMemory.h>
|
||||||
|
|
||||||
//#define DEBUG_IO
|
//#define DEBUG_IO
|
||||||
//#define TASK_DEBUG
|
//#define TASK_DEBUG
|
||||||
|
@ -2459,14 +2460,22 @@ int Process::sys$shm_open(const char* name, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
if (!validate_read_str(name))
|
if (!validate_read_str(name))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return -ENOTIMPL;
|
int fd = alloc_fd();
|
||||||
|
if (fd < 0)
|
||||||
|
return fd;
|
||||||
|
auto shm_or_error = SharedMemory::open(String(name), flags, mode);
|
||||||
|
if (shm_or_error.is_error())
|
||||||
|
return shm_or_error.error();
|
||||||
|
auto descriptor = FileDescriptor::create(shm_or_error.value().ptr());
|
||||||
|
m_fds[fd].set(move(descriptor), FD_CLOEXEC);
|
||||||
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$shm_unlink(const char* name)
|
int Process::sys$shm_unlink(const char* name)
|
||||||
{
|
{
|
||||||
if (!validate_read_str(name))
|
if (!validate_read_str(name))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return -ENOTIMPL;
|
return SharedMemory::unlink(String(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$ftruncate(int fd, off_t length)
|
int Process::sys$ftruncate(int fd, off_t length)
|
||||||
|
|
|
@ -1,7 +1,48 @@
|
||||||
#include <Kernel/SharedMemory.h>
|
#include <Kernel/SharedMemory.h>
|
||||||
#include <Kernel/VM/VMObject.h>
|
#include <Kernel/VM/VMObject.h>
|
||||||
|
#include <Kernel/Lock.h>
|
||||||
|
#include <Kernel/Process.h>
|
||||||
|
#include <AK/HashMap.h>
|
||||||
|
|
||||||
SharedMemory::SharedMemory()
|
Lockable<HashMap<String, RetainPtr<SharedMemory>>>& shared_memories()
|
||||||
|
{
|
||||||
|
static Lockable<HashMap<String, RetainPtr<SharedMemory>>>* map;
|
||||||
|
if (!map)
|
||||||
|
map = new Lockable<HashMap<String, RetainPtr<SharedMemory>>>;
|
||||||
|
return *map;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResultOr<Retained<SharedMemory>> SharedMemory::open(const String& name, int flags, mode_t mode)
|
||||||
|
{
|
||||||
|
LOCKER(shared_memories().lock());
|
||||||
|
auto it = shared_memories().resource().find(name);
|
||||||
|
if (it != shared_memories().resource().end()) {
|
||||||
|
auto shared_memory = it->value;
|
||||||
|
// FIXME: Improved access checking.
|
||||||
|
if (shared_memory->uid() != current->process().uid())
|
||||||
|
return KResult(-EACCES);
|
||||||
|
return *shared_memory;
|
||||||
|
}
|
||||||
|
auto shared_memory = adopt(*new SharedMemory(name, current->process().uid(), current->process().gid(), mode));
|
||||||
|
shared_memories().resource().set(name, shared_memory.ptr());
|
||||||
|
return shared_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
KResult SharedMemory::unlink(const String& name)
|
||||||
|
{
|
||||||
|
LOCKER(shared_memories().lock());
|
||||||
|
auto it = shared_memories().resource().find(name);
|
||||||
|
if (it == shared_memories().resource().end())
|
||||||
|
return KResult(-ENOENT);
|
||||||
|
shared_memories().resource().remove(it);
|
||||||
|
return KSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedMemory::SharedMemory(const String& name, uid_t uid, gid_t gid, mode_t mode)
|
||||||
|
: m_name(name)
|
||||||
|
, m_uid(uid)
|
||||||
|
, m_gid(gid)
|
||||||
|
, m_mode(mode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,21 +2,31 @@
|
||||||
|
|
||||||
#include <AK/Retainable.h>
|
#include <AK/Retainable.h>
|
||||||
#include <AK/RetainPtr.h>
|
#include <AK/RetainPtr.h>
|
||||||
|
#include <AK/AKString.h>
|
||||||
#include <Kernel/KResult.h>
|
#include <Kernel/KResult.h>
|
||||||
|
#include <Kernel/UnixTypes.h>
|
||||||
|
|
||||||
class VMObject;
|
class VMObject;
|
||||||
|
|
||||||
class SharedMemory : public Retainable<SharedMemory> {
|
class SharedMemory : public Retainable<SharedMemory> {
|
||||||
public:
|
public:
|
||||||
static Retained<SharedMemory> create();
|
static KResultOr<Retained<SharedMemory>> open(const String& name, int flags, mode_t);
|
||||||
|
static KResult unlink(const String& name);
|
||||||
~SharedMemory();
|
~SharedMemory();
|
||||||
|
|
||||||
|
String name() const { return m_name; }
|
||||||
KResult truncate(int);
|
KResult truncate(int);
|
||||||
|
VMObject* vmo() { return m_vmo.ptr(); }
|
||||||
|
const VMObject* vmo() const { return m_vmo.ptr(); }
|
||||||
|
uid_t uid() const { return m_uid; }
|
||||||
|
gid_t gid() const { return m_gid; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedMemory();
|
SharedMemory(const String& name, uid_t, gid_t, mode_t);
|
||||||
|
|
||||||
int m_uid { 0 };
|
String m_name;
|
||||||
int m_gid { 0 };
|
uid_t m_uid { 0 };
|
||||||
|
gid_t m_gid { 0 };
|
||||||
|
mode_t m_mode { 0 };
|
||||||
RetainPtr<VMObject> m_vmo;
|
RetainPtr<VMObject> m_vmo;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue