[kernel] First steps at removing channel objects
This commit does a number of things to start the transition of channels from kernel to user space: - Remove channel objects / syscalls from the kernel - Add mutex type in libj6 - Add condition type in libj6 - Add a `ring` type flag for VMA syscalls to create ring buffers - Implement a rudimentary shared memory channel using all of the above
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "assert.h"
|
||||
#include "memory.h"
|
||||
#include "objects/channel.h"
|
||||
#include "objects/thread.h"
|
||||
#include "objects/vm_area.h"
|
||||
|
||||
extern obj::vm_area_guarded g_kernel_buffers;
|
||||
|
||||
namespace obj {
|
||||
|
||||
constexpr size_t buffer_bytes = mem::kernel_buffer_pages * mem::frame_size;
|
||||
|
||||
channel::channel() :
|
||||
m_len {0},
|
||||
m_data {g_kernel_buffers.get_section()},
|
||||
m_closed {false},
|
||||
m_buffer {reinterpret_cast<uint8_t*>(m_data), buffer_bytes},
|
||||
kobject {kobject::type::channel}
|
||||
{
|
||||
}
|
||||
|
||||
channel::~channel()
|
||||
{
|
||||
if (!closed()) close();
|
||||
}
|
||||
|
||||
size_t
|
||||
channel::enqueue(const util::buffer &data)
|
||||
{
|
||||
util::scoped_lock lock {m_close_lock};
|
||||
|
||||
if (closed()) return 0;
|
||||
|
||||
size_t len = data.count;
|
||||
void *buffer = nullptr;
|
||||
len = m_buffer.reserve(len, &buffer);
|
||||
|
||||
memcpy(buffer, data.pointer, len);
|
||||
m_buffer.commit(len);
|
||||
|
||||
if (len) {
|
||||
thread *t = m_queue.pop_next();
|
||||
|
||||
lock.release();
|
||||
if (t) t->wake();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
channel::dequeue(util::buffer buffer, bool block)
|
||||
{
|
||||
util::scoped_lock lock {m_close_lock};
|
||||
|
||||
if (closed()) return 0;
|
||||
|
||||
void *data = nullptr;
|
||||
size_t avail = m_buffer.get_block(&data);
|
||||
if (!avail && block) {
|
||||
thread &cur = thread::current();
|
||||
m_queue.add_thread(&cur);
|
||||
|
||||
lock.release();
|
||||
cur.block();
|
||||
lock.reacquire();
|
||||
avail = m_buffer.get_block(&data);
|
||||
}
|
||||
|
||||
size_t len = buffer.count > avail ? avail : buffer.count;
|
||||
|
||||
memcpy(buffer.pointer, data, len);
|
||||
m_buffer.consume(len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void
|
||||
channel::close()
|
||||
{
|
||||
util::scoped_lock lock {m_close_lock};
|
||||
m_queue.clear();
|
||||
g_kernel_buffers.return_section(m_data);
|
||||
m_closed = true;
|
||||
}
|
||||
|
||||
} // namespace obj
|
||||
@@ -1,54 +0,0 @@
|
||||
#pragma once
|
||||
/// \file channel.h
|
||||
/// Definition of channel objects and related functions
|
||||
|
||||
#include <j6/cap_flags.h>
|
||||
#include <util/bip_buffer.h>
|
||||
#include <util/counted.h>
|
||||
#include <util/spinlock.h>
|
||||
|
||||
#include "objects/kobject.h"
|
||||
#include "wait_queue.h"
|
||||
|
||||
namespace obj {
|
||||
|
||||
/// Channels are uni-directional means of sending data
|
||||
class channel :
|
||||
public kobject
|
||||
{
|
||||
public:
|
||||
/// Capabilities on a newly constructed channel handle
|
||||
static constexpr j6_cap_t creation_caps = j6_cap_channel_all;
|
||||
static constexpr kobject::type type = kobject::type::channel;
|
||||
|
||||
channel();
|
||||
virtual ~channel();
|
||||
|
||||
/// Put a message into the channel
|
||||
/// \arg data Buffer of data to write
|
||||
/// \returns The number of bytes successfully written
|
||||
size_t enqueue(const util::buffer &data);
|
||||
|
||||
/// Get a message from the channel, copied into a provided buffer
|
||||
/// \arg buffer The buffer to copy data into
|
||||
/// \arg block If true, block the calling thread until there is data
|
||||
/// \returns The number of bytes copied into the provided buffer
|
||||
size_t dequeue(util::buffer buffer, bool block = false);
|
||||
|
||||
/// Mark this channel as closed, all future calls to enqueue or
|
||||
/// dequeue messages will fail with j6_status_closed.
|
||||
void close();
|
||||
|
||||
/// Check if this channel has been closed.
|
||||
inline bool closed() const { return m_closed; }
|
||||
|
||||
private:
|
||||
size_t m_len;
|
||||
uintptr_t m_data;
|
||||
bool m_closed;
|
||||
util::bip_buffer m_buffer;
|
||||
util::spinlock m_close_lock;
|
||||
wait_queue m_queue;
|
||||
};
|
||||
|
||||
} // namespace obj
|
||||
Reference in New Issue
Block a user