Line data Source code
1 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 1 : #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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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 1 : 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_ */