blob: 7b57c24cdb709b969516cd53d93828c1520a17d6 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library zx;
@transport("Syscall")
// TODO(https://fxbug.dev/339884866): Our versioning tooling does not yet
// support availability annotations for vDSO entry points. Enable this
// annotation once it's supported.
// @available(added=HEAD)
closed protocol Counter {
/// ## Summary
///
/// Create a counter.
///
/// ## Declaration
///
/// ```c
/// #include <zircon/syscalls.h>
///
/// zx_status_t zx_counter_create(uint32_t options, zx_handle_t* out);
/// ```
///
/// ## Description
///
/// `zx_counter_create()` creates a counter, which is an object that encapsulates
/// a signed 64-bit integer value that can be incremented, decremented, read, or
/// written.
///
/// When the value is greater than zero, the signal `ZX_COUNTER_POSITIVE` is
/// asserted. Otherwise `ZX_COUNTER_NON_POSITIVE` is asserted. Exactly one of
/// these two signals is always asserted, and never both at once.
///
/// Additionally, the signal `ZX_COUNTER_SIGNALED` may be set or cleared on the
/// counter using [`zx_object_signal()`]. This is independent of the value of the
/// counter or the state of the other signals.
///
/// The newly-created handle will have rights `ZX_RIGHTS_BASIC`, `ZX_RIGHTS_IO`, and
/// `ZX_RIGHT_SIGNAL`. The value will be zero and the signal
/// `ZX_COUNTER_NON_POSITIVE` will be asserted on the newly-created object.
///
/// ## Rights
///
/// TODO(https://fxbug.dev/387324141): Add/enforce ZX_POL_NEW_COUNTER policy.
///
/// Caller job policy must allow `ZX_POL_NEW_COUNTER`.
///
/// ## Return value
///
/// `zx_counter_create()` returns `ZX_OK` and a valid counter handle (via *out*) on
/// success.
///
/// On failure, an error value is returned.
///
/// ## Errors
///
/// `ZX_ERR_INVALID_ARGS` *out* is an invalid pointer, or *options* is non-zero.
///
/// `ZX_ERR_NO_MEMORY` Failure due to lack of memory. There is no good way for
/// userspace to handle this (unlikely) error. In a future build this error will no
/// longer occur.
///
/// ## See also
///
/// - [`zx_handle_close()`]
/// - [`zx_handle_duplicate()`]
/// - [`zx_handle_replace()`]
/// - [`zx_object_wait_async()`]
/// - [`zx_object_wait_many()`]
/// - [`zx_object_wait_one()`]
/// - [`zx_counter_add()`]
/// - [`zx_counter_read()`]
/// - [`zx_counter_write()`]
///
/// [`zx_handle_close()`]: handle_close.md
/// [`zx_handle_duplicate()`]: handle_duplicate.md
/// [`zx_handle_replace()`]: handle_replace.md
/// [`zx_object_signal()`]: object_signal.md
/// [`zx_object_wait_async()`]: object_wait_async.md
/// [`zx_object_wait_many()`]: object_wait_many.md
/// [`zx_object_wait_one()`]: object_wait_one.md
/// [`zx_counter_add()`]: counter_add.md
/// [`zx_counter_read()`]: counter_read.md
/// [`zx_counter_write()`]: counter_write.md
strict Create(struct {
options uint32;
}) -> (resource struct {
out Handle:COUNTER;
}) error Status;
/// ## Summary
///
/// Add a value to a counter.
///
/// ## Declaration
///
/// ```c
/// #include <zircon/syscalls.h>
///
/// zx_status_t zx_counter_add(zx_handle_t handle, int64_t value);
/// ```
///
/// ## Description
///
/// `zx_counter_add()` adds *value* to the counter referenced by *handle*.
///
/// After the result of the addition, if the counter's value is:
///
/// * less than or equal to zero - `ZX_COUNTER_NON_POSITIVE` will be asserted and
/// `ZX_COUNTER_POSITIVE` will be deasserted.
///
/// * greater than zero - `ZX_COUNTER_POSITIVE` will be asserted and
/// `ZX_COUNTER_NON_POSITIVE` will be deasserted.
///
/// ## Rights
///
/// *handle* must have both `ZX_RIGHT_READ` and `ZX_RIGHT_WRITE`. Because a
/// counter's value could be determined by checking for `ZX_ERR_OUT_OF_RANGE` on a
/// series of carefully crafted `zx_counter_add()` calls, there is no way to create
/// a counter that cannot be read, but which can be added.
///
/// ## Return value
///
/// `zx_counter_add()` returns `ZX_OK` on success.
///
/// On failure, an error value is returned.
///
/// ## Errors
///
/// `ZX_ERR_WRONG_TYPE` if *handle* is not a counter handle.
///
/// `ZX_ERR_ACCESS_DENIED` if *handle* does not have `ZX_RIGHT_WRITE`.
///
/// `ZX_ERR_OUT_OF_RANGE` if the result of the addition would overflow or underflow.
///
/// ## See also
///
/// - [`zx_object_wait_async()`]
/// - [`zx_object_wait_many()`]
/// - [`zx_object_wait_one()`]
/// - [`zx_counter_create()`]
/// - [`zx_counter_read()`]
/// - [`zx_counter_write()`]
///
/// [`zx_object_wait_async()`]: object_wait_async.md
/// [`zx_object_wait_many()`]: object_wait_many.md
/// [`zx_object_wait_one()`]: object_wait_one.md
/// [`zx_counter_create()`]: counter_create.md
/// [`zx_counter_read()`]: counter_read.md
/// [`zx_counter_write()`]: counter_write.md
strict Add(resource struct {
handle Handle;
value int64;
}) -> () error Status;
/// ## Summary
///
/// Read the value of a counter.
///
/// ## Declaration
///
/// ```c
/// #include <zircon/syscalls.h>
///
/// zx_status_t zx_counter_read(zx_handle_t handle, int64_t* value);
/// ```
///
/// ## Description
///
/// `zx_counter_read()` reads the value of the counter referenced by *handle* into
/// the integer *value* points at.
///
/// ## Rights
///
/// *handle* must have `ZX_RIGHT_READ`.
///
/// ## Return value
///
/// `zx_counter_read()` returns `ZX_OK` on success.
///
/// On failure, an error value is returned.
///
/// ## Errors
///
/// `ZX_ERR_WRONG_TYPE` if *handle* is not a counter handle.
///
/// `ZX_ERR_ACCESS_DENIED` if *handle* does not have `ZX_RIGHT_READ`.
///
/// `ZX_ERR_INVALID_ARGS` if *value* is an invalid pointer.
///
/// ## See also
///
/// - [`zx_counter_create()`]
/// - [`zx_counter_add()`]
/// - [`zx_counter_write()`]
///
/// [`zx_counter_create()`]: counter_create.md
/// [`zx_counter_add()`]: counter_add.md
/// [`zx_counter_write()`]: counter_write.md
strict Read(resource struct {
handle Handle;
}) -> (struct {
value int64;
}) error Status;
/// ## Summary
///
/// Write a value to a counter.
///
/// ## Declaration
///
/// ```c
/// #include <zircon/syscalls.h>
///
/// zx_status_t zx_counter_write(zx_handle_t handle, int64_t value);
/// ```
///
/// ## Description
///
/// `zx_counter_write()` writes *value* to the counter referenced by *handle*,
/// asserting/deasserting signals as necessary. See [`zx_counter_add()`] for
/// the conditions on which signals are asserted/deasserted.
///
/// Because concurrent operations on a counter may be interleaved with one another,
/// an implementation of a "counting semaphore" synchronization protocol should use
/// `zx_counter_add()` instead of a sequence of `zx_counter_read()`, modify,
/// `zx_counter_write()`.
///
/// ## Rights
///
/// *handle* must have `ZX_RIGHT_WRITE`.
///
/// ## Return value
///
/// `zx_counter_write()` returns `ZX_OK` on success.
///
/// On failure, an error value is returned.
///
/// ## Errors
///
/// `ZX_ERR_WRONG_TYPE` if *handle* is not a counter handle.
///
/// `ZX_ERR_ACCESS_DENIED` if *handle* does not have `ZX_RIGHT_WRITE`.
///
/// `ZX_ERR_INVALID_ARGS` if *value* is an invalid pointer.
///
/// ## See also
///
/// - [`zx_object_wait_async()`]
/// - [`zx_object_wait_many()`]
/// - [`zx_object_wait_one()`]
/// - [`zx_counter_create()`]
/// - [`zx_counter_add()`]
/// - [`zx_counter_read()`]
///
/// [`zx_object_wait_async()`]: object_wait_async.md
/// [`zx_object_wait_many()`]: object_wait_many.md
/// [`zx_object_wait_one()`]: object_wait_one.md
/// [`zx_counter_create()`]: counter_create.md
/// [`zx_counter_add()`]: counter_add.md
/// [`zx_counter_read()`]: counter_read.md
strict Write(resource struct {
handle Handle;
value int64;
}) -> () error Status;
};