Zircon System Interface Rubric

The Zircon system interface is expressed as the libzircon.so vDSO API surface.

Functions that are part of the interface must have names that start with zx_ and preprocessor macros must have names that start with ZX_. Types defined as part of the interface must have names that begin with zx_ and end with _t.

Every function that is part of the interface must be documented with a markdown file in /docs/zircon/syscalls/ and linked from /docs/zircon/syscalls.md .

Function Names

Functions must have names consisting entirely of lowercase letters and underscores and that conform to the following grammar:

zx_<noun>_<verb>{_<direct-object>}

For example:

zx_handle_close, zx_channel_write, zx_object_signal_peer

Typically, the noun is a kernel object type but can be other nouns, such as clock or ticks for which there is no corresponding kernel object. Other functions use more abstract nouns, such as system or status.

The nouns and verbs must not contain underscores (to avoid confusing the grammar). The noun and verb should each be single English words but acronyms (or abbreviations) may be used if there is no suitable word or the word is too long.

The direct object may contain underscores.

Some functions perform composite operations. In such cases, the function may be named by concatenating the names of the component operations.

Some functions operate on several types of kernel object, in which case the noun is a more abstract object type. For example, functions with the noun object operate on most kernel objects and functions with the noun task operate on jobs, processes, and threads.

Types

Use zx_status_t to represent success and failure.

Use fixed-size integer types. Functions must not use short, int, or unsigned long (or similar types). Instead, use types such as int16_t, int32_t, and uint64_t.

Use size_t for buffer lengths, element sizes, and element counts.

Use void* for pointers to arbitrary types in the caller's address space. Use zx_vaddr_t / zx_paddr_t for addresses that might be in other address spaces.

Use zx_time_t for timeouts, which must be expressed as absolute deadlines in nanoseconds in the system's monotonic clock timebase. In scenarios where absolute deadlines do not make sense (for example, timer slack), use zx_duration_t to represent an amount of time in nanoseconds with no specific timebase.

Parameters

Receiver

The vast majority of functions act on a handle, which is a reference to a kernel object of a type matching the noun in the function name. This handle is the first argument to such functions and is referred to as the receiver.

Use the name handle for the receiver.

Object creation functions (eg, zx_channel_create, zx_event_create) may not take a handle argument. These functions implicitly operate on the current process.

Options Parameter

Often functions include an options parameter to allow for flags that affect the operation, and include room for further flags being added to future revisions of the API.

Use the type uint32_t and the name options for the options parameter.

When present, an options parameter must be the first argument after the receiver handle or the first argument overall if the function does not have a receiver.

An options parameter is not required for all functions.

Individual option values must be defined as preprocessor macros that cast a numeric literal to uint32_t. The options must be bit flags that can be combined using the bitwise | operator.

Handles

When a function is given a handle as a parameter, the function must either always consume the handle or never consume, with the following exceptions:

  • If the function takes an options parameter, the function may have a non-default option to avoid consuming handles in various error conditions.

  • If the function does not take an options parameter, the function may avoid consuming handles if/when it returns ZX_ERR_SHOULD_WAIT.

Buffers with Data, Count/Size, and/or Actual

Always accompany arrays or buffers with a count or size (of type size_t), including strings. If the buffer is written by the function, the function must have an out parameter that returns the count or size of the data written.

For read and write style operations, the pointer(s) to the buffer(s) are followed by the buffer count(s) or size(s), and if a short read or write is possible, an out parameter provides the actual count(s) or size(s) on success:

zx_status_t zx_socket_write(zx_handle_t handle, uint32_t options,
                            const void* buffer, size_t size, size_t* actual);

When there are multiple buffers, the buffers, lengths, and out parameters appear interleaved in a consistent order. For example, see zx_channel_read:

zx_status_t zx_channel_read(zx_handle_t handle, uint32_t options,
                            void* bytes, zx_handle_t* handles,
                            uint32_t num_bytes, uint32_t num_handles,
                            uint32_t* actual_bytes, uint32_t* actual_handles);

Outputs

An out parameter is a scalar value written by the function. For example, a function that returns the number of CPUs by writing to a uint32_t has an out parameter. If the function populates a buffer provided by the client, the buffer isn’t an out parameter.

Out parameters always come at the end of the parameter list.

An out parameter must not also be an in parameter. For example, if a function has an out parameter through which it returns the number of bytes written to a buffer, that parameter must not also be used by the function to receive the length of the buffer from the caller.

Return Type

The vast majority of functions have a return type of zx_status_t, which is ZX_OK on success and ZX_ERR_... on failure.

Do not return other values through zx_status_t, for example using the positive value range. Instead, use an out parameter.

Other return types may be used for functions that cannot fail. For example, zx_thread_exit never fails to exit the thread and has a return type of void. Similarly, zx_clock_get_monotonic cannot fail to get the current time and has a return type of zx_time_t.

Function-specific rules

zx_object_get_property versus zx_object_get_info

There are two similar mechanisms for exposing data about objects: zx_object_get_property and zx_object_get_info. Prefer exposing data through zx_object_get_property if (a) the property can be set using zx_object_set_property or (b) the property exist across multiple types of objects. In other case, consider including the data in the general zx_object_get_info topic for the type of object that has the property.