Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std/c: Restore missing Mach declarations #21218

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9670,7 +9670,12 @@ pub const CPUFAMILY = darwin.CPUFAMILY;
pub const DB_RECORDTYPE = darwin.DB_RECORDTYPE;
pub const EXC = darwin.EXC;
pub const EXCEPTION = darwin.EXCEPTION;
pub const KernE = darwin.KernE;
pub const MachMsgE = darwin.MachMsgE;
pub const MACH_MSG_OPTION = darwin.MACH_MSG_OPTION;
pub const MACH_MSG_TIMEOUT_NONE = darwin.MACH_MSG_TIMEOUT_NONE;
pub const MACH_MSG_TYPE = darwin.MACH_MSG_TYPE;
pub const MACH_PORT_NULL = darwin.MACH_PORT_NULL;
pub const MACH_PORT_RIGHT = darwin.MACH_PORT_RIGHT;
pub const MACH_TASK_BASIC_INFO = darwin.MACH_TASK_BASIC_INFO;
pub const MACH_TASK_BASIC_INFO_COUNT = darwin.MACH_TASK_BASIC_INFO_COUNT;
Expand Down Expand Up @@ -9705,13 +9710,18 @@ pub const dispatch_semaphore_signal = darwin.dispatch_semaphore_signal;
pub const dispatch_semaphore_wait = darwin.dispatch_semaphore_wait;
pub const dispatch_time = darwin.dispatch_time;
pub const fcopyfile = darwin.fcopyfile;
pub const getKernError = darwin.getKernError;
pub const getMachMsgError = darwin.getMachMsgError;
pub const ipc_space_t = darwin.ipc_space_t;
pub const kern_return_t = darwin.kern_return_t;
pub const kevent64 = darwin.kevent64;
pub const kevent64_s = darwin.kevent64_s;
pub const mach_absolute_time = darwin.mach_absolute_time;
pub const mach_continuous_time = darwin.mach_continuous_time;
pub const mach_hdr = darwin.mach_hdr;
pub const mach_host_self = darwin.mach_host_self;
pub const mach_msg = darwin.mach_msg;
pub const mach_msg_header_t = darwin.mach_msg_header_t;
pub const mach_msg_type_number_t = darwin.mach_msg_type_number_t;
pub const mach_port_allocate = darwin.mach_port_allocate;
pub const mach_port_array_t = darwin.mach_port_array_t;
Expand Down Expand Up @@ -9791,6 +9801,7 @@ pub const vm_region_recurse_info_t = darwin.vm_region_recurse_info_t;
pub const vm_region_submap_info_64 = darwin.vm_region_submap_info_64;
pub const vm_region_submap_short_info_64 = darwin.vm_region_submap_short_info_64;
pub const vm_region_top_info = darwin.vm_region_top_info;
pub const unexpectedKernError = darwin.unexpectedKernError;

pub const _ksiginfo = netbsd._ksiginfo;
pub const _lwp_self = netbsd._lwp_self;
Expand Down
245 changes: 211 additions & 34 deletions lib/std/c/darwin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -124,40 +124,42 @@ pub const THREAD_NULL: thread_t = 0;
pub const MACH_PORT_NULL: mach_port_t = 0;
pub const MACH_MSG_TIMEOUT_NONE: mach_msg_timeout_t = 0;

pub const MACH_MSG_OPTION_NONE = 0x00000000;

pub const MACH_SEND_MSG = 0x00000001;
pub const MACH_RCV_MSG = 0x00000002;

pub const MACH_RCV_LARGE = 0x00000004;
pub const MACH_RCV_LARGE_IDENTITY = 0x00000008;

