aboutsummaryrefslogtreecommitdiff
path: root/ipc/ipc_port.h
diff options
context:
space:
mode:
authorPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
committerPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
commit5e0b8d508ed51004bd836384293be00950ee62c9 (patch)
treee3f16b1aa8b7177032ce3ec429fbad2b1d92a876 /ipc/ipc_port.h
downloadgnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.gz
gnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.bz2
init gnumach copy
Diffstat (limited to 'ipc/ipc_port.h')
-rw-r--r--ipc/ipc_port.h354
1 files changed, 354 insertions, 0 deletions
diff --git a/ipc/ipc_port.h b/ipc/ipc_port.h
new file mode 100644
index 0000000..192d880
--- /dev/null
+++ b/ipc/ipc_port.h
@@ -0,0 +1,354 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University.
+ * Copyright (c) 1993,1994 The University of Utah and
+ * the Computer Systems Laboratory (CSL).
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON, THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF
+ * THIS SOFTWARE IN ITS "AS IS" CONDITION, AND DISCLAIM ANY LIABILITY
+ * OF ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
+ * THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ */
+/*
+ * File: ipc/ipc_port.h
+ * Author: Rich Draves
+ * Date: 1989
+ *
+ * Definitions for ports.
+ */
+
+#ifndef _IPC_IPC_PORT_H_
+#define _IPC_IPC_PORT_H_
+
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/port.h>
+#include <kern/lock.h>
+#include <kern/macros.h>
+#include <kern/ipc_kobject.h>
+#include <ipc/ipc_mqueue.h>
+#include <ipc/ipc_table.h>
+#include <ipc/ipc_thread.h>
+#include <ipc/ipc_object.h>
+#include "ipc_target.h"
+
+/*
+ * A receive right (port) can be in four states:
+ * 1) dead (not active, ip_timestamp has death time)
+ * 2) in a space (ip_receiver_name != 0, ip_receiver points
+ * to the space but doesn't hold a ref for it)
+ * 3) in transit (ip_receiver_name == 0, ip_destination points
+ * to the destination port and holds a ref for it)
+ * 4) in limbo (ip_receiver_name == 0, ip_destination == IP_NULL)
+ *
+ * If the port is active, and ip_receiver points to some space,
+ * then ip_receiver_name != 0, and that space holds receive rights.
+ * If the port is not active, then ip_timestamp contains a timestamp
+ * taken when the port was destroyed.
+ */
+
+typedef unsigned int ipc_port_timestamp_t;
+
+struct ipc_port {
+ struct ipc_target ip_target;
+
+ /* This points to the ip_target above if this port isn't on a port set;
+ otherwise it points to the port set's ips_target. */
+ struct ipc_target *ip_cur_target;
+
+ union {
+ struct ipc_space *receiver;
+ struct ipc_port *destination;
+ ipc_port_timestamp_t timestamp;
+ } data;
+
+ ipc_kobject_t ip_kobject;
+
+ mach_port_mscount_t ip_mscount;
+ mach_port_rights_t ip_srights;
+ mach_port_rights_t ip_sorights;
+
+ struct ipc_port *ip_nsrequest;
+ struct ipc_port *ip_pdrequest;
+ struct ipc_port_request *ip_dnrequests;
+
+ struct ipc_pset *ip_pset;
+ mach_port_seqno_t ip_seqno; /* locked by message queue */
+ mach_port_msgcount_t ip_msgcount;
+ mach_port_msgcount_t ip_qlimit;
+ struct ipc_thread_queue ip_blocked;
+ rpc_uintptr_t ip_protected_payload;
+};
+
+#define ip_object ip_target.ipt_object
+#define ip_receiver_name ip_target.ipt_name
+#define ip_messages ip_target.ipt_messages
+#define ip_references ip_object.io_references
+#define ip_bits ip_object.io_bits
+#define ip_receiver data.receiver
+#define ip_destination data.destination
+#define ip_timestamp data.timestamp
+
+#define IP_NULL ((ipc_port_t) IO_NULL)
+#define IP_DEAD ((ipc_port_t) IO_DEAD)
+
+#define IP_VALID(port) IO_VALID(&(port)->ip_object)
+
+#define ip_active(port) io_active(&(port)->ip_object)
+#define ip_lock_init(port) io_lock_init(&(port)->ip_object)
+#define ip_lock(port) io_lock(&(port)->ip_object)
+#define ip_lock_try(port) io_lock_try(&(port)->ip_object)
+#define ip_unlock(port) io_unlock(&(port)->ip_object)
+#define ip_check_unlock(port) io_check_unlock(&(port)->ip_object)
+#define ip_reference(port) io_reference(&(port)->ip_object)
+#define ip_release(port) io_release(&(port)->ip_object)
+
+#define ip_alloc() ((ipc_port_t) io_alloc(IOT_PORT))
+#define ip_free(port) io_free(IOT_PORT, &(port)->ip_object)
+
+#define ip_kotype(port) io_kotype(&(port)->ip_object)
+
+typedef ipc_table_index_t ipc_port_request_index_t;
+
+typedef struct ipc_port_request {
+ union {
+ struct ipc_port *port;
+ ipc_port_request_index_t index;
+ } notify;
+
+ union {
+ mach_port_name_t name;
+ struct ipc_table_size *size;
+ } name;
+} *ipc_port_request_t;
+
+#define ipr_next notify.index
+#define ipr_size name.size
+
+#define ipr_soright notify.port
+#define ipr_name name.name
+
+#define IPR_NULL ((ipc_port_request_t) 0)
+
+/*
+ * Taking the ipc_port_multiple lock grants the privilege
+ * to lock multiple ports at once. No ports must locked
+ * when it is taken.
+ */
+
+decl_simple_lock_data(extern, ipc_port_multiple_lock_data)
+
+#define ipc_port_multiple_lock_init() \
+ simple_lock_init(&ipc_port_multiple_lock_data)
+
+#define ipc_port_multiple_lock() \
+ simple_lock(&ipc_port_multiple_lock_data)
+
+#define ipc_port_multiple_unlock() \
+ simple_unlock(&ipc_port_multiple_lock_data)
+
+/*
+ * The port timestamp facility provides timestamps
+ * for port destruction. It is used to serialize
+ * mach_port_names with port death.
+ */
+
+decl_simple_lock_data(extern, ipc_port_timestamp_lock_data)
+extern ipc_port_timestamp_t ipc_port_timestamp_data;
+
+#define ipc_port_timestamp_lock_init() \
+ simple_lock_init(&ipc_port_timestamp_lock_data)
+
+#define ipc_port_timestamp_lock() \
+ simple_lock(&ipc_port_timestamp_lock_data)
+
+#define ipc_port_timestamp_unlock() \
+ simple_unlock(&ipc_port_timestamp_lock_data)
+
+extern ipc_port_timestamp_t
+ipc_port_timestamp(void);
+
+/*
+ * Compares two timestamps, and returns TRUE if one
+ * happened before two. Note that this formulation
+ * works when the timestamp wraps around at 2^32,
+ * as long as one and two aren't too far apart.
+ */
+
+#define IP_TIMESTAMP_ORDER(one, two) ((int) ((one) - (two)) < 0)
+
+#define ipc_port_translate_receive(space, name, portp) \
+ ipc_object_translate((space), (name), \
+ MACH_PORT_RIGHT_RECEIVE, \
+ (ipc_object_t *) (portp))
+
+#define ipc_port_translate_send(space, name, portp) \
+ ipc_object_translate((space), (name), \
+ MACH_PORT_RIGHT_SEND, \
+ (ipc_object_t *) (portp))
+
+extern kern_return_t
+ipc_port_dnrequest(ipc_port_t, mach_port_name_t, ipc_port_t,
+ ipc_port_request_index_t *);
+
+extern kern_return_t
+ipc_port_dngrow(ipc_port_t);
+
+extern ipc_port_t
+ipc_port_dncancel(ipc_port_t, mach_port_name_t, ipc_port_request_index_t);
+
+#define ipc_port_dnrename(port, index, oname, nname) \
+MACRO_BEGIN \
+ ipc_port_request_t ipr, table; \
+ \
+ assert(ip_active(port)); \
+ \
+ table = port->ip_dnrequests; \
+ assert(table != IPR_NULL); \
+ \
+ ipr = &table[index]; \
+ assert(ipr->ipr_name == oname); \
+ \
+ ipr->ipr_name = nname; \
+MACRO_END
+
+/* Make a port-deleted request */
+extern void ipc_port_pdrequest(
+ ipc_port_t port,
+ ipc_port_t notify,
+ ipc_port_t *previousp);
+
+/* Make a no-senders request */
+extern void ipc_port_nsrequest(
+ ipc_port_t port,
+ mach_port_mscount_t sync,
+ ipc_port_t notify,
+ ipc_port_t *previousp);
+
+/* Change a port's queue limit */
+extern void ipc_port_set_qlimit(
+ ipc_port_t port,
+ mach_port_msgcount_t qlimit);
+
+#define ipc_port_set_mscount(port, mscount) \
+MACRO_BEGIN \
+ assert(ip_active(port)); \
+ \
+ (port)->ip_mscount = (mscount); \
+MACRO_END
+
+extern struct ipc_mqueue *
+ipc_port_lock_mqueue(ipc_port_t);
+
+extern void
+ipc_port_set_seqno(ipc_port_t, mach_port_seqno_t);
+
+extern void
+ipc_port_set_protected_payload(ipc_port_t, rpc_uintptr_t);
+
+extern void
+ipc_port_clear_protected_payload(ipc_port_t);
+
+extern void
+ipc_port_clear_receiver(ipc_port_t);
+
+extern void
+ipc_port_init(ipc_port_t, ipc_space_t, mach_port_name_t);
+
+extern kern_return_t
+ipc_port_alloc(ipc_space_t, mach_port_name_t *, ipc_port_t *);
+
+extern kern_return_t
+ipc_port_alloc_name(ipc_space_t, mach_port_name_t, ipc_port_t *);
+
+extern void
+ipc_port_destroy(ipc_port_t);
+
+extern boolean_t
+ipc_port_check_circularity(ipc_port_t, ipc_port_t);
+
+extern ipc_port_t
+ipc_port_lookup_notify(ipc_space_t, mach_port_name_t);
+
+extern ipc_port_t
+ipc_port_make_send(ipc_port_t);
+
+extern ipc_port_t
+ipc_port_copy_send(ipc_port_t);
+
+extern mach_port_name_t
+ipc_port_copyout_send(ipc_port_t, ipc_space_t);
+
+extern void
+ipc_port_release_send(ipc_port_t);
+
+extern ipc_port_t
+ipc_port_make_sonce(ipc_port_t);
+
+extern void
+ipc_port_release_sonce(ipc_port_t);
+
+extern void
+ipc_port_release_receive(ipc_port_t);
+
+extern ipc_port_t
+ipc_port_alloc_special(ipc_space_t);
+
+extern void
+ipc_port_dealloc_special(ipc_port_t, ipc_space_t);
+
+#define ipc_port_alloc_kernel() \
+ ipc_port_alloc_special(ipc_space_kernel)
+#define ipc_port_dealloc_kernel(port) \
+ ipc_port_dealloc_special((port), ipc_space_kernel)
+
+#define ipc_port_alloc_reply() \
+ ipc_port_alloc_special(ipc_space_reply)
+#define ipc_port_dealloc_reply(port) \
+ ipc_port_dealloc_special((port), ipc_space_reply)
+
+#define ipc_port_reference(port) \
+ ipc_object_reference(&(port)->ip_object)
+
+#define ipc_port_release(port) \
+ ipc_object_release(&(port)->ip_object)
+
+static inline boolean_t
+ipc_port_flag_protected_payload(const struct ipc_port *port)
+{
+ return !! (port->ip_target.ipt_object.io_bits
+ & IO_BITS_PROTECTED_PAYLOAD);
+}
+
+static inline void
+ipc_port_flag_protected_payload_set(struct ipc_port *port)
+{
+ port->ip_target.ipt_object.io_bits |= IO_BITS_PROTECTED_PAYLOAD;
+}
+
+static inline void
+ipc_port_flag_protected_payload_clear(struct ipc_port *port)
+{
+ port->ip_target.ipt_object.io_bits &= ~IO_BITS_PROTECTED_PAYLOAD;
+}
+
+#endif /* _IPC_IPC_PORT_H_ */