| // 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; |
| }; |