| /** @file |
| * @brief Network timer with wrap around |
| * |
| * Timer that runs longer than about 49 days needs to calculate wraps. |
| */ |
| |
| /* |
| * Copyright (c) 2018 Intel Corporation |
| * Copyright (c) 2020 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #ifndef ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ |
| #define ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ |
| |
| /** |
| * @brief Network long timeout primitives and helpers |
| * @defgroup net_timeout Network long timeout primitives and helpers |
| * @ingroup networking |
| * @{ |
| */ |
| |
| #include <string.h> |
| #include <stdbool.h> |
| #include <limits.h> |
| #include <zephyr/types.h> |
| #include <sys/slist.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** @brief Divisor used to support ms resolution timeouts. |
| * |
| * Because delays are processed in work queues which are not invoked |
| * synchronously with clock changes we need to be able to detect timeouts |
| * after they occur, which requires comparing "deadline" to "now" with enough |
| * "slop" to handle any observable latency due to "now" advancing past |
| * "deadline". |
| * |
| * The simplest solution is to use the native conversion of the well-defined |
| * 32-bit unsigned difference to a 32-bit signed difference, which caps the |
| * maximum delay at INT32_MAX. This is compatible with the standard mechanism |
| * for detecting completion of deadlines that do not overflow their |
| * representation. |
| */ |
| #define NET_TIMEOUT_MAX_VALUE ((uint32_t)INT32_MAX) |
| |
| /** Generic struct for handling network timeouts. |
| * |
| * Except for the linking node, all access to state from these objects must go |
| * through the defined API. |
| */ |
| struct net_timeout { |
| /** Used to link multiple timeouts that share a common timer infrastructure. |
| * |
| * For examples a set of related timers may use a single delayed work |
| * structure, which is always scheduled at the shortest time to a |
| * timeout event. |
| */ |
| sys_snode_t node; |
| |
| /* Time at which the timer was last set. |
| * |
| * This usually corresponds to the low 32 bits of k_uptime_get(). */ |
| uint32_t timer_start; |
| |
| /* Portion of remaining timeout that does not exceed |
| * NET_TIMEOUT_MAX_VALUE. |
| * |
| * This value is updated in parallel with timer_start and wrap_counter |
| * by net_timeout_evaluate(). |
| */ |
| uint32_t timer_timeout; |
| |
| /* Timer wrap count. |
| * |
| * This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that |
| * have yet to pass. It is also updated along with timer_start and |
| * wrap_counter by net_timeout_evaluate(). |
| */ |
| uint32_t wrap_counter; |
| }; |
| |
| /** @brief Configure a network timeout structure. |
| * |
| * @param timeout a pointer to the timeout state. |
| * |
| * @param lifetime the duration of the timeout in seconds. |
| * |
| * @param now the time at which the timeout started counting down, in |
| * milliseconds. This is generally a captured value of k_uptime_get_32(). |
| */ |
| void net_timeout_set(struct net_timeout *timeout, |
| uint32_t lifetime, |
| uint32_t now); |
| |
| /** @brief Return the 64-bit system time at which the timeout will complete. |
| * |
| * @note Correct behavior requires invocation of net_timeout_evaluate() at its |
| * specified intervals. |
| * |
| * @param timeout state a pointer to the timeout state, initialized by |
| * net_timeout_set() and maintained by net_timeout_evaluate(). |
| * |
| * @param now the full-precision value of k_uptime_get() relative to which the |
| * deadline will be calculated. |
| * |
| * @return the value of k_uptime_get() at which the timeout will expire. |
| */ |
| int64_t net_timeout_deadline(const struct net_timeout *timeout, |
| int64_t now); |
| |
| /** @brief Calculate the remaining time to the timeout in whole seconds. |
| * |
| * @note This function rounds the remaining time down, i.e. if the timeout |
| * will occur in 3500 milliseconds the value 3 will be returned. |
| * |
| * @note Correct behavior requires invocation of net_timeout_evaluate() at its |
| * specified intervals. |
| * |
| * @param timeout a pointer to the timeout state |
| * |
| * @param now the time relative to which the estimate of remaining time should |
| * be calculated. This should be recently captured value from |
| * k_uptime_get_32(). |
| * |
| * @retval 0 if the timeout has completed. |
| * @retval positive the remaining duration of the timeout, in seconds. |
| */ |
| uint32_t net_timeout_remaining(const struct net_timeout *timeout, |
| uint32_t now); |
| |
| /** @brief Update state to reflect elapsed time and get new delay. |
| * |
| * This function must be invoked periodically to (1) apply the effect of |
| * elapsed time on what remains of a total delay that exceeded the maximum |
| * representable delay, and (2) determine that either the timeout has |
| * completed or that the infrastructure must wait a certain period before |
| * checking again for completion. |
| * |
| * @param timeout a pointer to the timeout state |
| * |
| * @param now the time relative to which the estimate of remaining time should |
| * be calculated. This should be recently captured value from |
| * k_uptime_get_32(). |
| * |
| * @retval 0 if the timeout has completed |
| * @retval positive the maximum delay until the state of this timeout should |
| * be re-evaluated, in milliseconds. |
| */ |
| uint32_t net_timeout_evaluate(struct net_timeout *timeout, |
| uint32_t now); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| /** |
| * @} |
| */ |
| |
| |
| #endif /* ZEPHYR_INCLUDE_NET_NET_TIMEOUT_H_ */ |