[kernel] Re-add channel syscalls

Channels were unused, and while they were listed in syscalls.def, they
had no syscalls listed in their interface. This change adds them back,
and updates them to the curren syscall style.
This commit is contained in:
Justin C. Miller
2022-01-27 22:16:44 -08:00
parent 42d7f4245d
commit 9b75acf0b5
4 changed files with 76 additions and 46 deletions

View File

@@ -1,3 +1,14 @@
object channel : kobject { object channel : kobject {
uid 3ea38b96aa0e54c8 uid 3ea38b96aa0e54c8
method create [constructor]
method close [destructor]
method send {
param data buffer [inout]
}
method receive {
param data buffer [out]
}
} }

View File

@@ -24,63 +24,59 @@ channel::~channel()
if (!closed()) close(); if (!closed()) close();
} }
j6_status_t size_t
channel::enqueue(size_t *len, const void *data) channel::enqueue(const util::buffer &data)
{ {
// TODO: Make this thread safe! util::scoped_lock lock {m_close_lock};
if (closed())
return j6_status_closed;
if (!len || !*len) if (closed()) return 0;
return j6_err_invalid_arg;
if (m_buffer.free_space() == 0)
return j6_err_not_ready;
size_t len = data.count;
void *buffer = nullptr; void *buffer = nullptr;
size_t avail = m_buffer.reserve(*len, &buffer); size_t avail = m_buffer.reserve(len, &buffer);
*len = *len > avail ? avail : *len;
memcpy(buffer, data, *len); len = len > avail ? avail : len;
m_buffer.commit(*len);
memcpy(buffer, data.pointer, len);
m_buffer.commit(len);
if (len)
assert_signal(j6_signal_channel_can_recv);
assert_signal(j6_signal_channel_can_recv);
if (m_buffer.free_space() == 0) if (m_buffer.free_space() == 0)
deassert_signal(j6_signal_channel_can_send); deassert_signal(j6_signal_channel_can_send);
return j6_status_ok; return len;
} }
j6_status_t size_t
channel::dequeue(size_t *len, void *data) channel::dequeue(util::buffer buffer)
{ {
// TODO: Make this thread safe! util::scoped_lock lock {m_close_lock};
if (closed())
return j6_status_closed;
if (!len || !*len) if (closed()) return 0;
return j6_err_invalid_arg;
if (m_buffer.size() == 0) void *data = nullptr;
return j6_err_not_ready; size_t avail = m_buffer.get_block(&data);
size_t len = buffer.count > avail ? avail : buffer.count;
void *buffer = nullptr; memcpy(data, buffer.pointer, len);
size_t avail = m_buffer.get_block(&buffer); m_buffer.consume(len);
*len = *len > avail ? avail : *len;
memcpy(data, buffer, *len); if (len)
m_buffer.consume(*len); assert_signal(j6_signal_channel_can_send);
assert_signal(j6_signal_channel_can_send);
if (m_buffer.size() == 0) if (m_buffer.size() == 0)
deassert_signal(j6_signal_channel_can_recv); deassert_signal(j6_signal_channel_can_recv);
return j6_status_ok; return len;
} }
void void
channel::close() channel::close()
{ {
util::scoped_lock lock {m_close_lock};
kobject::close(); kobject::close();
g_kernel_buffers.return_section(m_data); g_kernel_buffers.return_section(m_data);
} }

View File

@@ -4,12 +4,14 @@
#include <j6/signals.h> #include <j6/signals.h>
#include <util/bip_buffer.h> #include <util/bip_buffer.h>
#include <util/counted.h>
#include <util/spinlock.h>
#include "objects/kobject.h" #include "objects/kobject.h"
namespace obj { namespace obj {
/// Channels are bi-directional means of sending messages /// Channels are uni-directional means of sending data
class channel : class channel :
public kobject public kobject
{ {
@@ -29,17 +31,14 @@ public:
inline bool can_receive() const { return check_signal(j6_signal_channel_can_recv); } inline bool can_receive() const { return check_signal(j6_signal_channel_can_recv); }
/// Put a message into the channel /// Put a message into the channel
/// \arg len [in] Bytes in data buffer [out] number of bytes written /// \arg data Buffer of data to write
/// \arg data Pointer to the message data /// \returns The number of bytes successfully written
/// \returns j6_status_ok on success size_t enqueue(const util::buffer &data);
j6_status_t enqueue(size_t *len, const void *data);
/// Get a message from the channel, copied into a provided buffer /// Get a message from the channel, copied into a provided buffer
/// \arg len On input, the size of the provided buffer. On output, /// \arg buffer The buffer to copy data into
/// the size of the message copied into the buffer. /// \returns The number of bytes copied into the provided buffer
/// \arg data Pointer to the buffer size_t dequeue(util::buffer buffer);
/// \returns j6_status_ok on success
j6_status_t dequeue(size_t *len, void *data);
/// Mark this channel as closed, all future calls to enqueue or /// Mark this channel as closed, all future calls to enqueue or
/// dequeue messages will fail with j6_status_closed. /// dequeue messages will fail with j6_status_closed.
@@ -52,6 +51,7 @@ private:
size_t m_len; size_t m_len;
uintptr_t m_data; uintptr_t m_data;
util::bip_buffer m_buffer; util::bip_buffer m_buffer;
util::spinlock m_close_lock;
}; };
} // namespace obj } // namespace obj

View File

@@ -1,5 +1,6 @@
#include <j6/errors.h> #include <j6/errors.h>
#include <j6/types.h> #include <j6/types.h>
#include <util/counted.h>
#include "objects/channel.h" #include "objects/channel.h"
#include "syscalls/helpers.h" #include "syscalls/helpers.h"
@@ -16,15 +17,37 @@ channel_create(j6_handle_t *self)
} }
j6_status_t j6_status_t
channel_send(channel *self, size_t *len, void *data) channel_send(channel *self, void *data, size_t *data_len)
{ {
return self->enqueue(len, data); if (self->closed())
return j6_status_closed;
const util::buffer buffer {data, *data_len};
*data_len = self->enqueue(buffer);
return j6_status_ok;
} }
j6_status_t j6_status_t
channel_receive(channel *self, size_t *len, void *data) channel_receive(channel *self, void *data, size_t *data_len)
{ {
return self->dequeue(len, data); if (self->closed())
return j6_status_closed;
util::buffer buffer {data, *data_len};
*data_len = self->dequeue(buffer);
return j6_status_ok;
}
j6_status_t
channel_close(channel *self)
{
if (self->closed())
return j6_status_closed;
self->close();
return j6_status_ok;
} }
} // namespace syscalls } // namespace syscalls