#include <os/os_sync_wait_on_address.h>

os/os_sync_wait_on_address.h

@header Low-level Darwin's futex style APIs.
includes: Availability.h, stddef.h, stdint.h, os/base.h, os/clock.h
5 functions · 2 enums · 2 typedefs · 1 macro

macroOS_WAIT_ON_ADDR_AVAILABILITY

#define OS_WAIT_ON_ADDR_AVAILABILITY __API_AVAILABLE(macos(14.4), ios(17.4), tvos(17.4), watchos(10.4))

enumos_sync_wait_on_address_flags_t

@typedef os_sync_wait_on_address_flags_t @const OS_SYNC_WAIT_ON_ADDRESS_NONE This flag should be used as a default flag when no other flags listed below are required. @const OS_SYNC_WAIT_ON_ADDRESS_SHARED This flag should be used when synchronizing among multiple processes by placing the @addr passed to os_sync_wait_on_address and its variants in a shared memory region. When using this flag, it is important to pass OS_SYNC_WAKE_BY_ADDRESS_SHARED flag along with the exact same @addr to os_sync_wake_by_address_any and its variants to correctly find and wake up blocked waiters on the @addr. This flag should not be used when synchronizing among multiple threads of a single process. It allows the kernel to perform performance optimizations as the @addr is local to the calling process.
underlying type uint32_t
OS_SYNC_WAIT_ON_ADDRESS_NONE0
OS_SYNC_WAIT_ON_ADDRESS_SHARED1

typedefos_sync_wait_on_address_flags_t

typedef enum os_sync_wait_on_address_flags_t os_sync_wait_on_address_flags_t;

functionos_sync_wait_on_address

OS_WAIT_ON_ADDR_AVAILABILITY OS_EXPORT OS_NOTHROW OS_NONNULL_ALL int os_sync_wait_on_address(
	void *addr,
	uint64_t value,
	size_t size,
	os_sync_wait_on_address_flags_t flags
)
@function os_sync_wait_on_address This function provides an atomic compare-and-wait functionality that can be used to implement other higher level synchronization primitives. It reads a value from @addr, compares it to expected @value and blocks the calling thread if they are equal. This sequence of operations is done atomically with respect to other concurrent operations that can be performed on this @addr by other threads using this same function or os_sync_wake_by_addr variants. At this point, the blocked calling thread is considered to be a waiter on this @addr, waiting to be woken up by a call to os_sync_wake_by_addr variants. If the value at @addr turns out to be different than expected, the calling thread returns immediately without blocking. This function is expected to be used for implementing synchronization primitives that do not have a sense of ownership (e.g. condition variables, semaphores) as it does not provide priority inversion avoidance. For locking primitives, it is recommended that you use existing OS primitives such as os_unfair_lock API family / pthread mutex or std::mutex. @param addr The userspace address to be used for atomic compare-and-wait. This address must be aligned to @size. @param value The value expected at @addr. @param size The size of @value, in bytes. This can be either 4 or 8 today. For @value of @size 4 bytes, the upper 4 bytes of @value are ignored. @param flags Flags to alter behavior of os_sync_wait_on_address. See os_sync_wait_on_address_flags_t. @return If the calling thread is woken up by a call to os_sync_wake_by_addr variants or the value at @addr is different than expected, this function returns successfully and the return value indicates the number of outstanding waiters blocked on this address. In the event of an error, returns -1 with errno set to indicate the error. EINVAL : Invalid flags or size. EINVAL : The @addr passed is NULL or misaligned. EINVAL : The operation associated with existing kernel state at this @addr is inconsistent with what the caller has requested. It is important to make sure consistent values are passed across wait and wake APIs for @addr, @size and the shared memory specification (See os_sync_wait_on_address_flags_t). It is possible for the os_sync_wait_on_address and its variants to perform an early return in the event of following errors where user may want to re-try the wait operation. E.g. low memory conditions could cause such early return. It is important to read the current value at the @addr before re-trying to ensure that the new value still requires waiting on @addr. ENOMEM : Unable to allocate memory for kernel internal data structures. EINTR : The syscall was interrupted / spurious wake up. EFAULT : Unable to read value from the @addr. Kernel copyin failed. It is possible to receive EFAULT error in following cases: 1. The @addr is an invalid address. This is a programmer error. 2. The @addr is valid; but, this is a transient error such as due to low memory conditions. User may want to re-try the wait operation. Following code snippet illustrates a possible re-try loop. <code> retry: current = atomic_load_explicit(addr, memory_order_relaxed); if (current != expected) { int ret = os_sync_wait_on_address(addr, current, size, flags); if ((ret < 0) && ((errno == EINTR) || (errno == EFAULT))) { goto retry; } } </code>

