mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
sul: lws_sul_nonmonotonic_adjust
FreeRTOS only supports nonmonotonic time, when we correct it by, eg, ntpclient, we offset all the existing sul timeouts. This adds an internal helper function to correct existing sul timeouts by the step amount, and call it in lws ntpclient implementation when adjusting the gettimeofday() time.
This commit is contained in:
parent
f902873634
commit
2e1969187d
3 changed files with 87 additions and 4 deletions
|
@ -1447,6 +1447,9 @@ lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len);
|
|||
int
|
||||
lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len);
|
||||
|
||||
lws_usec_t
|
||||
lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us);
|
||||
|
||||
|
||||
enum {
|
||||
LW5CHS_RET_RET0,
|
||||
|
|
|
@ -103,7 +103,7 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow)
|
|||
lws_system_do_attach(pt);
|
||||
|
||||
/* must be at least 1 */
|
||||
assert(own_len);
|
||||
assert(own_len > 0);
|
||||
|
||||
/*
|
||||
* Of the own_len sul owning lists, the earliest next sul could be on
|
||||
|
@ -154,6 +154,72 @@ __lws_sul_service_ripe(lws_dll2_owner_t *own, int own_len, lws_usec_t usnow)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally we use the OS monotonic time, which does not step when the
|
||||
* gettimeofday() time is adjusted after, eg, ntpclient. But on some OSes,
|
||||
* high resolution monotonic time doesn't exist; sul time is computed from and
|
||||
* compared against gettimeofday() time and breaks when that steps.
|
||||
*
|
||||
* For those cases, this allows us to retrospectively adjust existing suls on
|
||||
* all owning lists by the step amount, at the same time we adjust the
|
||||
* nonmonotonic clock. Then nothing breaks so long as we do this when the
|
||||
* gettimeofday() clock is stepped.
|
||||
*
|
||||
* Linux and so on offer Posix MONOTONIC, which lws uses. FreeRTOS doesn't
|
||||
* have a high-resolution monotonic clock and has to use gettimeofday(), which
|
||||
* requires this adjustment when it is stepped.
|
||||
*/
|
||||
|
||||
lws_usec_t
|
||||
lws_sul_nonmonotonic_adjust(struct lws_context *ctx, int64_t step_us)
|
||||
{
|
||||
struct lws_context_per_thread *pt = &ctx->pt[0];
|
||||
int n, m;
|
||||
|
||||
/*
|
||||
* for each pt
|
||||
*/
|
||||
|
||||
for (m = 0; m < ctx->count_threads; m++) {
|
||||
|
||||
/*
|
||||
* For each owning list...
|
||||
*/
|
||||
|
||||
lws_pt_lock(pt, __func__);
|
||||
|
||||
for (n = 0; n < LWS_COUNT_PT_SUL_OWNERS; n++) {
|
||||
|
||||
if (!pt->pt_sul_owner[n].count)
|
||||
continue;
|
||||
|
||||
/* ... and for every existing sul on a list... */
|
||||
|
||||
lws_start_foreach_dll(struct lws_dll2 *, p,
|
||||
lws_dll2_get_head(
|
||||
&pt->pt_sul_owner[n])) {
|
||||
lws_sorted_usec_list_t *sul = lws_container_of(
|
||||
p, lws_sorted_usec_list_t, list);
|
||||
|
||||
/*
|
||||
* ... retrospectively step its ripe time by the
|
||||
* step we will adjust the gettimeofday() clock
|
||||
* with
|
||||
*/
|
||||
|
||||
sul->us += step_us;
|
||||
|
||||
} lws_end_foreach_dll(p);
|
||||
}
|
||||
|
||||
lws_pt_unlock(pt);
|
||||
|
||||
pt++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Earliest wakeable event on any pt
|
||||
*/
|
||||
|
|
|
@ -127,6 +127,8 @@ callback_ntpc(struct lws *wsi, enum lws_callback_reasons reason, void *user,
|
|||
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
||||
lws_get_protocol(wsi));
|
||||
uint8_t pkt[LWS_PRE + 48];
|
||||
struct timeval t1;
|
||||
int64_t delta_us;
|
||||
uint64_t ns;
|
||||
|
||||
switch (reason) {
|
||||
|
@ -224,16 +226,28 @@ do_close:
|
|||
ns = lws_ser_ru32be(((uint8_t *)in) + 40) - 2208988800;
|
||||
ns = (ns * 1000000000) + lws_ser_ru32be(((uint8_t *)in) + 44);
|
||||
|
||||
lwsl_notice("%s: Unix time: %llu\n", __func__,
|
||||
(unsigned long long)ns / 1000000000);
|
||||
/*
|
||||
* Compute the step
|
||||
*/
|
||||
|
||||
#if defined(LWS_ESP_PLATFORM)
|
||||
gettimeofday(&t1, NULL);
|
||||
|
||||
delta_us = (ns / 1000) -
|
||||
((t1.tv_sec * LWS_US_PER_SEC) + t1.tv_usec);
|
||||
|
||||
lwsl_notice("%s: Unix time: %llu, step: %lldus\n", __func__,
|
||||
(unsigned long long)ns / 1000000000,
|
||||
delta_us);
|
||||
|
||||
#if defined(LWS_PLAT_FREERTOS)
|
||||
{
|
||||
struct timeval t;
|
||||
|
||||
t.tv_sec = (unsigned long long)ns / 1000000000;
|
||||
t.tv_usec = (ns % 1000000000) / 1000;
|
||||
|
||||
lws_sul_nonmonotonic_adjust(wsi->context, delta_us);
|
||||
|
||||
settimeofday(&t, NULL);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue