Add a basic IPC setup with Channel Object.

Pass a process a channel endpoint on startup that it will use to
get it's initial capabilities.
This commit is contained in:
Drew Galbraith 2023-06-07 08:24:10 -07:00
parent b79ec07636
commit 81b925eea0
15 changed files with 341 additions and 20 deletions

61
zion/object/channel.cpp Normal file
View file

@ -0,0 +1,61 @@
#include "object/channel.h"
#include "include/zerrors.h"
Pair<RefPtr<Channel>, RefPtr<Channel>> Channel::CreateChannelPair() {
auto c1 = MakeRefCounted<Channel>();
auto c2 = MakeRefCounted<Channel>();
c1->SetPeer(c2);
c2->SetPeer(c1);
return {c1, c2};
}
uint64_t Channel::Write(const ZMessage& msg) {
return peer_->EnqueueMessage(msg);
}
uint64_t Channel::Read(ZMessage& msg) {
if (pending_messages_.size() == 0) {
dbgln("Unimplemented add blocking.");
return ZE_UNIMPLEMENTED;
}
Message next_msg = pending_messages_.PeekFront();
if (next_msg.num_bytes > msg.num_bytes) {
return ZE_BUFF_SIZE;
}
msg.type = next_msg.type;
msg.num_bytes = next_msg.num_bytes;
msg.num_caps = 0;
for (uint64_t i = 0; i < msg.num_bytes; i++) {
msg.bytes[i] = next_msg.bytes[i];
}
pending_messages_.PopFront();
return Z_OK;
}
uint64_t Channel::EnqueueMessage(const ZMessage& msg) {
if (msg.num_caps > 0) {
dbgln("Unimplemented passing caps on channel");
return ZE_UNIMPLEMENTED;
}
if (msg.num_bytes > 0x1000) {
dbgln("Large message size unimplemented: %x", msg.num_bytes);
return ZE_INVALID;
}
Message message{
.type = msg.type,
.num_bytes = msg.num_bytes,
.bytes = new uint8_t[msg.num_bytes],
};
for (uint64_t i = 0; i < msg.num_bytes; i++) {
message.bytes[i] = msg.bytes[i];
}
pending_messages_.PushBack(message);
return Z_OK;
}

40
zion/object/channel.h Normal file
View file

@ -0,0 +1,40 @@
#pragma once
#include "capability/capability.h"
#include "lib/linked_list.h"
#include "lib/pair.h"
#include "lib/ref_ptr.h"
#include "object/kernel_object.h"
#include "usr/zcall_internal.h"
class Channel : public KernelObject {
public:
static Pair<RefPtr<Channel>, RefPtr<Channel>> CreateChannelPair();
RefPtr<Channel> peer() { return peer_; }
uint64_t Write(const ZMessage& msg);
uint64_t Read(ZMessage& msg);
private:
// FIXME: We will likely never close the channel based on this
// circular dependency.
RefPtr<Channel> peer_{nullptr};
struct Message {
uint64_t type;
uint64_t num_bytes;
uint8_t* bytes;
};
// FIXME: This is probably dangerous because of an
// implicit shallow copy.
LinkedList<Message> pending_messages_;
friend class MakeRefCountedFriend<Channel>;
Channel() {}
void SetPeer(const RefPtr<Channel>& peer) { peer_ = peer; }
uint64_t EnqueueMessage(const ZMessage& msg);
};

View file

@ -62,10 +62,25 @@ void Process::CheckState() {
state_ = FINISHED;
}
RefPtr<Capability> Process::ReleaseCapability(uint64_t cid) {
auto iter = caps_.begin();
while (iter != caps_.end()) {
if (*iter && iter->id() == cid) {
auto cap = *iter;
*iter = {nullptr};
return cap;
}
++iter;
}
dbgln("Bad cap access");
dbgln("Num caps: %u", caps_.size());
return {};
}
RefPtr<Capability> Process::GetCapability(uint64_t cid) {
auto iter = caps_.begin();
while (iter != caps_.end()) {
if (iter->id() == cid) {
if (*iter && iter->id() == cid) {
return *iter;
}
++iter;
@ -75,6 +90,11 @@ RefPtr<Capability> Process::GetCapability(uint64_t cid) {
return {};
}
uint64_t Process::AddCapability(const RefPtr<Capability>& cap) {
cap->set_id(next_cap_id_++);
caps_.PushBack(cap);
return cap->id();
}
uint64_t Process::AddCapability(const RefPtr<Thread>& thread) {
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(
@ -100,6 +120,12 @@ uint64_t Process::AddCapability(const RefPtr<MemoryObject>& vmmo) {
cap_id, ZC_WRITE));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<Channel>& chan) {
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(MakeRefCounted<Capability>(chan, Capability::CHANNEL, cap_id,
ZC_WRITE | ZC_READ));
return cap_id;
}
void Process::AddCapability(uint64_t cap_id, const RefPtr<MemoryObject>& vmmo) {
caps_.PushBack(MakeRefCounted<Capability>(vmmo, Capability::MEMORY_OBJECT,

View file

@ -6,6 +6,7 @@
#include "lib/linked_list.h"
#include "lib/ref_ptr.h"
#include "object/address_space.h"
#include "object/channel.h"
// Forward decl due to cyclic dependency.
class Thread;
@ -27,11 +28,15 @@ class Process : public KernelObject {
RefPtr<Thread> CreateThread();
RefPtr<Thread> GetThread(uint64_t tid);
RefPtr<Capability> ReleaseCapability(uint64_t cid);
RefPtr<Capability> GetCapability(uint64_t cid);
// FIXME: We can't reset the cap id here.
uint64_t AddCapability(const RefPtr<Capability>& cap);
uint64_t AddCapability(const RefPtr<Thread>& t);
uint64_t AddCapability(const RefPtr<Process>& p);
uint64_t AddCapability(const RefPtr<AddressSpace>& vmas);
uint64_t AddCapability(const RefPtr<MemoryObject>& vmmo);
uint64_t AddCapability(const RefPtr<Channel>& chan);
void AddCapability(uint64_t cap_id, const RefPtr<MemoryObject>& vmmo);
// Checks the state of all child threads and transitions to