1
0
Fork 0
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:
Andy Green 2020-07-03 06:42:31 +01:00
parent f902873634
commit 2e1969187d
3 changed files with 87 additions and 4 deletions

View file

@ -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,

View file

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

View file

@ -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