pub const MACH_SEND_TIMEOUT = 0x00000010;
pub const MACH_SEND_OVERRIDE = 0x00000020;
pub const MACH_SEND_INTERRUPT = 0x00000040;
pub const MACH_SEND_NOTIFY = 0x00000080;
pub const MACH_SEND_ALWAYS = 0x00010000;
pub const MACH_SEND_FILTER_NONFATAL = 0x00010000;
pub const MACH_SEND_TRAILER = 0x00020000;
pub const MACH_SEND_NOIMPORTANCE = 0x00040000;
pub const MACH_SEND_NODENAP = MACH_SEND_NOIMPORTANCE;
pub const MACH_SEND_IMPORTANCE = 0x00080000;
pub const MACH_SEND_SYNC_OVERRIDE = 0x00100000;
pub const MACH_SEND_PROPAGATE_QOS = 0x00200000;
pub const MACH_SEND_SYNC_USE_THRPRI = MACH_SEND_PROPAGATE_QOS;
pub const MACH_SEND_KERNEL = 0x00400000;
pub const MACH_SEND_SYNC_BOOTSTRAP_CHECKIN = 0x00800000;

pub const MACH_RCV_TIMEOUT = 0x00000100;
pub const MACH_RCV_NOTIFY = 0x00000000;
pub const MACH_RCV_INTERRUPT = 0x00000400;
pub const MACH_RCV_VOUCHER = 0x00000800;
pub const MACH_RCV_OVERWRITE = 0x00000000;
pub const MACH_RCV_GUARDED_DESC = 0x00001000;
pub const MACH_RCV_SYNC_WAIT = 0x00004000;
pub const MACH_RCV_SYNC_PEEK = 0x00008000;

pub const MACH_MSG_STRICT_REPLY = 0x00000200;
pub const MACH_MSG_OPTION = struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if these definitions really all go together, could you please put them into a packed struct? the name is unfortunately not obvious based on Apple's extremely sloppy C code, so maybe the name can be determined by looking at the function(s) that these flags are passed to. Which is what? Might be nice to leave a little comment trail for the next person here.

Copy link
Author

@steeve steeve Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I didn't go for a packed struct are these two definitions, which have the same value but different semantic meanings:

#define MACH_SEND_ALWAYS        0x00010000      /* ignore qlimits - kernel only */
#define MACH_SEND_FILTER_NONFATAL        0x00010000      /* rejection by message filter should return failure - user only */

OTOH MACH_SEND_ALWAYS is "kernel only" so it might be ok to remove it.

Copy link
Author

@steeve steeve Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the function is mach_msg. Should I change the signature to accept the packed struct ? It currently accepts a mach_msg_option_t at the moment (on which the packed struct is based)

pub const NONE = 0x00000000;

pub const SEND_MSG = 0x00000001;
pub const RCV_MSG = 0x00000002;

pub const RCV_LARGE = 0x00000004;
pub const RCV_LARGE_IDENTITY = 0x00000008;

pub const SEND_TIMEOUT = 0x00000010;
pub const SEND_OVERRIDE = 0x00000020;
pub const SEND_INTERRUPT = 0x00000040;
pub const SEND_NOTIFY = 0x00000080;
pub const SEND_ALWAYS = 0x00010000;
pub const SEND_FILTER_NONFATAL = 0x00010000;
pub const SEND_TRAILER = 0x00020000;
pub const SEND_NOIMPORTANCE = 0x00040000;
pub const SEND_NODENAP = SEND_NOIMPORTANCE;
pub const SEND_IMPORTANCE = 0x00080000;
pub const SEND_SYNC_OVERRIDE = 0x00100000;
pub const SEND_PROPAGATE_QOS = 0x00200000;
pub const SEND_SYNC_USE_THRPRI = SEND_PROPAGATE_QOS;
pub const SEND_KERNEL = 0x00400000;
pub const SEND_SYNC_BOOTSTRAP_CHECKIN = 0x00800000;

pub const RCV_TIMEOUT = 0x00000100;
pub const RCV_NOTIFY = 0x00000000;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't include the legacy and deprecated values please

#define MACH_RCV_NOTIFY         0x00000000      /* legacy name (value was: 0x00000200) */
#define MACH_RCV_OVERWRITE      0x00000000      /* scatter receive (deprecated) */

pub const RCV_INTERRUPT = 0x00000400;
pub const RCV_VOUCHER = 0x00000800;
pub const RCV_OVERWRITE = 0x00000000;
pub const RCV_GUARDED_DESC = 0x00001000;
pub const RCV_SYNC_WAIT = 0x00004000;
pub const RCV_SYNC_PEEK = 0x00008000;