functionos_sync_wait_on_address_with_deadline

OS_WAIT_ON_ADDR_AVAILABILITY OS_EXPORT OS_NOTHROW OS_NONNULL_ALL int os_sync_wait_on_address_with_deadline(
	void *addr,
	uint64_t value,
	size_t size,
	os_sync_wait_on_address_flags_t flags,
	os_clockid_t clockid,
	uint64_t deadline
)
@function os_sync_wait_on_address_with_deadline This function is a variant of os_sync_wait_on_address that allows the calling thread to specify a deadline until which it is willing to block. @param addr The userspace address to be used for atomic compare-and-wait. This address must be aligned to @size. @param value The value expected at @addr. @param size The size of @value, in bytes. This can be either 4 or 8 today. For @value of @size 4 bytes, the upper 4 bytes of @value are ignored. @param flags Flags to alter behavior of os_sync_wait_on_address_with_deadline. See os_sync_wait_on_address_flags_t. @param clockid This value anchors @deadline argument to a specific clock id. See os_clockid_t. @param deadline This value is used to specify a deadline until which the calling thread is willing to block. Passing zero for the @deadline results in an error being returned. It is recommended to use os_sync_wait_on_address API to block indefinitely until woken up by a call to os_sync_wake_by_address_any or os_sync_wake_by_address_all APIs. @return If the calling thread is woken up by a call to os_sync_wake_by_addr variants or the value at @addr is different than expected, this function returns successfully and the return value indicates the number of outstanding waiters blocked on this address. In the event of an error, returns -1 with errno set to indicate the error. In addition to errors returned by os_sync_wait_on_address, this function can return the following additional error codes. EINVAL : Invalid clock id. EINVAL : The @deadline passed is 0. ETIMEDOUT : Deadline expired.

functionos_sync_wait_on_address_with_timeout

OS_WAIT_ON_ADDR_AVAILABILITY OS_EXPORT OS_NOTHROW OS_NONNULL_ALL int os_sync_wait_on_address_with_timeout(
	void *addr,
	uint64_t value,
	size_t size,
	os_sync_wait_on_address_flags_t flags,
	os_clockid_t clockid,
	uint64_t timeout_ns
)
@function os_sync_wait_on_address_with_timeout This function is a variant of os_sync_wait_on_address that allows the calling thread to specify a timeout until which it is willing to block. @param addr The userspace address to be used for atomic compare-and-wait. This address must be aligned to @size. @param value The value expected at @addr. @param size The size of @value, in bytes. This can be either 4 or 8 today. For @value of @size 4 bytes, the upper 4 bytes of @value are ignored. @param flags Flags to alter behavior of os_sync_wait_on_address_with_timeout. See os_sync_wait_on_address_flags_t. @param clockid This value anchors @timeout_ns argument to a specific clock id. See os_clockid_t. @param timeout_ns This value is used to specify a timeout in nanoseconds until which the calling thread is willing to block. Passing zero for the @timeout_ns results in an error being returned. It is recommended to use os_sync_wait_on_address API to block indefinitely until woken up by a call to os_sync_wake_by_address_any or os_sync_wake_by_address_all APIs. @return If the calling thread is woken up by a call to os_sync_wake_by_address variants or the value at @addr is different than expected, this function returns successfully and the return value indicates the number of outstanding waiters blocked on this address. In the event of an error, returns -1 with errno set to indicate the error. In addition to errors returned by os_sync_wait_on_address, this function can return the following additional error codes. EINVAL : Invalid clock id. EINVAL : The @timeout_ns passed is 0. ETIMEDOUT : Timeout expired.

