blob: b04f7588f8b65135cc84139ec70cfd94c9e0dc39 [file] [log] [blame] [view]
# Driver runtime API guidelines
This page contains a set of principles and rules that Fuchsia follows when defining
C APIs in the driver runtime. Fuchsia is more opinionated for these APIs, compared to
others, because they are a significant part of the driver ABI.
## Naming
- APIs should follow the Zircon syscall naming convention of `<subject>_<verb>[_<object>]`.
- In the API example of `fdf_dispatcher_get_options`, the subject is `dispatcher`,
the verb is `get`, and the object is `options`.
- However, not all APIs have an object. In certain cases, the object may be an adverb
(for instance, `fdf_channel_wait_async`).
- Test-only and APIs for the embedding environment APIs refer to global singleton objects.
- APIs must start with the `fdf_` prefix.
- Test-only APIs must start with the `fdf_testing_` prefix.
- APIs meant for the embedding environment must start with the `fdf_env_` prefix.
- Output parameters must start with the `out_` prefix.
## Threading
- APIs should indicate whether they are blocking or not blocking in comment blocks.
- Blocking APIs must validate that they are invoked in the context of a driver runtime
dispatcher, which has the `FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS` option specified.
- However, `zx_futex_wait` and `zx_futex_requeue` are exceptions to this rule because they
cannot block on state external to the driver, which avoids risk of a deadlock outside
of the control of the driver author.
- APIs must be thread-safe.
- While they may return error when called in the incorrect dispatcher context, they should
never act in an undefined manner.
- APIs that take in a callback should provide synchronous cancellation semantics[^1]
in the context of a synchronized[^2] driver runtime dispatcher.
- Asynchronous cancellation should result in the callback being called, possibly with an error
status signaling forward progress was forced and the normal condition for triggering the
callback was not met.
- An API should never supply conditionally synchronous or asynchronous cancellation based on
anything other than the type of dispatcher that the callback was registered against.
[^1]: Synchronous cancellation semantics mean that when the cancellation function call returns, it is guaranteed that the callback will no longer be called. Either it was already called and cannot be canceled, or was canceled successfully.
[^2]: A synchronized dispatcher is constructed via `fdf_dispatcher_create` when the `FDF_DISPATCHER_OPTION_UNSYNCHRONIZED` option is not specified.
## Objects
- APIs that create objects must have a corresponding API to destroy those objects.
- APIs that return created objects should return an opaque pointer to the object and not describe
the internal structure of the object.
- APIs that create objects should take in a `uint32_t options` parameter with an extensible set
of bit flags for extensibility.
## Parameters
- APIs should take in all non-primitive parameters by pointer.
- APIs that take in a client-allocated parameter that outlives the function call itself must do
the following:
- Take full ownership of the object, and any other objects it refers to if they are not
self-referential (that is, also contained in the same allocation).
- Supply a mechanism (such as a callback parameter) to return the object to the caller.
- Provide a cancellation mechanism to proactively return the object to the caller before
it would normally be returned.
- Provide a mechanism to allow the client to use a single allocation to inline additional
client-specific context after the object.
- Strings should not be assumed to be null terminated nor have static lifetimes.
- Callback parameters should be aliased to a new type by using `typedef`.
- Callback parameters should be embedded in a `struct` to ensure they can be stored in a single
allocation.
## Miscellaneous
- APIs should have a comment block describing their purpose, parameters, outputs, and
possible errors.
- Examples are optional but recommended.
- Comment blocks must use Markdown syntax, which is conducive to generating web-based
documentation.
- APIs must be memory tight in other words, memory allocated by the runtime must be
freed by the runtime and memory allocated by the client must be freed by the client.
- An exception to this rule is allowed for arenas.
- APIs should prefer to return errors rather than assert if invoked incorrectly (for
instance, on the wrong dispatcher with invalid parameters).
- Test-only APIs must be available only in the context of tests.
- Environment-only APIs must be available only to the environment in which the driver runs,
not the driver itself.