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
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 .
Functions must have names consisting entirely of lowercase letters and underscores and that conform to the following grammar:
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
ticks for which there is no corresponding kernel object. Other functions use more abstract nouns, such as
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.
zx_status_t to represent success and failure.
Use fixed-size integer types. Functions must not use
unsigned long (or similar types). Instead, use types such as
size_t for buffer lengths, element sizes, and element counts.
void* for pointers to arbitrary types in the caller's address space. Use
zx_paddr_t for addresses that might be in other address spaces.
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.
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_event_create) may not take a handle argument. These functions implicitly operate on the current process.
Often functions include an
options parameter to allow for flags which 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
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.
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
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
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_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);
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.
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
There are two similar mechanisms for exposing data about objects:
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.