/* * Copyright (c) 2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef __MACH_RIGHT_PRIVATE_H #define __MACH_RIGHT_PRIVATE_H #include <os/base.h> #include <mach/mach.h> #include <mach/port.h> #include <mach/mach_port.h> #include <sys/cdefs.h> #include <stdbool.h> __BEGIN_DECLS; /*! * @typedef mach_right_recv_t * A type representing the receive right to a Mach port. */ typedef struct _mach_right_recv { mach_port_t mrr_name; } mach_right_recv_t; /*! * @const MACH_RIGHT_RECV_NULL * A convenience initializer for a receive right object. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define MACH_RIGHT_RECV_NULL ((mach_right_recv_t){MACH_PORT_NULL}) #elif defined(__cplusplus) && __cplusplus >= 201103L #define MACH_RIGHT_RECV_NULL (mach_right_recv_t{MACH_PORT_NULL}) #elif defined(__cplusplus) #define MACH_RIGHT_RECV_NULL \ (mach_right_recv_t((mach_right_recv_t){MACH_PORT_NULL})) #else #define MACH_RIGHT_RECV_NULL {MACH_PORT_NULL} #endif /*! * @typedef mach_right_send_t * A type representing a send right to a Mach port. */ typedef struct _mach_right_send { mach_port_t mrs_name; } mach_right_send_t; /*! * @const MACH_RIGHT_SEND_NULL * A convenience initializer for a send right object. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define MACH_RIGHT_SEND_NULL ((mach_right_send_t){MACH_PORT_NULL}) #elif defined(__cplusplus) && __cplusplus >= 201103L #define MACH_RIGHT_SEND_NULL (mach_right_send_t{MACH_PORT_NULL}) #elif defined(__cplusplus) #define MACH_RIGHT_SEND_NULL \ (mach_right_send_t((mach_right_send_t){MACH_PORT_NULL})) #else #define MACH_RIGHT_SEND_NULL {MACH_PORT_NULL} #endif /*! * @typedef mach_right_send_once_t * A type representing a send-once right to a Mach port. */ typedef struct _mach_right_send_once { mach_port_t mrso_name; } mach_right_send_once_t; /*! * @const MACH_RIGHT_SEND_ONCE_NULL * A convenience initializer for a send-once right object. */ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define MACH_RIGHT_SEND_ONCE_NULL ((mach_right_send_once_t){MACH_PORT_NULL}) #elif defined(__cplusplus) && __cplusplus >= 201103L #define MACH_RIGHT_SEND_ONCE_NULL (mach_right_send_once_t{MACH_PORT_NULL}) #elif defined(__cplusplus) #define MACH_RIGHT_SEND_ONCE_NULL \ (mach_right_send_once_t((mach_right_send_once_t){MACH_PORT_NULL})) #else #define MACH_RIGHT_SEND_ONCE_NULL {MACH_PORT_NULL} #endif /*! * @function mach_right_recv * Wraps a port name as a receive right object. * * @param pn * The port name. If this name is valid but does not represent a receive right, * the behavior of mach_right_recv_* implementations is undefined. * * @result * A new receive right object. */ OS_ALWAYS_INLINE OS_WARN_RESULT static inline mach_right_recv_t mach_right_recv(mach_port_name_t pn) { mach_right_recv_t mrr = {pn}; return mrr; } /*! * @function mach_right_send * Wraps a port name as a send right object. * * @param pn * The port name. If this name is valid but does not represent a send right, the * behavior of mach_right_send_* implementations is undefined. * * @result * A new send right object. */ OS_ALWAYS_INLINE OS_WARN_RESULT static inline mach_right_send_t mach_right_send(mach_port_name_t pn) { mach_right_send_t mrs = {pn}; return mrs; } /*! * @function mach_right_send_valid * Checks if the given send right object is valid. * * @param mrs * The send right object to check. * * @result * A Boolean indicating whether the right is valid. */ OS_ALWAYS_INLINE OS_WARN_RESULT static inline bool mach_right_send_valid(mach_right_send_t mrs) { return MACH_PORT_VALID(mrs.mrs_name); } /*! * @function mach_right_send_once * Wraps a port name as a send-once right object. * * @param pn * The port name. If this name is valid but does not represent a send-once * right, the behavior of mach_right_send_once_* implementations is undefined. * * @result * A new send-once right object. */ OS_ALWAYS_INLINE OS_WARN_RESULT static inline mach_right_send_once_t mach_right_send_once(mach_port_name_t pn) { mach_right_send_once_t mrso = {pn}; return mrso; } /*! * @function mach_right_send_once_valid * Checks if the given send-once right object is valid. * * @param mrso * The send-once right object to check. * * @result * A Boolean indicating whether the right is valid. */ OS_ALWAYS_INLINE OS_WARN_RESULT static inline bool mach_right_send_once_valid(mach_right_send_once_t mrso) { return MACH_PORT_VALID(mrso.mrso_name); } /*! * @typedef mach_right_flags_t * Flags influencing the behavior of a constructed Mach port. * * @const MACH_RIGHT_RECV_INIT * No flags set. This value is suitable for initialization purposes. * * @const MACH_RIGHT_RECV_UNGUARDED * The given context should not serve as a guard for the underlying port's * destruction. */ OS_ENUM(mach_right_flags, uint64_t, MACH_RIGHT_RECV_FLAG_INIT = 0, MACH_RIGHT_RECV_FLAG_UNGUARDED = (1 << 0), ); /*! * @function mach_right_recv_construct * Allocates a new Mach port and returns the receive right to the caller. * * @param flags * Flags to influence the behavior of the new port. * * @param sr * If non-NULL, will be filled in with the name of a send right which * corresponds to the new port. The caller is responsible for disposing of this * send right with {@link mach_right_send_release}. * * @param ctx * Context to be associated with the new port. By default, this context must be * passed to {@link mach_right_recv_destruct} in order to destroy the underlying * port. This requirement may be elided with the * {@link MACH_RIGHT_RECV_UNGUARDED} flag. * * @result * A new port handle which refers to the receive right for the newly-created * port. The caller is responsible for disposing of this handle with * {@link mach_right_recv_destruct}. * * @discussion * The implementation will abort on any failure to allocate a new port object in * the kernel. Thus the caller may assert that a new, valid receive right is * always returned. */ OS_EXPORT OS_WARN_RESULT mach_right_recv_t mach_right_recv_construct(mach_right_flags_t flags, mach_right_send_t *_Nullable sr, uintptr_t ctx); /*! * @function mach_right_recv_destruct * Closes the port referred to by the given receive right. * * @param r * The receive right for the port to manipulate. * * @param s * A pointer to the send right to dispose of. If NULL is given, no attempt will * be made to clean up any send right associated with the port. If the name of * the given send right does not match the name of the given receive right, the * implementation's behavior is undefined. * * @param ctx * The context which guards the underlying port destruction. If the receive * right was created with {@link MACH_RIGHT_RECV_UNGUARDED}, this parameter is * ignored. * * @discussion * If a send right is passed, the implementation performs the moral equivalent * of * * mach_right_recv_destruct(r, MACH_PORT_NULL, ctx); * mach_right_send_release(s); * * except in a more efficient manner, requiring only one system call. * * The implementation will abort on any failure to dispose of the port. As such, * this routine should only be used on ports that are known to be under the * caller's complete control. */ OS_EXPORT void mach_right_recv_destruct(mach_right_recv_t r, mach_right_send_t *_Nullable s, uintptr_t ctx); /*! * @function mach_right_send_create * Creates a send right to the port referenced by the given receive right. * * @param r * The receive right for the port for which to create the send right. * * @result * The name of the new send right. The caller is responsible for disposing of * this send right with {@link mach_right_send_release}. * * This operation will increment the make-send count of the port referenced by * the given receive right. * * @discussion * The implementation will abort on any failure to create the send right. As * such, this routine should only be used on ports that are known to be under * the caller's complete control. */ OS_EXPORT OS_WARN_RESULT mach_right_send_t mach_right_send_create(mach_right_recv_t r); /*! * @function mach_right_send_retain * Increments the user reference count for the given send right. * * @param s * The send right to manipulate. * * @result * If the reference count was successfully incremented, the given port name is * returned. If either MACH_PORT_NULL or MACH_PORT_DEAD are given, the given * value is returned. If the given send right became a dead name before or * during the attempt to retain the send right, MACH_PORT_DEAD is returned. * * If the implementation encounters any other failure condition, it will abort. */ OS_EXPORT OS_WARN_RESULT mach_right_send_t mach_right_send_retain(mach_right_send_t s); /*! * @function mach_right_send_release * Decrements the user reference count for the given send right. * * @param s * The send right to manipulate. * * @discussion * If the given send right became a dead name before or during the attempt to * release it, the implementation will dispose of that dead name. * * If the implementation encounters any other failure condition, it will abort. */ OS_EXPORT void mach_right_send_release(mach_right_send_t s); /*! * @function mach_right_send_once_create * Creates a send-once right from the given receive right. * * @param r * The receive right for the port for which to create the send-once right. * * @result * The newly-created send-once right. * * @discussion * The implementation will abort on any failure to allocate a new send-once * right, and therefore the caller should only provide a receive right which is * under its complete control. The caller may assert that a new, valid send-once * right is always returned. * * The returned send-once right will never share a name with the given receive * right. A send-once right must be consumed either by using it to send a * message or by consuming it with {@link mach_right_send_once_consume}. * * The returned right does not support retain/release semantics despite the * presence of "create" in the name. */ OS_EXPORT OS_WARN_RESULT mach_right_send_once_t mach_right_send_once_create(mach_right_recv_t r); /*! * @function mach_right_send_once_consume * Consumes the given send-once right. * * @param so * The send-once right to manipulate. * * @discussion * If the given send-once right became a dead name before or during the attempt * to release it, the implementation will dispose of that dead name. * * If the implementation encounters any other failure condition, it will abort. * * This operation will cause a send-once notification to be delivered to the * port to which the send-once right refers unless the right is a dead name, in * which case there are no side effects. */ OS_EXPORT void mach_right_send_once_consume(mach_right_send_once_t so); __END_DECLS; #endif // __MACH_RIGHT_PRIVATE_H