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_ */
|