enumos_sync_wake_by_address_flags_t

@typedef os_sync_wake_by_address_flags_t @const OS_SYNC_WAKE_BY_ADDRESS_NONE This flag should be used as a default flag when no other flags listed below are required. @const OS_SYNC_WAKE_BY_ADDRESS_SHARED This flag should be used when synchronizing among multiple processes by placing the @addr passed to os_sync_wake_by_address_any and its variants in a shared memory region. When using this flag, it is important to pass OS_SYNC_WAIT_ON_ADDRESS_SHARED flag along with the exact same @addr to os_sync_wait_on_address and its variants to correctly find and wake up blocked waiters on the @addr. This flag should not be used when synchronizing among multiple threads of a single process. It allows the kernel to perform performance optimizations as the @addr is local the calling process.
underlying type uint32_t
OS_SYNC_WAKE_BY_ADDRESS_NONE0
OS_SYNC_WAKE_BY_ADDRESS_SHARED1

typedefos_sync_wake_by_address_flags_t

typedef enum os_sync_wake_by_address_flags_t os_sync_wake_by_address_flags_t;

functionos_sync_wake_by_address_any

OS_WAIT_ON_ADDR_AVAILABILITY OS_EXPORT OS_NOTHROW OS_NONNULL_ALL int os_sync_wake_by_address_any(
	void *addr,
	size_t size,
	os_sync_wake_by_address_flags_t flags
)
@function os_sync_wake_by_address_any This function wakes up one waiter out of all those blocked in os_sync_wait_on_address or its variants on the @addr. No guarantee is provided about which specific waiter is woken up. @param addr The userspace address to be used for waking up the blocked waiter. It should be same as what is passed to os_sync_wait_on_address or its variants. @param size The size of lock value, in bytes. This can be either 4 or 8 today. It should be same as what is passed to os_sync_wait_on_address or its variants. @param flags Flags to alter behavior of os_sync_wake_by_address_any. See os_sync_wake_by_address_flags_t. @return Returns 0 on success. In the event of an error, returns -1 with errno set to indicate the error. EINVAL : Invalid flags or size. EINVAL : The @addr passed is NULL. EINVAL : The operation associated with existing kernel state at this @addr is inconsistent with what caller has requested. It is important to make sure consistent values are passed across wait and wake APIs for @addr, @size and the shared memory specification (See os_sync_wake_by_address_flags_t). ENOENT : No waiter(s) found waiting on the @addr.

functionos_sync_wake_by_address_all

OS_WAIT_ON_ADDR_AVAILABILITY OS_EXPORT OS_NOTHROW OS_NONNULL_ALL int os_sync_wake_by_address_all(
	void *addr,
	size_t size,
	os_sync_wake_by_address_flags_t flags
)
@function os_sync_wake_by_address_all This function is a variant of os_sync_wake_by_address_any that wakes up all waiters blocked in os_sync_wait_on_address or its variants. @param addr The userspace address to be used for waking up the blocked waiters. It should be same as what is passed to os_sync_wait_on_address or its variants. @param size The size of lock value, in bytes. This can be either 4 or 8 today. It should be same as what is passed to os_sync_wait_on_address or its variants. @param flags Flags to alter behavior of os_sync_wake_by_address_all. See os_sync_wake_by_address_flags_t. @return Returns 0 on success. In the event of an error, returns -1 with errno set to indicate the error. This function returns same error codes as returned by os_sync_wait_on_address.