pub const STRICT_REPLY = 0x00000200;
};

pub const exception_type_t = c_int;

Expand Down Expand Up @@ -1513,3 +1515,178 @@ pub const DB_RECORDTYPE = enum(u32) {
pub const APP_DEFINED_START = 0x80000000;
pub const APP_DEFINED_END = 0xffffffff;
};

pub fn getKernError(err: std.c.kern_return_t) KernE {
return @as(KernE, @enumFromInt(@as(u32, @truncate(@as(usize, @intCast(err))))));
}

pub fn unexpectedKernError(err: KernE) std.posix.UnexpectedError {
if (std.posix.unexpected_error_tracing) {
std.debug.print("unexpected error: {d}\n", .{@intFromEnum(err)});
std.debug.dumpCurrentStackTrace(null);
}
return error.Unexpected;
}
Comment on lines +1519 to +1529
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These functions do not belong in the C namespace.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where would you see them? They used to live in std/c.zig so that's where code used to import them from (rather through std.posix.system).
Eg: https://github.com/mitchellh/libxev/blob/dbe22910a43e9e8ec9948d3cbd73d8488a074967/src/backend/kqueue.zig#L2460

Perhaps in KERN ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm sorry. The original contributor put these in the wrong place. I think the best place for such abstractions is in std.os.darwin. I can help get this PR landed; I realize it's a bit of a messy situation.


/// Kernel return values
pub const KernE = enum(u32) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to kern_return.h this should be

