Files
jsix/src/kernel/objects/endpoint.h
Justin C. Miller 1d30322820 [kernel] Pass objects not handles to syscall impls
This commit contains a couple large, interdependent changes:

- In preparation for capability checking, the _syscall_verify_*
  functions now load most handles passed in, and verify that they exist
  and are of the correct type. Lists and out-handles are not converted
  to objects.
- Also in preparation for capability checking, the internal
  representation of handles has changed. j6_handle_t is now 32 bits, and
  a new j6_cap_t (also 32 bits) is added. Handles of a process are now a
  util::map<j6_handle_t, handle> where handle is a new struct containing
  the id, capabilities, and object pointer.
- The kernel object definition DSL gained a few changes to support auto
  generating the handle -> object conversion in the _syscall_verify_*
  functions, mostly knowing the object type, and an optional "cname"
  attribute on objects where their names differ from C++ code.
  (Specifically vma/vm_area)
- Kernel object code and other code under kernel/objects is now in a new
  obj:: namespace, because fuck you <cstdlib> for putting "system" in
  the global namespace. Why even have that header then?
- Kernel object types constructed with the construct_handle helper now
  have a creation_caps static member to declare what capabilities a
  newly created object's handle should have.
2022-01-17 23:23:04 -08:00

79 lines
2.5 KiB
C++

#pragma once
/// \file endpoint.h
/// Definition of endpoint kobject types
#include <j6/signals.h>
#include <util/vector.h>
#include "objects/kobject.h"
namespace obj {
/// Endpoints are objects that enable synchronous message-passing IPC
class endpoint :
public kobject
{
public:
/// Capabilities on a newly constructed endpoint handle
constexpr static j6_cap_t creation_caps = 0;
endpoint();
virtual ~endpoint();
static constexpr kobject::type type = kobject::type::endpoint;
/// Close the endpoint, waking all waiting processes with an error
virtual void close() override;
/// Check if the endpoint has space for a message to be sent
inline bool can_send() const { return check_signal(j6_signal_endpoint_can_send); }
/// Check if the endpoint has a message wiating already
inline bool can_receive() const { return check_signal(j6_signal_endpoint_can_recv); }
/// Send a message to a thread waiting to receive on this endpoint. If no threads
/// are currently trying to receive, block the current thread.
/// \arg tag The application-specified message tag
/// \arg data The message data
/// \arg len The size in bytes of the message
/// \returns j6_status_ok on success
j6_status_t send(j6_tag_t tag, const void *data, size_t data_len);
/// Receive a message from a thread waiting to send on this endpoint. If no threads
/// are currently trying to send, block the current thread.
/// \arg tag [in] The sender-specified message tag
/// \arg len [in] The size in bytes of the buffer [out] Number of bytes in the message
/// \arg data Buffer for copying message data into
/// \arg timeout Receive timeout in nanoseconds
/// \returns j6_status_ok on success
j6_status_t receive(j6_tag_t *tag, void *data, size_t *data_len, uint64_t timeout = 0);
/// Give the listener on the endpoint a message that a bound IRQ has been signalled
/// \arg irq The IRQ that caused this signal
void signal_irq(unsigned irq);
private:
struct thread_data
{
thread *th;
union {
const void *data;
void *buffer;
};
union {
j6_tag_t *tag_p;
j6_tag_t tag;
};
union {
size_t *len_p;
size_t len;
};
};
j6_status_t do_message_copy(const thread_data &sender, thread_data &receiver);
util::vector<thread_data> m_blocked;
};
} // namespace obj