1 /** @file 2 * @brief Network timer with wrap around 3 * 4 * Timer that runs longer than about 49 days needs to calculate wraps. 5 */ 6 7 /* 8 * Copyright (c) 2018 Intel Corporation 9 * Copyright (c) 2020 Nordic Semiconductor ASA 10 * 11 * SPDX-License-Identifier: Apache-2.0 12 */ 13 14 #ifndef ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ 15 #define ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ 16 17 /** 18 * @brief Network long timeout primitives and helpers 19 * @defgroup net_timeout Network long timeout primitives and helpers 20 * @since 1.14 21 * @version 0.8.0 22 * @ingroup networking 23 * @{ 24 */ 25 26 #include <string.h> 27 #include <stdbool.h> 28 #include <limits.h> 29 #include <zephyr/types.h> 30 #include <zephyr/sys/slist.h> 31 32 #ifdef __cplusplus 33 extern "C" { 34 #endif 35 36 /** @brief Divisor used to support ms resolution timeouts. 37 * 38 * Because delays are processed in work queues which are not invoked 39 * synchronously with clock changes we need to be able to detect timeouts 40 * after they occur, which requires comparing "deadline" to "now" with enough 41 * "slop" to handle any observable latency due to "now" advancing past 42 * "deadline". 43 * 44 * The simplest solution is to use the native conversion of the well-defined 45 * 32-bit unsigned difference to a 32-bit signed difference, which caps the 46 * maximum delay at INT32_MAX. This is compatible with the standard mechanism 47 * for detecting completion of deadlines that do not overflow their 48 * representation. 49 */ 50 #define NET_TIMEOUT_MAX_VALUE ((uint32_t)INT32_MAX) 51 52 /** Generic struct for handling network timeouts. 53 * 54 * Except for the linking node, all access to state from these objects must go 55 * through the defined API. 56 */ 57 struct net_timeout { 58 /** Used to link multiple timeouts that share a common timer infrastructure. 59 * 60 * For examples a set of related timers may use a single delayed work 61 * structure, which is always scheduled at the shortest time to a 62 * timeout event. 63 */ 64 sys_snode_t node; 65 66 /** Time at which the timer was last set. 67 * 68 * This usually corresponds to the low 32 bits of k_uptime_get(). 69 */ 70 uint32_t timer_start; 71 72 /** Portion of remaining timeout that does not exceed 73 * NET_TIMEOUT_MAX_VALUE. 74 * 75 * This value is updated in parallel with timer_start and wrap_counter 76 * by net_timeout_evaluate(). 77 */ 78 uint32_t timer_timeout; 79 80 /** Timer wrap count. 81 * 82 * This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that 83 * have yet to pass. It is also updated along with timer_start and 84 * wrap_counter by net_timeout_evaluate(). 85 */ 86 uint32_t wrap_counter; 87 }; 88 89 /** @brief Configure a network timeout structure. 90 * 91 * @param timeout a pointer to the timeout state. 92 * 93 * @param lifetime the duration of the timeout in seconds. 94 * 95 * @param now the time at which the timeout started counting down, in 96 * milliseconds. This is generally a captured value of k_uptime_get_32(). 97 */ 98 void net_timeout_set(struct net_timeout *timeout, 99 uint32_t lifetime, 100 uint32_t now); 101 102 /** @brief Return the 64-bit system time at which the timeout will complete. 103 * 104 * @note Correct behavior requires invocation of net_timeout_evaluate() at its 105 * specified intervals. 106 * 107 * @param timeout state a pointer to the timeout state, initialized by 108 * net_timeout_set() and maintained by net_timeout_evaluate(). 109 * 110 * @param now the full-precision value of k_uptime_get() relative to which the 111 * deadline will be calculated. 112 * 113 * @return the value of k_uptime_get() at which the timeout will expire. 114 */ 115 int64_t net_timeout_deadline(const struct net_timeout *timeout, 116 int64_t now); 117 118 /** @brief Calculate the remaining time to the timeout in whole seconds. 119 * 120 * @note This function rounds the remaining time down, i.e. if the timeout 121 * will occur in 3500 milliseconds the value 3 will be returned. 122 * 123 * @note Correct behavior requires invocation of net_timeout_evaluate() at its 124 * specified intervals. 125 * 126 * @param timeout a pointer to the timeout state 127 * 128 * @param now the time relative to which the estimate of remaining time should 129 * be calculated. This should be recently captured value from 130 * k_uptime_get_32(). 131 * 132 * @retval 0 if the timeout has completed. 133 * @retval positive the remaining duration of the timeout, in seconds. 134 */ 135 uint32_t net_timeout_remaining(const struct net_timeout *timeout, 136 uint32_t now); 137 138 /** @brief Update state to reflect elapsed time and get new delay. 139 * 140 * This function must be invoked periodically to (1) apply the effect of 141 * elapsed time on what remains of a total delay that exceeded the maximum 142 * representable delay, and (2) determine that either the timeout has 143 * completed or that the infrastructure must wait a certain period before 144 * checking again for completion. 145 * 146 * @param timeout a pointer to the timeout state 147 * 148 * @param now the time relative to which the estimate of remaining time should 149 * be calculated. This should be recently captured value from 150 * k_uptime_get_32(). 151 * 152 * @retval 0 if the timeout has completed 153 * @retval positive the maximum delay until the state of this timeout should 154 * be re-evaluated, in milliseconds. 155 */ 156 uint32_t net_timeout_evaluate(struct net_timeout *timeout, 157 uint32_t now); 158 159 #ifdef __cplusplus 160 } 161 #endif 162 163 /** 164 * @} 165 */ 166 167 168 #endif /* ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ */ 169