| // Copyright Microsoft and CHERIoT Contributors. | 
 | // SPDX-License-Identifier: MIT | 
 |  | 
 | #pragma once | 
 | /** | 
 |  * @file timeout.h | 
 |  * | 
 |  * This file contains the types used for timeouts across scheduler APIs. | 
 |  */ | 
 |  | 
 | #include <cdefs.h> | 
 | #include <stdint.h> | 
 |  | 
 | /** | 
 |  * Quantity used for measuring time for timeouts.  The unit is scheduler ticks. | 
 |  */ | 
 | typedef uint32_t Ticks; | 
 |  | 
 | /// Value indicating an unbounded timeout. | 
 | static __if_cxx(constexpr) const Ticks UnlimitedTimeout = UINT32_MAX; | 
 |  | 
 | /** | 
 |  * Structure representing a timeout.  This is intended to allow a single | 
 |  * instance to be chained across blocking calls. | 
 |  * | 
 |  * Timeouts *may not be stored in the heap*.  Handling timeout structures that | 
 |  * may disappear between sleeping and waking is very complicated and would | 
 |  * impact a lot of fast paths.  Instead, most functions that take a timeout | 
 |  * will simply fail if the timeout is on the heap. | 
 |  */ | 
 | typedef struct Timeout | 
 | { | 
 | 	/** | 
 | 	 * The time that has elapsed during blocking operations for this timeout | 
 | 	 * structure.  This should be initialised to 0.  It may exceed the initial | 
 | 	 * value of `remaining` if a higher-priority thread preempts the blocking | 
 | 	 * thread. | 
 | 	 */ | 
 | 	Ticks elapsed __if_cxx(= 0); | 
 | 	/** | 
 | 	 * The remaining time. This is clamped at 0 on subtraction. A special | 
 | 	 * value of `UnlimitedTimeout` can be set to represent an unlimited | 
 | 	 * timeout. | 
 | 	 */ | 
 | 	Ticks remaining; | 
 | #ifdef __cplusplus | 
 | 	/** | 
 | 	 * Constructor, initialises this structure to allow `time` ticks to | 
 | 	 *  elapse. | 
 | 	 */ | 
 | 	Timeout(Ticks time) : remaining(time) {} | 
 |  | 
 | 	/** | 
 | 	 * Constructor that initialises both fields, should be used only for | 
 | 	 * initialiser-list initialisation in code that needs to compile as both C | 
 | 	 * and C++. | 
 | 	 */ | 
 | 	Timeout(Ticks elapsed, Ticks remaining) | 
 | 	  : elapsed(elapsed), remaining(remaining) | 
 | 	{ | 
 | 	} | 
 |  | 
 | 	/** | 
 | 	 * Update this timeout if `time` ticks have elapsed.  This function | 
 | 	 * saturates the values on overflow. | 
 | 	 */ | 
 | 	inline void elapse(Ticks time) | 
 | 	{ | 
 | 		if (__builtin_add_overflow(time, elapsed, &elapsed)) | 
 | 		{ | 
 | 			elapsed = UnlimitedTimeout; | 
 | 		} | 
 | 		if (remaining != UnlimitedTimeout && | 
 | 		    __builtin_sub_overflow(remaining, time, &remaining)) | 
 | 		{ | 
 | 			remaining = 0; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/** | 
 | 	 * Helper indicating whether the owner of this timeout may block. | 
 | 	 */ | 
 | 	bool may_block() | 
 | 	{ | 
 | 		return remaining > 0; | 
 | 	} | 
 | #endif | 
 | } Timeout; |