Suggested change
pub const KernE = enum(u32) {
pub const KERN = enum(u32) {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do. how do you deal with prefix collision between different types? such as MachMsgE (a bit further) for instance? https://github.com/ziglang/zig/pull/21218/files#diff-f69178bf0db31205e046265d33d0eff15e5ddfdce2a7a18dc39309db4da64a5eR9674

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MachMsgE is a made up name that doesn't seem to be based on any C bits, so that's a problem. If it's so messy that nonexhaustive enums and packed structs cannot be used, then the best move would be to give up and use a single MACH empty struct namespace for all of them. It is not obvious to me based on a quick glance how these bits relate to each other.

SUCCESS = 0,
/// Specified address is not currently valid
INVALID_ADDRESS = 1,
/// Specified memory is valid, but does not permit the
/// required forms of access.
PROTECTION_FAILURE = 2,
/// The address range specified is already in use, or
/// no address range of the size specified could be
/// found.
NO_SPACE = 3,
/// The function requested was not applicable to this
/// type of argument, or an argument is invalid
INVALID_ARGUMENT = 4,
/// The function could not be performed. A catch-all.
FAILURE = 5,
/// A system resource could not be allocated to fulfill
/// this request. This failure may not be permanent.
RESOURCE_SHORTAGE = 6,
/// The task in question does not hold receive rights
/// for the port argument.
NOT_RECEIVER = 7,
/// Bogus access restriction.
NO_ACCESS = 8,
/// During a page fault, the target address refers to a
/// memory object that has been destroyed. This
/// failure is permanent.
MEMORY_FAILURE = 9,
/// During a page fault, the memory object indicated
/// that the data could not be returned. This failure
/// may be temporary; future attempts to access this
/// same data may succeed, as defined by the memory
/// object.
MEMORY_ERROR = 10,
/// The receive right is already a member of the portset.
ALREADY_IN_SET = 11,
/// The receive right is not a member of a port set.
NOT_IN_SET = 12,
/// The name already denotes a right in the task.
NAME_EXISTS = 13,
/// The operation was aborted. Ipc code will
/// catch this and reflect it as a message error.
ABORTED = 14,
/// The name doesn't denote a right in the task.
INVALID_NAME = 15,
/// Target task isn't an active task.
INVALID_TASK = 16,
/// The name denotes a right, but not an appropriate right.
INVALID_RIGHT = 17,
/// A blatant range error.
INVALID_VALUE = 18,
/// Operation would overflow limit on user-references.
UREFS_OVERFLOW = 19,
/// The supplied (port) capability is improper.
INVALID_CAPABILITY = 20,
/// The task already has send or receive rights
/// for the port under another name.
RIGHT_EXISTS = 21,
/// Target host isn't actually a host.
INVALID_HOST = 22,
/// An attempt was made to supply "precious" data
/// for memory that is already present in a
/// memory object.
MEMORY_PRESENT = 23,
/// A page was requested of a memory manager via
/// memory_object_data_request for an object using
/// a MEMORY_OBJECT_COPY_CALL strategy, with the
/// VM_PROT_WANTS_COPY flag being used to specify
/// that the page desired is for a copy of the
/// object, and the memory manager has detected
/// the page was pushed into a copy of the object
/// while the kernel was walking the shadow chain
/// from the copy to the object. This error code
/// is delivered via memory_object_data_error
/// and is handled by the kernel (it forces the
/// kernel to restart the fault). It will not be
/// seen by users.
MEMORY_DATA_MOVED = 24,
/// A strategic copy was attempted of an object
/// upon which a quicker copy is now possible.
/// The caller should retry the copy using
/// vm_object_copy_quickly. This error code
/// is seen only by the kernel.
MEMORY_RESTART_COPY = 25,
/// An argument applied to assert processor set privilege
/// was not a processor set control port.
INVALID_PROCESSOR_SET = 26,
/// The specified scheduling attributes exceed the thread's
/// limits.
POLICY_LIMIT = 27,
/// The specified scheduling policy is not currently
/// enabled for the processor set.
INVALID_POLICY = 28,
/// The external memory manager failed to initialize the
/// memory object.
INVALID_OBJECT = 29,
/// A thread is attempting to wait for an event for which
/// there is already a waiting thread.
ALREADY_WAITING = 30,
/// An attempt was made to destroy the default processor
/// set.
DEFAULT_SET = 31,
/// An attempt was made to fetch an exception port that is
/// protected, or to abort a thread while processing a
/// protected exception.
EXCEPTION_PROTECTED = 32,
/// A ledger was required but not supplied.
INVALID_LEDGER = 33,
/// The port was not a memory cache control port.
INVALID_MEMORY_CONTROL = 34,
/// An argument supplied to assert security privilege
/// was not a host security port.
INVALID_SECURITY = 35,
/// thread_depress_abort was called on a thread which
/// was not currently depressed.
NOT_DEPRESSED = 36,
/// Object has been terminated and is no longer available
TERMINATED = 37,
/// Lock set has been destroyed and is no longer available.
LOCK_SET_DESTROYED = 38,
/// The thread holding the lock terminated before releasing
/// the lock
LOCK_UNSTABLE = 39,
/// The lock is already owned by another thread
LOCK_OWNED = 40,
/// The lock is already owned by the calling thread
LOCK_OWNED_SELF = 41,
/// Semaphore has been destroyed and is no longer available.
SEMAPHORE_DESTROYED = 42,
/// Return from RPC indicating the target server was
/// terminated before it successfully replied
RPC_SERVER_TERMINATED = 43,
/// Terminate an orphaned activation.
RPC_TERMINATE_ORPHAN = 44,
/// Allow an orphaned activation to continue executing.
RPC_CONTINUE_ORPHAN = 45,
/// Empty thread activation (No thread linked to it)
NOT_SUPPORTED = 46,
/// Remote node down or inaccessible.
NODE_DOWN = 47,
/// A signalled thread was not actually waiting.
NOT_WAITING = 48,
/// Some thread-oriented operation (semaphore_wait) timed out
OPERATION_TIMED_OUT = 49,
/// During a page fault, indicates that the page was rejected
/// as a result of a signature check.
CODESIGN_ERROR = 50,
/// The requested property cannot be changed at this time.
POLICY_STATIC = 51,
/// The provided buffer is of insufficient size for the requested data.
INSUFFICIENT_BUFFER_SIZE = 52,
/// Denied by security policy
DENIED = 53,
/// The KC on which the function is operating is missing
MISSING_KC = 54,
/// The KC on which the function is operating is invalid
INVALID_KC = 55,
/// A search or query operation did not return a result
NOT_FOUND = 56,
_,
};
Loading