| // Copyright Microsoft and CHERIoT Contributors. | 
 | // SPDX-License-Identifier: MIT | 
 |  | 
 | #pragma once | 
 | #include <cdefs.h> | 
 | #include <stdint.h> | 
 | #include <timeout.h> | 
 |  | 
 | enum [[clang::flag_enum]] FutexWaitFlags{ | 
 |   /// No flags | 
 |   FutexNone = 0, | 
 |   /** | 
 |    * This futex uses priority inheritance.  The low 16 bits of the futex word | 
 |    * are assumed to hold the thread ID of the thread that currently holds the | 
 |    * lock. | 
 |    */ | 
 |   FutexPriorityInheritance = (1 << 0)}; | 
 |  | 
 | /** | 
 |  * Compare the value at `address` to `expected` and, if they match, sleep the | 
 |  * thread until a wake event is sent with `futex_wake` or until this the thread | 
 |  * has slept for `ticks` ticks. | 
 |  * | 
 |  * The value of `ticks` specifies the permitted timeout.  See `timeout.h` for | 
 |  * details. | 
 |  * | 
 |  * The `address` argument must permit loading four bytes of data after the | 
 |  * address. | 
 |  * | 
 |  * The `flags` argument contains flags that may control the behaviour of the | 
 |  * call. | 
 |  * | 
 |  * This returns: | 
 |  *  - 0 on success: either `*address` and `expected` differ or a wake is | 
 |  *    received. | 
 |  *  - `-EINVAL` if the arguments are invalid. | 
 |  *  - `-ETIMEOUT` if the timeout expires. | 
 |  */ | 
 | [[cheri::interrupt_state(disabled)]] int __cheri_compartment("sched") | 
 |   futex_timed_wait(Timeout        *ticks, | 
 |                    const uint32_t *address, | 
 |                    uint32_t        expected, | 
 |                    uint32_t flags  __if_cxx(= FutexNone)); | 
 |  | 
 | /** | 
 |  * Compare the value at `address` to `expected` and, if they match, sleep the | 
 |  * thread until a wake event is sent with `futex_wake`. | 
 |  * | 
 |  * The `address` argument must permit loading four bytes of data after the | 
 |  * address. | 
 |  * | 
 |  * This returns 0 on success or `-EINVAL` if the arguments are invalid. | 
 |  */ | 
 | __always_inline static int futex_wait(const uint32_t *address, | 
 |                                       uint32_t        expected) | 
 | { | 
 | 	Timeout t = {0, UnlimitedTimeout}; | 
 | 	return futex_timed_wait(&t, address, expected, FutexNone); | 
 | } | 
 |  | 
 | /** | 
 |  * Wakes up to `count` threads that are sleeping with `futex[_timed]_wait` on | 
 |  * `address`. | 
 |  * | 
 |  * The `address` argument must permit storing four bytes of data after the | 
 |  * address. This call does not store to the address but requiring store | 
 |  * permission prevents a thread from waking up a futex that it cannot possibly | 
 |  * have moved to a different state. | 
 |  * | 
 |  * The return value for a successful call is the number of threads that were | 
 |  * woken.  `-EINVAL` is returned for invalid arguments. | 
 |  */ | 
 | [[cheri::interrupt_state(disabled)]] int __cheri_compartment("sched") | 
 |   futex_wake(uint32_t *address, uint32_t count); |