166 lines
5.1 KiB
C
166 lines
5.1 KiB
C
/** @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_ */
|