Documentation
¶
Overview ¶
Package mach provides a small, hand-written discipline layer over the raw Mach bindings in the kernel package: thread ports and real-time thread promotion.
The raw calls (thread_policy_set, mach_port_deallocate, ...) are generated into the kernel package from Apple's Kernel framework documentation. What generation cannot supply lives here: acquiring the right thread port without leaking a port right, converting durations to Mach absolute time units, and the pin-then-promote calling discipline.
Promotion applies to an OS thread, not a goroutine. Callers must hold the thread with runtime.LockOSThread before promoting, and the promotion lasts until the thread is demoted or exits:
runtime.LockOSThread()
defer runtime.UnlockOSThread()
t := mach.ThreadSelf()
err := t.SetTimeConstraint(mach.TimeConstraint{
Period: time.Millisecond * 10,
Computation: time.Millisecond * 2,
Constraint: time.Millisecond * 4,
Preemptible: true,
})
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BootstrapRegister ¶
BootstrapRegister registers a send right for p under name in this session's bootstrap namespace, making it visible to BootstrapLookUp in other processes. p must carry a send right (see MakeSendRight).
bootstrap_register is deprecated in favor of launchd job submission, but remains the only route for an unprivileged process to publish a port at runtime, which is exactly the rendezvous case this package serves.
func Send ¶
func Send(dest Port, destDisp Disposition, id int32, rights []PortRight, body []byte, timeout time.Duration) error
Send sends a message to dest. destDisp says what right the send consumes to address dest (CopySend keeps the caller's send right, MoveSend consumes it, MakeSend requires dest be a receive right). Attached port rights cross by their own dispositions. timeout zero blocks.
The kernel both reads the buffer and requires it not move; the buffer is built pointer-free and pinned for the call.
Types ¶
type Disposition ¶
type Disposition uint32
Disposition says how a port right crosses in a message (mach_msg_type_name_t). MoveSend consumes the sender's right; CopySend does not. Getting this backwards leaks a right or produces a dead name — see the leak tests.
const ( MoveReceive Disposition = 16 MoveSend Disposition = 17 MoveSendOnce Disposition = 18 CopySend Disposition = 19 MakeSend Disposition = 20 MakeSendOnce Disposition = 21 )
type Header ¶
type Header struct {
Bits uint32
Size uint32
RemotePort Port
LocalPort Port
VoucherPort Port
ID int32
}
Header is mach_msg_header_t with its field names restored.
The generated kernel.Mach_msg_header_t is an opaque [6]uint32: Apple's documentation describes the typedef and the field names live on the anonymous struct, so the generator cannot recover them. The layout is ABI pinned to xnu, not to the SDK documentation, so owning it here as a hand-written struct is correct, with the size assertions below tying it to the generated type so a change on either side breaks the build.
type Message ¶
Message is a received Mach message: the header, any port rights carried in descriptors, and the inline body bytes.
Received rights are owned by the caller and must be balanced (Deallocate for send rights) like any other acquired right.
Mach message sizes are word-aligned, so Body carries up to three bytes of zero padding beyond what was sent; protocols that need exact lengths carry them in the body or the ID.
type Port ¶
type Port uint32
Port is a Mach port name in this task's port namespace.
Port rights are reference-counted in the kernel and leak silently: a leaked receive right keeps its object alive forever, and a dropped send right becomes a dead name whose next use fails far from the bug. A Port is a name, not an object — Go's GC cannot manage right lifetime, so every acquired right is balanced explicitly with Deallocate or DestroyReceive, typically via defer.
const PortNull Port = 0
PortNull is the null port name.
func BootstrapLookUp ¶
BootstrapLookUp returns a send right to the port registered under name. The caller owns the returned right and balances it with Deallocate.
func (Port) Deallocate ¶
Deallocate releases one send, send-once, or dead-name reference.
func (Port) DestroyReceive ¶
DestroyReceive releases p's receive right.
func (Port) MakeSendRight ¶
MakeSendRight adds a send right for p's receive right under the same name. Balance with Deallocate.
type PortRight ¶
type PortRight struct {
Port Port
Disposition Disposition
}
PortRight names a port right to carry in a message.
type Thread ¶
type Thread uint32
Thread is a Mach thread port name.
func ThreadSelf ¶
ThreadSelf returns the Mach thread port of the calling OS thread.
It resolves the port via pthread_mach_thread_np(pthread_self()) rather than mach_thread_self: the pthread route borrows the port cached in the pthread structure, so no port right is allocated and nothing needs to be deallocated. The result is only meaningful for the current OS thread; pin it with runtime.LockOSThread before using the port.
func (Thread) SetStandard ¶
SetStandard demotes the thread back to the standard scheduling class.
func (Thread) SetTimeConstraint ¶
func (t Thread) SetTimeConstraint(tc TimeConstraint) error
SetTimeConstraint promotes the thread to the real-time scheduling class. The calling goroutine must be locked to the thread t was obtained from.
type TimeConstraint ¶
type TimeConstraint struct {
Period time.Duration
Computation time.Duration
Constraint time.Duration
Preemptible bool
}
TimeConstraint describes a real-time scheduling contract, as passed to THREAD_TIME_CONSTRAINT_POLICY. Period is the interval between deadlines (for audio, the buffer duration), Computation the CPU time needed per period, and Constraint the window within which that computation must complete (Computation <= Constraint <= Period).