{"schema":"libjg2-1",
"vpath":"/git/",
"avatar":"/git/avatar/",
"alang":"",
"gen_ut":1746418058,
"reponame":"libwebsockets",
"desc":"libwebsockets lightweight C networking library",
"owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets",
"f":3,
"items": [
{"schema":"libjg2-1",
"cid":"778949f7ce98afd24793826ec9e32b06",
"commit": {"type":"commit",
"time": 1565253909,
"time_ofs": 60,
"oid_tree": { "oid": "41f048d689474b1ca2cc86d955c32b17e682ebc6", "alias": []},
"oid":{ "oid": "fed78bef4246389cd53215ee0e2671d3bac35df1", "alias": []},
"msg": "sequencer: upgrade timeout to use us",
"sig_commit": { "git_time": { "time": 1565253909, "offset": 60 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },
"sig_author": { "git_time": { "time": 1565242214, "offset": 60 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }},
"body": "sequencer: upgrade timeout to use us\n\nAdapt service loops and event libs to use microsecond waits\ninternally, for hrtimer and sequencer. Reduce granularity\naccording to platform / event lib wait.\n\nAdd a helper so there's a single place to extend it."
,
"diff": "diff --git a/CMakeLists.txt b/CMakeLists.txt\nindex f62245a..620469b 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -1305,6 +1305,11 @@ if (LWS_WITH_HTTP_PROXY)\n \t\tlib/roles/http/server/rewrite.c)\n endif()\n \n+if (LWS_WITH_NETWORK)\n+\tlist(APPEND SOURCES\n+\t\tlib/event-libs/common.c)\n+endif()\n+\n if (LWS_WITH_POLL AND LWS_WITH_NETWORK)\n \tlist(APPEND SOURCES\n \t\tlib/event-libs/poll/poll.c)\ndiff --git a/include/libwebsockets.h b/include/libwebsockets.h\nindex 38789da..8d81d30 100644\n--- a/include/libwebsockets.h\n+++ b/include/libwebsockets.h\n@@ -42,6 +42,12 @@ extern \u0022C\u0022 {\n * CARE: everything using cmake defines needs to be below here\n */\n \n+#define LWS_US_PER_SEC 1000000\n+#define LWS_MS_PER_SEC 1000\n+#define LWS_US_PER_MS 1000\n+\n+#define LWS_US_TO_MS(x) ((x + (LWS_US_PER_MS / 2)) / LWS_US_PER_MS)\n+\n #if defined(LWS_HAS_INTPTR_T)\n #include \u003cstdint.h\u003e\n #define lws_intptr_t intptr_t\ndiff --git a/include/libwebsockets/abstract/abstract.h b/include/libwebsockets/abstract/abstract.h\nindex b9d856a..d8f0228 100644\n--- a/include/libwebsockets/abstract/abstract.h\n+++ b/include/libwebsockets/abstract/abstract.h\n@@ -73,7 +73,7 @@ typedef struct lws_abs {\n \tconst struct lws_abs_transport\t*at;\n \tconst lws_token_map_t\t\t*at_tokens;\n \n-\tlws_sequencer_t\t\t\t*seq;\n+\tlws_seq_t\t\t\t*seq;\n \tvoid\t\t\t\t*opaque_user_data;\n \n \t/*\ndiff --git a/include/libwebsockets/lws-client.h b/include/libwebsockets/lws-client.h\nindex d2eab9d..d218e2b 100644\n--- a/include/libwebsockets/lws-client.h\n+++ b/include/libwebsockets/lws-client.h\n@@ -49,7 +49,7 @@ enum lws_client_connect_ssl_connection_flags {\n \t\t * */\n };\n \n-typedef struct lws_sequencer lws_sequencer_t;\n+typedef struct lws_sequencer lws_seq_t;\n \n /** struct lws_client_connect_info - parameters to connect with when using\n *\t\t\t\t lws_client_connect_via_info() */\n@@ -121,8 +121,8 @@ struct lws_client_connect_info {\n \t * tokens\n \t */\n \n-\tlws_sequencer_t *seq;\n-\t/**\u003c NULL, or an lws_sequencer_t that wants to be given messages about\n+\tlws_seq_t *seq;\n+\t/**\u003c NULL, or an lws_seq_t that wants to be given messages about\n \t * this wsi's lifecycle as it connects, errors or closes.\n \t */\n \n@@ -130,7 +130,7 @@ struct lws_client_connect_info {\n \t/**\u003c This data has no meaning to lws but is applied to the client wsi\n \t * and can be retrieved by user code with lws_get_opaque_user_data().\n \t * It's also provided with sequencer messages if the wsi is bound to\n-\t * an lws_sequencer_t.\n+\t * an lws_seq_t.\n \t */\n \n \t/* Add new things just above here ---^\ndiff --git a/include/libwebsockets/lws-sequencer.h b/include/libwebsockets/lws-sequencer.h\nindex db84325..b216a86 100644\n--- a/include/libwebsockets/lws-sequencer.h\n+++ b/include/libwebsockets/lws-sequencer.h\n@@ -56,7 +56,7 @@ typedef enum lws_seq_cb_return {\n \tLWSSEQ_RET_DESTROY\n } lws_seq_cb_return_t;\n \n-typedef struct lws_sequencer lws_sequencer_t; /* opaque */\n+typedef struct lws_sequencer lws_seq_t; /* opaque */\n \n /*\n * handler for this sequencer. Return 0 if OK else nonzero to destroy the\n@@ -83,7 +83,7 @@ typedef struct lws_seq_info {\n } lws_seq_info_t;\n \n /**\n- * lws_sequencer_create() - create and bind sequencer to a pt\n+ * lws_seq_create() - create and bind sequencer to a pt\n *\n * \u005cparam info:\tinformation about sequencer to create\n *\n@@ -97,26 +97,26 @@ typedef struct lws_seq_info {\n *\n * pt locking is used to protect the related data structures.\n */\n-LWS_VISIBLE LWS_EXTERN lws_sequencer_t *\n-lws_sequencer_create(lws_seq_info_t *info);\n+LWS_VISIBLE LWS_EXTERN lws_seq_t *\n+lws_seq_create(lws_seq_info_t *info);\n \n /**\n- * lws_sequencer_destroy() - destroy the sequencer\n+ * lws_seq_destroy() - destroy the sequencer\n *\n * \u005cparam seq: pointer to the the opaque sequencer pointer returned by\n- *\t lws_sequencer_create()\n+ *\t lws_seq_create()\n *\n * This proceeds to destroy the sequencer, calling LWSSEQ_DESTROYED and then\n * freeing the sequencer object itself. The pointed-to seq pointer will be\n * set to NULL.\n */\n LWS_VISIBLE LWS_EXTERN void\n-lws_sequencer_destroy(lws_sequencer_t **seq);\n+lws_seq_destroy(lws_seq_t **seq);\n \n /**\n- * lws_sequencer_queue_event() - queue an event on the given sequencer\n+ * lws_seq_queue_event() - queue an event on the given sequencer\n *\n- * \u005cparam seq: the opaque sequencer pointer returned by lws_sequencer_create()\n+ * \u005cparam seq: the opaque sequencer pointer returned by lws_seq_create()\n * \u005cparam e: the event index to queue\n * \u005cparam data: associated opaque (to lws) data to provide the callback\n * \u005cparam aux: second opaque data to provide the callback\n@@ -131,11 +131,11 @@ lws_sequencer_destroy(lws_sequencer_t **seq);\n * values here.\n */\n LWS_VISIBLE LWS_EXTERN int\n-lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data,\n+lws_seq_queue_event(lws_seq_t *seq, lws_seq_events_t e, void *data,\n \t\t\t void *aux);\n \n /**\n- * lws_sequencer_check_wsi() - check if wsi still extant\n+ * lws_seq_check_wsi() - check if wsi still extant\n *\n * \u005cparam seq: the sequencer interested in the wsi\n * \u005cparam wsi: the wsi we want to confirm hasn't closed yet\n@@ -151,15 +151,17 @@ lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data,\n * close message yet.\n */\n LWS_VISIBLE LWS_EXTERN int\n-lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi);\n+lws_seq_check_wsi(lws_seq_t *seq, struct lws *wsi);\n+\n+#define LWSSEQTO_NONE 0\n \n /**\n- * lws_sequencer_timeout() - set a timeout by which the sequence must have\n- *\t\t\t completed by a different event or inform the\n- *\t\t\t sequencer\n+ * lws_seq_timeout_us() - set a timeout by which the sequence must have\n+ *\t\t\t\tcompleted by a different event or inform the\n+ *\t\t\t\tsequencer\n *\n * \u005cparam seq: The sequencer to set the timeout on\n- * \u005cparam secs: How many seconds in the future to fire the timeout (0 \u003d disable)\n+ * \u005cparam us: How many us in the future to fire the timeout (0 \u003d disable)\n *\n * This api allows the sequencer to ask to be informed if it has not completed\n * or disabled its timeout after secs seconds. Lws will send a LWSSEQ_TIMED_OUT\n@@ -178,54 +180,54 @@ lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi);\n * react appropriately.\n */\n LWS_VISIBLE LWS_EXTERN int\n-lws_sequencer_timeout(lws_sequencer_t *seq, int secs);\n+lws_seq_timeout_us(lws_seq_t *seq, lws_usec_t us);\n \n /**\n- * lws_sequencer_from_user(): get the lws_sequencer_t pointer from the user ptr\n+ * lws_seq_from_user(): get the lws_seq_t pointer from the user ptr\n *\n- * \u005cparam u: the sequencer user allocation returned by lws_sequencer_create() or\n+ * \u005cparam u: the sequencer user allocation returned by lws_seq_create() or\n *\t provided in the sequencer callback\n *\n- * This gets the lws_sequencer_t * from the sequencer user allocation pointer.\n+ * This gets the lws_seq_t * from the sequencer user allocation pointer.\n * Actually these are allocated at the same time in one step, with the user\n- * allocation immediately after the lws_sequencer_t, so lws can compute where\n- * the lws_sequencer_t is from having the user allocation pointer. Since the\n- * size of the lws_sequencer_t is unknown to user code, this helper does it for\n+ * allocation immediately after the lws_seq_t, so lws can compute where\n+ * the lws_seq_t is from having the user allocation pointer. Since the\n+ * size of the lws_seq_t is unknown to user code, this helper does it for\n * you.\n */\n-LWS_VISIBLE LWS_EXTERN lws_sequencer_t *\n-lws_sequencer_from_user(void *u);\n+LWS_VISIBLE LWS_EXTERN lws_seq_t *\n+lws_seq_from_user(void *u);\n \n /**\n- * lws_sequencer_secs_since_creation(): elapsed seconds since sequencer created\n+ * lws_seq_secs_since_creation(): elapsed seconds since sequencer created\n *\n- * \u005cparam seq: pointer to the lws_sequencer_t\n+ * \u005cparam seq: pointer to the lws_seq_t\n *\n- * Returns the number of seconds elapsed since the lws_sequencer_t was\n+ * Returns the number of seconds elapsed since the lws_seq_t was\n * created. This is useful to calculate sequencer timeouts for the current\n * step considering a global sequencer lifetime limit.\n */\n LWS_VISIBLE LWS_EXTERN int\n-lws_sequencer_secs_since_creation(lws_sequencer_t *seq);\n+lws_seq_secs_since_creation(lws_seq_t *seq);\n \n /**\n- * lws_sequencer_name(): get the name of this sequencer\n+ * lws_seq_name(): get the name of this sequencer\n *\n- * \u005cparam seq: pointer to the lws_sequencer_t\n+ * \u005cparam seq: pointer to the lws_seq_t\n *\n * Returns the name given when the sequencer was created. This is useful to\n * annotate logging when then are multiple sequencers in play.\n */\n LWS_VISIBLE LWS_EXTERN const char *\n-lws_sequencer_name(lws_sequencer_t *seq);\n+lws_seq_name(lws_seq_t *seq);\n \n /**\n- * lws_sequencer_get_context(): get the lws_context sequencer was created on\n+ * lws_seq_get_context(): get the lws_context sequencer was created on\n *\n- * \u005cparam seq: pointer to the lws_sequencer_t\n+ * \u005cparam seq: pointer to the lws_seq_t\n *\n * Returns the lws_context. Saves you having to store it if you have a seq\n * pointer handy.\n */\n LWS_VISIBLE LWS_EXTERN struct lws_context *\n-lws_sequencer_get_context(lws_sequencer_t *seq);\n+lws_seq_get_context(lws_seq_t *seq);\ndiff --git a/lib/abstract/test-sequencer.c b/lib/abstract/test-sequencer.c\nindex 89eefb3..2872aef 100644\n--- a/lib/abstract/test-sequencer.c\n+++ b/lib/abstract/test-sequencer.c\n@@ -21,7 +21,7 @@\n *\n * A helper for running multiple unit tests against abstract protocols.\n *\n- * An lws_sequencer_t is used to base its actions in the event loop and manage\n+ * An lws_seq_t is used to base its actions in the event loop and manage\n * the sequencing of multiple tests. A new abstract connection is instantiated\n * for each test using te\n */\n@@ -35,7 +35,7 @@ struct lws_seq_test_sequencer {\n \n \tstruct lws_context\t\t*context;\n \tstruct lws_vhost\t\t*vhost;\n-\tlws_sequencer_t\t\t\t*unit_test_seq;\n+\tlws_seq_t\t\t\t*unit_test_seq;\n \n \t/* holds the per-test token for the unit-test transport to consume */\n \tlws_token_map_t\t\t\tuttt[4];\n@@ -88,7 +88,7 @@ unit_test_result_cb(const void *cb_user, int disposition)\n \t\treturn -1;\n \t}\n \n-\tlws_sequencer_queue_event(s-\u003eunit_test_seq, r, NULL, NULL);\n+\tlws_seq_queue_event(s-\u003eunit_test_seq, r, NULL, NULL);\n \n \t((struct lws_seq_test_sequencer *)s)-\u003einstance \u003d NULL;\n \n@@ -115,7 +115,7 @@ test_sequencer_cb(struct lws_sequencer *seq, void *user, int event, void *data,\n \tswitch ((int)event) {\n \tcase LWSSEQ_CREATED: /* our sequencer just got started */\n \t\tlwsl_notice(\u0022%s: %s: created\u005cn\u0022, __func__,\n-\t\t\t lws_sequencer_name(seq));\n+\t\t\t lws_seq_name(seq));\n \t\ts-\u003estate \u003d 0; /* first thing we'll do is the first url */\n \t\tgoto step;\n \n@@ -178,7 +178,7 @@ pass:\n \t\ts-\u003eargs.results[s-\u003estate] \u003d LPE_SUCCEEDED;\n \n done:\n-\t\tlws_sequencer_timeout(lws_sequencer_from_user(s), 0);\n+\t\tlws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE);\n \t\ts-\u003estate++;\n step:\n \t\tif (!s-\u003eargs.tests[s-\u003estate].name) {\n@@ -233,7 +233,7 @@ int\n lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args)\n {\n \tstruct lws_seq_test_sequencer *s;\n-\tlws_sequencer_t *seq;\n+\tlws_seq_t *seq;\n \tlws_seq_info_t i;\n \n \tmemset(\u0026i, 0, sizeof(i));\n@@ -247,7 +247,7 @@ lws_abs_unit_test_sequencer(const lws_test_sequencer_args_t *args)\n \t * Create a sequencer in the event loop to manage the tests\n \t */\n \n-\tseq \u003d lws_sequencer_create(\u0026i);\n+\tseq \u003d lws_seq_create(\u0026i);\n \tif (!seq) {\n \t\tlwsl_err(\u0022%s: unable to create sequencer\u005cn\u0022, __func__);\n \t\treturn 1;\ndiff --git a/lib/abstract/transports/raw-skt.c b/lib/abstract/transports/raw-skt.c\nindex 683efad..74f08ab 100644\n--- a/lib/abstract/transports/raw-skt.c\n+++ b/lib/abstract/transports/raw-skt.c\n@@ -97,7 +97,7 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,\n \t\t\t * our lifecycle events\n \t\t\t */\n \n-\t\t\tlws_sequencer_queue_event(wsi-\u003eseq, LWSSEQ_WSI_CONNECTED,\n+\t\t\tlws_seq_queue_event(wsi-\u003eseq, LWSSEQ_WSI_CONNECTED,\n \t\t\t\t\t\t wsi, NULL);\n break;\n \n@@ -112,7 +112,7 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,\n \t\t\t * our lifecycle events\n \t\t\t */\n \n-\t\t\tlws_sequencer_queue_event(wsi-\u003eseq, LWSSEQ_WSI_CONN_FAIL,\n+\t\t\tlws_seq_queue_event(wsi-\u003eseq, LWSSEQ_WSI_CONN_FAIL,\n \t\t\t\t\t wsi, NULL);\n \n \t\tgoto close_path;\n@@ -128,7 +128,7 @@ callback_abs_client_raw_skt(struct lws *wsi, enum lws_callback_reasons reason,\n \t\t\t * our lifecycle events\n \t\t\t */\n \n-\t\t\tlws_sequencer_queue_event(wsi-\u003eseq, LWSSEQ_WSI_CONN_CLOSE,\n+\t\t\tlws_seq_queue_event(wsi-\u003eseq, LWSSEQ_WSI_CONN_CLOSE,\n \t\t\t\t\t wsi, NULL);\n \n close_path:\ndiff --git a/lib/abstract/transports/unit-test.c b/lib/abstract/transports/unit-test.c\nindex 3be03ed..c891861 100644\n--- a/lib/abstract/transports/unit-test.c\n+++ b/lib/abstract/transports/unit-test.c\n@@ -33,7 +33,7 @@ typedef struct lws_abstxp_unit_test_priv {\n \tchar\t\t\t\t\tnote[128];\n \tstruct lws_abs\t\t\t\t*abs;\n \n-\tlws_sequencer_t\t\t\t\t*seq;\n+\tlws_seq_t\t\t\t\t*seq;\n \tlws_unit_test_t\t\t\t\t*current_test;\n \tlws_unit_test_packet_t\t\t\t*expect;\n \tlws_unit_test_packet_test_cb\t\tresult_cb;\n@@ -78,7 +78,7 @@ lws_unit_test_packet_dispose(abs_unit_test_priv_t *priv,\n \n \tpriv-\u003edisposition \u003d disp;\n \n-\tlws_sequencer_queue_event(priv-\u003eseq, UTSEQ_MSG_DISPOSITION_KNOWN,\n+\tlws_seq_queue_event(priv-\u003eseq, UTSEQ_MSG_DISPOSITION_KNOWN,\n \t\t\t\t NULL, NULL);\n \n \treturn disp;\n@@ -135,10 +135,10 @@ unit_test_sequencer_cb(struct lws_sequencer *seq, void *user, int event,\n \tswitch ((int)event) {\n \tcase LWSSEQ_CREATED: /* our sequencer just got started */\n \t\tlwsl_notice(\u0022%s: %s: created\u005cn\u0022, __func__,\n-\t\t\t lws_sequencer_name(seq));\n+\t\t\t lws_seq_name(seq));\n \t\tif (s-\u003eai-\u003eat-\u003eclient_conn(s-\u003eai)) {\n \t\t\tlwsl_notice(\u0022%s: %s: abstract client conn failed\u005cn\u0022,\n-\t\t\t\t\t__func__, lws_sequencer_name(seq));\n+\t\t\t\t\t__func__, lws_seq_name(seq));\n \n \t\t\treturn LWSSEQ_RET_DESTROY;\n \t\t}\n@@ -257,7 +257,8 @@ ph:\n \t\tgoto done;\n \n done:\n-\t\tlws_sequencer_timeout(lws_sequencer_from_user(s), 0);\n+\t\tlws_seq_timeout_us(lws_seq_from_user(s),\n+\t\t\t\t\t LWSSEQTO_NONE);\n \t\tpriv-\u003eexpect++;\n \t\tif (!priv-\u003eexpect-\u003ebuffer) {\n \t\t\t/* the sequence has completed */\n@@ -281,7 +282,7 @@ lws_atcut_close(lws_abs_transport_inst_t *ati)\n \n \tlwsl_notice(\u0022%s\u005cn\u0022, __func__);\n \n-\tlws_sequencer_queue_event(priv-\u003eseq, UTSEQ_MSG_CLOSING, NULL, NULL);\n+\tlws_seq_queue_event(priv-\u003eseq, UTSEQ_MSG_CLOSING, NULL, NULL);\n \n \treturn 0;\n }\n@@ -333,7 +334,7 @@ lws_atcut_tx(lws_abs_transport_inst_t *ati, uint8_t *buf, size_t len)\n \n \tpriv-\u003eexpect++;\n \n-\tlws_sequencer_queue_event(priv-\u003eseq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL);\n+\tlws_seq_queue_event(priv-\u003eseq, UTSEQ_MSG_POST_TX_KICK, NULL, NULL);\n \n \treturn 0;\n }\n@@ -378,12 +379,13 @@ lws_atcut_client_conn(const lws_abs_t *abs)\n \tpriv-\u003edisposition \u003d LPE_CONTINUE;\n \tpriv-\u003enote[0] \u003d '\u005c0';\n \n-\tlws_sequencer_timeout(priv-\u003eseq, priv-\u003ecurrent_test-\u003emax_secs);\n+\tlws_seq_timeout_us(priv-\u003eseq, priv-\u003ecurrent_test-\u003emax_secs *\n+\t\t\t\t\t LWS_US_PER_SEC);\n \n \tlwsl_notice(\u0022%s: %s: test '%s': start\u005cn\u0022, __func__, abs-\u003eap-\u003ename,\n \t\t priv-\u003ecurrent_test-\u003ename);\n \n-\tlws_sequencer_queue_event(priv-\u003eseq, UTSEQ_MSG_CONNECTING, NULL, NULL);\n+\tlws_seq_queue_event(priv-\u003eseq, UTSEQ_MSG_CONNECTING, NULL, NULL);\n \n \treturn 0;\n }\n@@ -402,7 +404,7 @@ lws_atcut_ask_for_writeable(lws_abs_transport_inst_t *ati)\n \t * until we have returned to the event loop, just like a real\n \t * callback_on_writable()\n \t */\n-\tlws_sequencer_queue_event(priv-\u003eseq, UTSEQ_MSG_WRITEABLE, NULL, NULL);\n+\tlws_seq_queue_event(priv-\u003eseq, UTSEQ_MSG_WRITEABLE, NULL, NULL);\n \n \treturn 0;\n }\n@@ -415,7 +417,7 @@ static int\n lws_atcut_create(lws_abs_t *ai)\n {\n \tabs_unit_test_priv_t *priv;\n-\tlws_sequencer_t *seq;\n+\tlws_seq_t *seq;\n \tlws_seq_info_t i;\n \tseq_priv_t *s;\n \n@@ -430,7 +432,7 @@ lws_atcut_create(lws_abs_t *ai)\n \t * Create the sequencer for the steps in a single unit test\n \t */\n \n-\tseq \u003d lws_sequencer_create(\u0026i);\n+\tseq \u003d lws_seq_create(\u0026i);\n \tif (!seq) {\n \t\tlwsl_err(\u0022%s: unable to create sequencer\u005cn\u0022, __func__);\n \ndiff --git a/lib/core-net/private.h b/lib/core-net/private.h\nindex 123e3a0..d56e3bb 100644\n--- a/lib/core-net/private.h\n+++ b/lib/core-net/private.h\n@@ -288,6 +288,8 @@ struct lws_context_per_thread {\n \tstruct lws_pt_tls tls;\n #endif\n \n+\tlws_usec_t last_heartbeat;\n+\n \tstruct lws_pollfd *fds;\n \tvolatile struct lws_foreign_thread_pollfd * volatile foreign_pfd_list;\n #ifdef _WIN32\n@@ -512,7 +514,7 @@ struct lws {\n \tconst struct lws_protocols *protocol;\n \tstruct lws_dll same_vh_protocol;\n \n-\tlws_sequencer_t *seq;\t/* associated sequencer if any */\n+\tlws_seq_t *seq;\t/* associated sequencer if any */\n \n \tstruct lws_dll dll_timeout;\n \tstruct lws_dll dll_hrtimer;\n@@ -921,8 +923,8 @@ lws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len);\n LWS_EXTERN void\n lws_remove_from_timeout_list(struct lws *wsi);\n \n-LWS_EXTERN int\n-lws_sequencer_timeout_check(struct lws_context_per_thread *pt, time_t now);\n+LWS_EXTERN lws_usec_t\n+__lws_seq_timeout_check(struct lws_context_per_thread *pt, lws_usec_t usnow);\n \n LWS_EXTERN struct lws * LWS_WARN_UNUSED_RESULT\n lws_client_connect_2(struct lws *wsi);\n@@ -1040,7 +1042,7 @@ int\n lws_pt_do_pending_sequencer_events(struct lws_context_per_thread *pt);\n \n void\n-lws_sequencer_destroy_all_on_pt(struct lws_context_per_thread *pt);\n+lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt);\n \n LWS_EXTERN int\n lws_broadcast(struct lws_context *context, int reason, void *in, size_t len);\n@@ -1094,7 +1096,7 @@ void\n __lws_remove_from_timeout_list(struct lws *wsi);\n \n lws_usec_t\n-__lws_hrtimer_service(struct lws_context_per_thread *pt);\n+__lws_hrtimer_service(struct lws_context_per_thread *pt, lws_usec_t t);\n \n \n int\ndiff --git a/lib/core-net/sequencer.c b/lib/core-net/sequencer.c\nindex 1312d50..06d28f7 100644\n--- a/lib/core-net/sequencer.c\n+++ b/lib/core-net/sequencer.c\n@@ -46,19 +46,19 @@ typedef struct lws_sequencer {\n \tconst char\t\t\t*name;\n \tconst lws_retry_bo_t\t\t*retry;\n \n-\ttime_t\t\t\t\ttime_created;\n-\ttime_t\t\t\t\ttimeout; /* 0 or time we timeout */\n+\tlws_usec_t\t\t\ttime_created;\n+\tlws_usec_t\t\t\ttimeout; /* 0 or time we timeout */\n \n \tchar\t\t\t\tgoing_down;\n-} lws_sequencer_t;\n+} lws_seq_t;\n \n #define QUEUE_SANITY_LIMIT 10\n \n-lws_sequencer_t *\n-lws_sequencer_create(lws_seq_info_t *i)\n+lws_seq_t *\n+lws_seq_create(lws_seq_info_t *i)\n {\n \tstruct lws_context_per_thread *pt \u003d \u0026i-\u003econtext-\u003ept[i-\u003etsi];\n-\tlws_sequencer_t *seq \u003d lws_zalloc(sizeof(*seq) + i-\u003euser_size, __func__);\n+\tlws_seq_t *seq \u003d lws_zalloc(sizeof(*seq) + i-\u003euser_size, __func__);\n \n \tif (!seq)\n \t\treturn NULL;\n@@ -78,11 +78,11 @@ lws_sequencer_create(lws_seq_info_t *i)\n \n \tlws_pt_unlock(pt); /* } pt ------------------------------------------ */\n \n-\ttime(\u0026seq-\u003etime_created);\n+\tseq-\u003etime_created \u003d lws_now_usecs();\n \n \t/* try to queue the creation cb */\n \n-\tif (lws_sequencer_queue_event(seq, LWSSEQ_CREATED, NULL, NULL)) {\n+\tif (lws_seq_queue_event(seq, LWSSEQ_CREATED, NULL, NULL)) {\n \t\tlws_dll2_remove(\u0026seq-\u003eseq_list);\n \t\tlws_free(seq);\n \n@@ -105,9 +105,9 @@ seq_ev_destroy(struct lws_dll2 *d, void *user)\n }\n \n void\n-lws_sequencer_destroy(lws_sequencer_t **pseq)\n+lws_seq_destroy(lws_seq_t **pseq)\n {\n-\tlws_sequencer_t *seq \u003d *pseq;\n+\tlws_seq_t *seq \u003d *pseq;\n \n \t/* defeat another thread racing to add events while we are destroying */\n \tseq-\u003egoing_down \u003d 1;\n@@ -129,20 +129,20 @@ lws_sequencer_destroy(lws_sequencer_t **pseq)\n }\n \n void\n-lws_sequencer_destroy_all_on_pt(struct lws_context_per_thread *pt)\n+lws_seq_destroy_all_on_pt(struct lws_context_per_thread *pt)\n {\n \tlws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,\n \t\t\t\t pt-\u003eseq_owner.head) {\n-\t\tlws_sequencer_t *s \u003d lws_container_of(p, lws_sequencer_t,\n+\t\tlws_seq_t *s \u003d lws_container_of(p, lws_seq_t,\n \t\t\t\t\t\t seq_list);\n \n-\t\tlws_sequencer_destroy(\u0026s);\n+\t\tlws_seq_destroy(\u0026s);\n \n \t} lws_end_foreach_dll_safe(p, tp);\n }\n \n int\n-lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data,\n+lws_seq_queue_event(lws_seq_t *seq, lws_seq_events_t e, void *data,\n \t\t\t void *aux)\n {\n \tlws_seq_event_t *seqe;\n@@ -191,7 +191,7 @@ lws_sequencer_queue_event(lws_sequencer_t *seq, lws_seq_events_t e, void *data,\n */\n \n int\n-lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi)\n+lws_seq_check_wsi(lws_seq_t *seq, struct lws *wsi)\n {\n \tlws_seq_event_t *seqe;\n \tstruct lws_dll2 *dh;\n@@ -220,9 +220,9 @@ lws_sequencer_check_wsi(lws_sequencer_t *seq, struct lws *wsi)\n */\n \n static int\n-lws_sequencer_next_event(struct lws_dll2 *d, void *user)\n+lws_seq_next_event(struct lws_dll2 *d, void *user)\n {\n-\tlws_sequencer_t *seq \u003d lws_container_of(d, lws_sequencer_t,\n+\tlws_seq_t *seq \u003d lws_container_of(d, lws_seq_t,\n \t\t\t\t\t\tseq_pend_list);\n \tlws_seq_event_t *seqe;\n \tstruct lws_dll2 *dh;\n@@ -258,7 +258,7 @@ lws_sequencer_next_event(struct lws_dll2 *d, void *user)\n \tif (n) {\n \t\tlwsl_info(\u0022%s: destroying seq '%s' by request\u005cn\u0022, __func__,\n \t\t\t\tseq-\u003ename);\n-\t\tlws_sequencer_destroy(\u0026seq);\n+\t\tlws_seq_destroy(\u0026seq);\n \n \t\treturn LWSSEQ_RET_DESTROY;\n \t}\n@@ -278,25 +278,24 @@ lws_pt_do_pending_sequencer_events(struct lws_context_per_thread *pt)\n \t\treturn 0;\n \n \treturn lws_dll2_foreach_safe(\u0026pt-\u003eseq_pend_owner, NULL,\n-\t\t\t\t lws_sequencer_next_event);\n+\t\t\t\t lws_seq_next_event);\n }\n \n /* set secs to zero to remove timeout */\n \n int\n-lws_sequencer_timeout(lws_sequencer_t *seq, int secs)\n+lws_seq_timeout_us(lws_seq_t *seq, lws_usec_t us)\n {\n \tlws_dll2_remove(\u0026seq-\u003eseq_to_list);\n \n-\tif (!secs) {\n+\tif (!us) {\n \t\t/* we are clearing the timeout */\n \t\tseq-\u003etimeout \u003d 0;\n \n \t\treturn 0;\n \t}\n \n-\ttime(\u0026seq-\u003etimeout);\n-\tseq-\u003etimeout +\u003d secs;\n+\tseq-\u003etimeout \u003d lws_now_usecs() + us;\n \n \t/*\n \t * we sort the pt's list of sequencers with pending timeouts, so it's\n@@ -305,14 +304,12 @@ lws_sequencer_timeout(lws_sequencer_t *seq, int secs)\n \n \tlws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,\n \t\t\t\t seq-\u003ept-\u003eseq_to_owner.head) {\n-\t\tlws_sequencer_t *s \u003d lws_container_of(p, lws_sequencer_t,\n-\t\t\t\t\t\t seq_to_list);\n+\t\tlws_seq_t *s \u003d lws_container_of(p, lws_seq_t, seq_to_list);\n \n \t\tassert(s-\u003etimeout); /* shouldn't be on the list otherwise */\n \t\tif (s-\u003etimeout \u003e\u003d seq-\u003etimeout) {\n \t\t\t/* drop us in before this guy */\n-\t\t\tlws_dll2_add_before(\u0026seq-\u003eseq_to_list,\n-\t\t\t\t\t \u0026s-\u003eseq_to_list);\n+\t\t\tlws_dll2_add_before(\u0026seq-\u003eseq_to_list, \u0026s-\u003eseq_to_list);\n \n \t\t\treturn 0;\n \t\t}\n@@ -330,61 +327,70 @@ lws_sequencer_timeout(lws_sequencer_t *seq, int secs)\n \n /*\n * nonpublic helper to check for and handle sequencer timeouts for a whole pt\n+ * returns either 0 or number of us until next event (which cannot be 0 or we\n+ * would have serviced it)\n */\n \n-int\n-lws_sequencer_timeout_check(struct lws_context_per_thread *pt, time_t now)\n+lws_usec_t\n+__lws_seq_timeout_check(struct lws_context_per_thread *pt, lws_usec_t usnow)\n {\n+\tlws_usec_t future_us \u003d 0;\n+\n \tlws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,\n \t\t\t\t pt-\u003eseq_to_owner.head) {\n-\t\tlws_sequencer_t *s \u003d lws_container_of(p, lws_sequencer_t,\n-\t\t\t\t\t\t seq_to_list);\n+\t\tlws_seq_t *s \u003d lws_container_of(p, lws_seq_t, seq_to_list);\n \n \t\tassert(s-\u003etimeout); /* shouldn't be on the list otherwise */\n-\t\tif (s-\u003etimeout \u003c\u003d now) {\n+\t\tif (s-\u003etimeout \u003c\u003d usnow) {\n \t\t\t/* seq has timed out... remove him from timeout list */\n-\t\t\tlws_sequencer_timeout(s, 0);\n+\t\t\tlws_seq_timeout_us(s, LWSSEQTO_NONE);\n \t\t\t/* queue the message to inform the sequencer */\n-\t\t\tlws_sequencer_queue_event(s, LWSSEQ_TIMED_OUT,\n-\t\t\t\t\t\t NULL, NULL);\n-\t\t} else\n+\t\t\tlws_seq_queue_event(s, LWSSEQ_TIMED_OUT, NULL, NULL);\n+\t\t} else {\n \t\t\t/*\n \t\t\t * No need to look further if we met one later than now:\n \t\t\t * the list is sorted in ascending time order\n \t\t\t */\n-\t\t\treturn 0;\n+\t\t\tfuture_us \u003d usnow - s-\u003etimeout;\n+\n+\t\t\tbreak;\n+\t\t}\n \n \t} lws_end_foreach_dll_safe(p, tp);\n \n+\tif (usnow - pt-\u003elast_heartbeat\u003c LWS_US_PER_SEC)\n+\t\treturn future_us;\n+\n+\tpt-\u003elast_heartbeat \u003d usnow;\n+\n \t/* send every sequencer a heartbeat message... it can ignore it */\n \n \tlws_start_foreach_dll_safe(struct lws_dll2 *, p, tp,\n \t\t\t\t pt-\u003eseq_owner.head) {\n-\t\tlws_sequencer_t *s \u003d lws_container_of(p, lws_sequencer_t,\n-\t\t\t\t\t\t seq_list);\n+\t\tlws_seq_t *s \u003d lws_container_of(p, lws_seq_t, seq_list);\n \n \t\t/* queue the message to inform the sequencer */\n-\t\tlws_sequencer_queue_event(s, LWSSEQ_HEARTBEAT, NULL, NULL);\n+\t\tlws_seq_queue_event(s, LWSSEQ_HEARTBEAT, NULL, NULL);\n \n \t} lws_end_foreach_dll_safe(p, tp);\n \n-\treturn 0;\n+\treturn future_us;\n }\n \n-lws_sequencer_t *\n-lws_sequencer_from_user(void *u)\n+lws_seq_t *\n+lws_seq_from_user(void *u)\n {\n-\treturn \u0026((lws_sequencer_t *)u)[-1];\n+\treturn \u0026((lws_seq_t *)u)[-1];\n }\n \n const char *\n-lws_sequencer_name(lws_sequencer_t *seq)\n+lws_seq_name(lws_seq_t *seq)\n {\n \treturn seq-\u003ename;\n }\n \n int\n-lws_sequencer_secs_since_creation(lws_sequencer_t *seq)\n+lws_seq_secs_since_creation(lws_seq_t *seq)\n {\n \ttime_t now;\n \n@@ -394,7 +400,7 @@ lws_sequencer_secs_since_creation(lws_sequencer_t *seq)\n }\n \n struct lws_context *\n-lws_sequencer_get_context(lws_sequencer_t *seq)\n+lws_seq_get_context(lws_seq_t *seq)\n {\n \treturn seq-\u003ept-\u003econtext;\n }\ndiff --git a/lib/core-net/service.c b/lib/core-net/service.c\nindex a14a303..a529421 100644\n--- a/lib/core-net/service.c\n+++ b/lib/core-net/service.c\n@@ -603,6 +603,7 @@ lws_service_periodic_checks(struct lws_context *context,\n \tlws_sockfd_type our_fd \u003d 0, tmp_fd;\n \tstruct lws *wsi;\n \tint timed_out \u003d 0;\n+\tlws_usec_t usnow;\n \ttime_t now;\n #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)\n \tstruct allocated_headers *ah;\n@@ -615,14 +616,15 @@ lws_service_periodic_checks(struct lws_context *context,\n \t\t\treturn -1;\n \t\t}\n \n-\ttime(\u0026now);\n+\tusnow \u003d lws_now_usecs();\n+\tnow \u003d usnow / LWS_US_PER_SEC;\n \n \t/*\n \t * handle case that system time was uninitialized when lws started\n \t * at boot, and got initialized a little later\n \t */\n \tif (context-\u003etime_up \u003c 1464083026 \u0026\u0026 now \u003e 1464083026)\n-\t\tcontext-\u003etime_up \u003d now;\n+\t\tcontext-\u003etime_up \u003d now / LWS_US_PER_SEC;\n \n \tif (context-\u003elast_timeout_check_s \u0026\u0026\n \t now - context-\u003elast_timeout_check_s \u003e 100) {\n@@ -648,7 +650,7 @@ lws_service_periodic_checks(struct lws_context *context,\n \t\tcontext-\u003elast_timeout_check_s \u003d now - 1;\n \t}\n \n-\tlws_sequencer_timeout_check(pt, now);\n+\t__lws_seq_timeout_check(pt, usnow);\n \tlws_pt_do_pending_sequencer_events(pt);\n \n \tif (!lws_compare_time_t(context, context-\u003elast_timeout_check_s, now))\n@@ -1086,7 +1088,7 @@ handled:\n \tlws_service_periodic_checks(context, pollfd, tsi);\n \n \tlws_pt_lock(pt, __func__);\n-\t__lws_hrtimer_service(pt);\n+\t__lws_hrtimer_service(pt, lws_now_usecs());\n \tlws_pt_unlock(pt);\n \n \treturn 0;\ndiff --git a/lib/core-net/wsi-timeout.c b/lib/core-net/wsi-timeout.c\nindex 6e2d10b..5702bad 100644\n--- a/lib/core-net/wsi-timeout.c\n+++ b/lib/core-net/wsi-timeout.c\n@@ -82,16 +82,12 @@ lws_set_timer_usecs(struct lws *wsi, lws_usec_t usecs)\n \t__lws_set_timer_usecs(wsi, usecs);\n }\n \n+/* return 0 if nothing pending, or the number of us before the next event */\n \n lws_usec_t\n-__lws_hrtimer_service(struct lws_context_per_thread *pt)\n+__lws_hrtimer_service(struct lws_context_per_thread *pt, lws_usec_t t)\n {\n-\tstruct timeval now;\n \tstruct lws *wsi;\n-\tlws_usec_t t;\n-\n-\tgettimeofday(\u0026now, NULL);\n-\tt \u003d (now.tv_sec * 1000000ll) + now.tv_usec;\n \n \tlws_start_foreach_dll_safe(struct lws_dll *, d, d1,\n \t\t\t\t pt-\u003edll_hrtimer_head.next) {\n@@ -118,18 +114,16 @@ __lws_hrtimer_service(struct lws_context_per_thread *pt)\n \t/* return an estimate how many us until next timer hit */\n \n \tif (!pt-\u003edll_hrtimer_head.next)\n-\t\treturn LWS_HRTIMER_NOWAIT;\n+\t\treturn 0; /* there is nothing pending */\n \n \twsi \u003d lws_container_of(pt-\u003edll_hrtimer_head.next, struct lws,\n \t\t\t dll_hrtimer);\n \n-\tgettimeofday(\u0026now, NULL);\n-\tt \u003d (now.tv_sec * 1000000ll) + now.tv_usec;\n-\n-\tif (wsi-\u003epending_timer \u003c t)\n-\t\treturn 0;\n+\tt \u003d lws_now_usecs();\n+\tif (wsi-\u003epending_timer \u003c\u003d t) /* in the past */\n+\t\treturn 1;\n \n-\treturn wsi-\u003epending_timer - t;\n+\treturn wsi-\u003epending_timer - t; /* at least 1 */\n }\n \n void\ndiff --git a/lib/core/context.c b/lib/core/context.c\nindex 31df3e6..0ed77b5 100644\n--- a/lib/core/context.c\n+++ b/lib/core/context.c\n@@ -552,7 +552,7 @@ lws_context_destroy3(struct lws_context *context)\n \tfor (n \u003d 0; n \u003c context-\u003ecount_threads; n++) {\n \t\tstruct lws_context_per_thread *pt \u003d \u0026context-\u003ept[n];\n \n-\t\tlws_sequencer_destroy_all_on_pt(pt);\n+\t\tlws_seq_destroy_all_on_pt(pt);\n \n \t\tif (context-\u003eevent_loop_ops-\u003edestroy_pt)\n \t\t\tcontext-\u003eevent_loop_ops-\u003edestroy_pt(context, n);\ndiff --git a/lib/core/private.h b/lib/core/private.h\nindex a920066..f0d1c28 100644\n--- a/lib/core/private.h\n+++ b/lib/core/private.h\n@@ -241,8 +241,6 @@ lws_mutex_refcount_unlock(struct lws_mutex_refcount *mr);\n #include \u0022core-net/private.h\u0022\n #endif\n \n-#define LWS_HRTIMER_NOWAIT (0x7fffffffffffffffll)\n-\n struct lws_deferred_free\n {\n \tstruct lws_deferred_free *next;\ndiff --git a/lib/event-libs/common.c b/lib/event-libs/common.c\nnew file mode 100644\nindex 0000000..cd90253\n--- /dev/null\n+++ b/lib/event-libs/common.c\n@@ -0,0 +1,43 @@\n+/*\n+ * libwebsockets - small server side websockets and web server implementation\n+ *\n+ * Copyright (C) 2010-2018 Andy Green \u003candy@warmcat.com\u003e\n+ *\n+ * This library is free software; you can redistribute it and/or\n+ * modify it under the terms of the GNU Lesser General Public\n+ * License as published by the Free Software Foundation:\n+ * version 2.1 of the License.\n+ *\n+ * This library is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n+ * Lesser General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU Lesser General Public\n+ * License along with this library; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,\n+ * MA 02110-1301 USA\n+ */\n+\n+#include \u0022core/private.h\u0022\n+\n+lws_usec_t\n+__lws_event_service_get_earliest_wake(struct lws_context_per_thread *pt,\n+\t\t\t\t lws_usec_t usnow)\n+{\n+\tlws_usec_t t, us \u003d 0;\n+\tchar seen \u003d 0;\n+\n+\tt \u003d __lws_hrtimer_service(pt, usnow);\n+\tif (t \u0026\u0026 (!seen || t \u003c us)) {\n+\t\tus \u003d t;\n+\t\tseen \u003d 1;\n+\t}\n+\tt \u003d __lws_seq_timeout_check(pt, usnow);\n+\tif (t \u0026\u0026 (!seen || t \u003c us)) {\n+\t\tus \u003d t;\n+\t\tseen \u003d 1;\n+\t}\n+\n+\treturn us;\n+}\ndiff --git a/lib/event-libs/libev/libev.c b/lib/event-libs/libev/libev.c\nindex 26f41a6..0f02f75 100644\n--- a/lib/event-libs/libev/libev.c\n+++ b/lib/event-libs/libev/libev.c\n@@ -29,8 +29,8 @@ lws_ev_hrtimer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents)\n \tlws_usec_t us;\n \n \tlws_pt_lock(pt, __func__);\n-\tus \u003d __lws_hrtimer_service(pt);\n-\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n+\tus \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\tif (us) {\n \t\tev_timer_set(\u0026pt-\u003eev.hrtimer, ((float)us) / 1000000.0, 0);\n \t\tev_timer_start(pt-\u003eev.io_loop, \u0026pt-\u003eev.hrtimer);\n \t}\n@@ -61,8 +61,8 @@ lws_ev_idle_cb(struct ev_loop *loop, struct ev_idle *handle, int revents)\n \t/* account for hrtimer */\n \n \tlws_pt_lock(pt, __func__);\n-\tus \u003d __lws_hrtimer_service(pt);\n-\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n+\tus \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\tif (us) {\n \t\tev_timer_set(\u0026pt-\u003eev.hrtimer, ((float)us) / 1000000.0, 0);\n \t\tev_timer_start(pt-\u003eev.io_loop, \u0026pt-\u003eev.hrtimer);\n \t}\ndiff --git a/lib/event-libs/libevent/libevent.c b/lib/event-libs/libevent/libevent.c\nindex e1f48a4..764eb6f 100644\n--- a/lib/event-libs/libevent/libevent.c\n+++ b/lib/event-libs/libevent/libevent.c\n@@ -29,10 +29,10 @@ lws_event_hrtimer_cb(int fd, short event, void *p)\n \tlws_usec_t us;\n \n \tlws_pt_lock(pt, __func__);\n-\tus \u003d __lws_hrtimer_service(pt);\n-\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n-\t\ttv.tv_sec \u003d us / 1000000;\n-\t\ttv.tv_usec \u003d us - (tv.tv_sec * 1000000);\n+\tus \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\tif (us) {\n+\t\ttv.tv_sec \u003d us / LWS_US_PER_SEC;\n+\t\ttv.tv_usec \u003d us - (tv.tv_sec * LWS_US_PER_SEC);\n \t\tevtimer_add(pt-\u003eevent.hrtimer, \u0026tv);\n \t}\n \tlws_pt_unlock(pt);\n@@ -70,10 +70,10 @@ lws_event_idle_timer_cb(int fd, short event, void *p)\n \t/* account for hrtimer */\n \n \tlws_pt_lock(pt, __func__);\n-\tus \u003d __lws_hrtimer_service(pt);\n-\tif (us !\u003d LWS_HRTIMER_NOWAIT) {\n-\t\ttv.tv_sec \u003d us / 1000000;\n-\t\ttv.tv_usec \u003d us - (tv.tv_sec * 1000000);\n+\tus \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\tif (us) {\n+\t\ttv.tv_sec \u003d us / LWS_US_PER_SEC;\n+\t\ttv.tv_usec \u003d us - (tv.tv_sec * LWS_US_PER_SEC);\n \t\tevtimer_add(pt-\u003eevent.hrtimer, \u0026tv);\n \t}\n \tlws_pt_unlock(pt);\ndiff --git a/lib/event-libs/libuv/libuv.c b/lib/event-libs/libuv/libuv.c\nindex 3650eee..89a9c1c 100644\n--- a/lib/event-libs/libuv/libuv.c\n+++ b/lib/event-libs/libuv/libuv.c\n@@ -33,9 +33,10 @@ lws_uv_hrtimer_cb(uv_timer_t *timer\n \tlws_usec_t us;\n \n \tlws_pt_lock(pt, __func__);\n-\tus \u003d __lws_hrtimer_service(pt);\n-\tif (us !\u003d LWS_HRTIMER_NOWAIT)\n-\t\tuv_timer_start(\u0026pt-\u003euv.hrtimer, lws_uv_hrtimer_cb, us / 1000, 0);\n+\tus \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\tif (us)\n+\t\tuv_timer_start(\u0026pt-\u003euv.hrtimer, lws_uv_hrtimer_cb,\n+\t\t\t LWS_US_TO_MS(us), 0);\n \tlws_pt_unlock(pt);\n }\n \n@@ -67,9 +68,10 @@ lws_uv_idle(uv_idle_t *handle\n \t/* account for hrtimer */\n \n \tlws_pt_lock(pt, __func__);\n-\tus \u003d __lws_hrtimer_service(pt);\n-\tif (us !\u003d LWS_HRTIMER_NOWAIT)\n-\t\tuv_timer_start(\u0026pt-\u003euv.hrtimer, lws_uv_hrtimer_cb, us / 1000, 0);\n+\tus \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\tif (us)\n+\t\tuv_timer_start(\u0026pt-\u003euv.hrtimer, lws_uv_hrtimer_cb,\n+\t\t\t LWS_US_TO_MS(us), 0);\n \tlws_pt_unlock(pt);\n \n \t/* there is nobody who needs service forcing, shut down idle */\ndiff --git a/lib/event-libs/private.h b/lib/event-libs/private.h\nindex 58bca94..da0f9c4 100644\n--- a/lib/event-libs/private.h\n+++ b/lib/event-libs/private.h\n@@ -54,6 +54,12 @@ struct lws_event_loop_ops {\n \tunsigned int periodic_events_available:1;\n };\n \n+struct lws_context_per_thread;\n+\n+lws_usec_t\n+__lws_event_service_get_earliest_wake(struct lws_context_per_thread *pt,\n+\t\t\t\t lws_usec_t usnow);\n+\n /* bring in event libs private declarations */\n \n #if defined(LWS_WITH_POLL)\ndiff --git a/lib/plat/esp32/esp32-service.c b/lib/plat/esp32/esp32-service.c\nindex 5ca16a3..056b9d0 100644\n--- a/lib/plat/esp32/esp32-service.c\n+++ b/lib/plat/esp32/esp32-service.c\n@@ -38,6 +38,7 @@ lws_plat_service(struct lws_context *context, int timeout_ms)\n LWS_EXTERN int\n _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n {\n+\tlws_usec_t timeout_us \u003d timeout_ms * LWS_US_PER_MS;\n \tstruct lws_context_per_thread *pt;\n \tint n \u003d -1, m, c;\n \n@@ -101,24 +102,28 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \t\t/* still somebody left who wants forced service? */\n \t\tif (!lws_service_adjust_timeout(context, 1, pt-\u003etid))\n \t\t\t/* yes... come back again quickly */\n-\t\t\ttimeout_ms \u003d 0;\n+\t\t\ttimeout_us \u003d 0;\n \t}\n \n-\tif (timeout_ms) {\n+\tif (timeout_us) {\n+\t\tlws_usec_t t, us \u003d lws_now_usecs();\n \t\tlws_pt_lock(pt, __func__);\n-\t\t/* don't stay in poll wait longer than next hr timeout */\n-\t\tlws_usec_t t \u003d __lws_hrtimer_service(pt);\n-\n-\t\tif ((lws_usec_t)timeout_ms * 1000 \u003e t)\n-\t\t\ttimeout_ms \u003d t / 1000;\n+\t\t/* don't stay in poll wait longer than next hr timeout... */\n+\t\tt \u003d __lws_hrtimer_service(pt, us);\n+\t\tif (t \u0026\u0026 timeout_us \u003e t)\n+\t\t\ttimeout_us \u003d t;\n+\t\t/* ... or next sequencer timeout */\n+\t\tt \u003d __lws_seq_timeout_check(pt, us);\n+\t\tif (t \u0026\u0026 timeout_us \u003e t)\n+\t\t\ttimeout_us \u003d t;\n \t\tlws_pt_unlock(pt);\n \t}\n \n //\tn \u003d poll(pt-\u003efds, pt-\u003efds_count, timeout_ms);\n \t{\n \t\tfd_set readfds, writefds, errfds;\n-\t\tstruct timeval tv \u003d { timeout_ms / 1000,\n-\t\t\t\t (timeout_ms % 1000) * 1000 }, *ptv \u003d \u0026tv;\n+\t\tstruct timeval tv \u003d { timeout_us / LWS_US_PER_SEC,\n+\t\t\t\t timeout_us % LWS_US_PER_SEC }, *ptv \u003d \u0026tv;\n \t\tint max_fd \u003d 0;\n \t\tFD_ZERO(\u0026readfds);\n \t\tFD_ZERO(\u0026writefds);\ndiff --git a/lib/plat/optee/network.c b/lib/plat/optee/network.c\nindex a305293..f1f976b 100644\n--- a/lib/plat/optee/network.c\n+++ b/lib/plat/optee/network.c\n@@ -58,6 +58,7 @@ lws_poll_listen_fd(struct lws_pollfd *fd)\n LWS_EXTERN int\n _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n {\n+\tlws_usec_t timeout_us \u003d timeout_ms * LWS_US_PER_MS;\n \tstruct lws_context_per_thread *pt;\n \tint n \u003d -1, m, c;\n \t//char buf;\n@@ -93,10 +94,24 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \t\t/* still somebody left who wants forced service? */\n \t\tif (!lws_service_adjust_timeout(context, 1, pt-\u003etid))\n \t\t\t/* yes... come back again quickly */\n-\t\t\ttimeout_ms \u003d 0;\n+\t\t\ttimeout_us \u003d 0;\n \t}\n \n-\tn \u003d poll(pt-\u003efds, pt-\u003efds_count, timeout_ms);\n+\tif (timeout_us) {\n+\t\tlws_usec_t t, us \u003d lws_now_usecs();\n+\n+\t\tlws_pt_lock(pt, __func__);\n+\t\t/* don't stay in poll wait longer than next hr timeout */\n+\t\tt \u003d __lws_hrtimer_service(pt, us);\n+\t\tif (t \u0026\u0026 timeout_us \u003e t)\n+\t\t\ttimeout_us \u003d t;\n+\t\tt \u003d __lws_seq_timeout_check(pt, us);\n+\t\tif (t \u0026\u0026 timeout_us \u003e t)\n+\t\t\ttimeout_us \u003d t;\n+\t\tlws_pt_unlock(pt);\n+\t}\n+\n+\tn \u003d poll(pt-\u003efds, pt-\u003efds_count, timeout_us / LWS_US_PER_MS);\n \n \tm \u003d 0;\n \ndiff --git a/lib/plat/unix/unix-service.c b/lib/plat/unix/unix-service.c\nindex a94f6f5..83c4c3e 100644\n--- a/lib/plat/unix/unix-service.c\n+++ b/lib/plat/unix/unix-service.c\n@@ -36,6 +36,7 @@ LWS_EXTERN int\n _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n {\n \tvolatile struct lws_foreign_thread_pollfd *ftp, *next;\n+\tlws_usec_t timeout_us \u003d timeout_ms * LWS_US_PER_MS;\n \tvolatile struct lws_context_per_thread *vpt;\n \tstruct lws_context_per_thread *pt;\n \tint n \u003d -1, m, c;\n@@ -62,9 +63,9 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \t\tmemset(\u0026_lws, 0, sizeof(_lws));\n \t\t_lws.context \u003d context;\n \n-\t\tpt-\u003eservice_tid \u003d\n-\t\t\tcontext-\u003evhost_list-\u003eprotocols[0].callback(\n-\t\t\t\u0026_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);\n+\t\tpt-\u003eservice_tid \u003d context-\u003evhost_list-\u003eprotocols[0].callback(\n+\t\t\t\t\t\u0026_lws, LWS_CALLBACK_GET_THREAD_ID,\n+\t\t\t\t\tNULL, NULL, 0);\n \t\tpt-\u003eservice_tid_detected \u003d 1;\n \t}\n \n@@ -77,21 +78,24 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \t\t/* still somebody left who wants forced service? */\n \t\tif (!lws_service_adjust_timeout(context, 1, pt-\u003etid))\n \t\t\t/* yes... come back again quickly */\n-\t\t\ttimeout_ms \u003d 0;\n+\t\t\ttimeout_us \u003d 0;\n \t}\n \n-\tif (timeout_ms) {\n+\tif (timeout_us) {\n+\t\tlws_usec_t t;\n+\n \t\tlws_pt_lock(pt, __func__);\n \t\t/* don't stay in poll wait longer than next hr timeout */\n-\t\tlws_usec_t t \u003d __lws_hrtimer_service(pt);\n-\t\tif ((lws_usec_t)timeout_ms * 1000 \u003e t)\n-\t\t\ttimeout_ms \u003d t / 1000;\n+\t\tt \u003d __lws_event_service_get_earliest_wake(pt, lws_now_usecs());\n+\t\tif (t \u0026\u0026 t \u003c timeout_us)\n+\t\t\ttimeout_us \u003d t;\n+\n \t\tlws_pt_unlock(pt);\n \t}\n \n \tvpt-\u003einside_poll \u003d 1;\n \tlws_memory_barrier();\n-\tn \u003d poll(pt-\u003efds, pt-\u003efds_count, timeout_ms);\n+\tn \u003d poll(pt-\u003efds, pt-\u003efds_count, timeout_us / LWS_US_PER_MS);\n \tvpt-\u003einside_poll \u003d 0;\n \tlws_memory_barrier();\n \n@@ -130,7 +134,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \n \t/* we have come out of a poll wait... check the hrtimer list */\n \n-\t__lws_hrtimer_service(pt);\n+\t__lws_hrtimer_service(pt, lws_now_usecs());\n \n \tlws_pt_unlock(pt);\n \ndiff --git a/lib/plat/windows/windows-service.c b/lib/plat/windows/windows-service.c\nindex c95ff0f..614baea 100644\n--- a/lib/plat/windows/windows-service.c\n+++ b/lib/plat/windows/windows-service.c\n@@ -28,6 +28,7 @@\n LWS_EXTERN int\n _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n {\n+\tlws_usec_t timeout_us \u003d timeout_ms * LWS_US_PER_MS;\n \tstruct lws_context_per_thread *pt;\n \tWSANETWORKEVENTS networkevents;\n \tstruct lws_pollfd *pfd;\n@@ -114,18 +115,21 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \t\t/* still somebody left who wants forced service? */\n \t\tif (!lws_service_adjust_timeout(context, 1, pt-\u003etid))\n \t\t\t/* yes... come back again quickly */\n-\t\t\ttimeout_ms \u003d 0;\n+\t\t\ttimeout_us \u003d 0;\n \t}\n \n-\tif (timeout_ms) {\n-\t\tlws_usec_t t;\n+\tif (timeout_us) {\n+\t\tlws_usec_t t, us \u003d lws_now_usecs();\n \n \t\tlws_pt_lock(pt, __func__);\n-\t\t/* don't stay in poll wait longer than next hr timeout */\n-\t\tt \u003d __lws_hrtimer_service(pt);\n-\n-\t\tif ((lws_usec_t)timeout_ms * 1000 \u003e t)\n-\t\t\ttimeout_ms \u003d (int)(t / 1000);\n+\t\t/* don't stay in poll wait longer than next hr timeout... */\n+\t\tt \u003d __lws_hrtimer_service(pt, us);\n+\t\tif (t \u0026\u0026 timeout_us \u003e t)\n+\t\t\ttimeout_us \u003d t;\n+\t\t/* ... or next sequencer timeout */\n+\t\tt \u003d __lws_seq_timeout_check(pt, us);\n+\t\tif (t \u0026\u0026 timeout_us \u003e t)\n+\t\t\ttimeout_us \u003d t;\n \t\tlws_pt_unlock(pt);\n \t}\n \n@@ -137,7 +141,8 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)\n \t\t FD_ROUTING_INTERFACE_CHANGE |\n \t\t FD_ADDRESS_LIST_CHANGE);\n \n-\tev \u003d WSAWaitForMultipleEvents(1, \u0026pt-\u003eevents, FALSE, timeout_ms, FALSE);\n+\tev \u003d WSAWaitForMultipleEvents(1, \u0026pt-\u003eevents, FALSE,\n+\t\t\t\t timeout_us / LWS_US_PER_MS, FALSE);\n \tif (ev \u003d\u003d WSA_WAIT_EVENT_0) {\n \t\tEnterCriticalSection(\u0026pt-\u003einterrupt_lock);\n \t\tinterrupt_requested \u003d pt-\u003einterrupt_requested;\ndiff --git a/minimal-examples/api-tests/api-test-lws_sequencer/main.c b/minimal-examples/api-tests/api-test-lws_sequencer/main.c\nindex 7924c0c..04dcda2 100644\n--- a/minimal-examples/api-tests/api-test-lws_sequencer/main.c\n+++ b/minimal-examples/api-tests/api-test-lws_sequencer/main.c\n@@ -162,7 +162,7 @@ notify:\n \n \tlws_set_wsi_user(wsi, NULL);\n \ts-\u003ecwsi \u003d NULL;\n-\tlws_sequencer_queue_event(lws_sequencer_from_user(s), seq_msg,\n+\tlws_seq_queue_event(lws_seq_from_user(s), seq_msg,\n \t\t\t\t NULL, NULL);\n \n \treturn 0;\n@@ -185,7 +185,7 @@ sequencer_start_client(struct myseq *s)\n \tlws_strncpy(uri, url_paths[s-\u003estate], sizeof(uri));\n \n \tmemset(\u0026i, 0, sizeof i);\n-\ti.context \u003d lws_sequencer_get_context(lws_sequencer_from_user(s));\n+\ti.context \u003d lws_seq_get_context(lws_seq_from_user(s));\n \n \tif (lws_parse_uri(uri, \u0026prot, \u0026i.address, \u0026i.port, \u0026path1)) {\n \t\tlwsl_err(\u0022%s: uri error %s\u005cn\u0022, __func__, uri);\n@@ -217,13 +217,13 @@ sequencer_start_client(struct myseq *s)\n \n \t\t/* we couldn't even get started with the client connection */\n \n-\t\tlws_sequencer_queue_event(lws_sequencer_from_user(s),\n+\t\tlws_seq_queue_event(lws_seq_from_user(s),\n \t\t\t\t SEQ_MSG_CLIENT_FAILED, NULL, NULL);\n \n \t\treturn 1;\n \t}\n \n-\tlws_sequencer_timeout(lws_sequencer_from_user(s), 3);\n+\tlws_seq_timeout_us(lws_seq_from_user(s), 3 * LWS_US_PER_SEC);\n \n \tlwsl_notice(\u0022%s: wsi %p: connecting to %s://%s:%d%s\u005cn\u0022, __func__,\n \t\t s-\u003ecwsi, prot, i.address, i.port, path);\n@@ -297,7 +297,7 @@ sequencer_cb(struct lws_sequencer *seq, void *user, int event,\n \t\t\t s-\u003estate, s-\u003ehttp_resp);\n \n done:\n-\t\tlws_sequencer_timeout(lws_sequencer_from_user(s), 0);\n+\t\tlws_seq_timeout_us(lws_seq_from_user(s), LWSSEQTO_NONE);\n \t\ts-\u003estate++;\n \t\tif (s-\u003estate \u003d\u003d LWS_ARRAY_SIZE(url_paths)) {\n \t\t\t/* the sequence has completed */\n@@ -324,7 +324,7 @@ main(int argc, const char **argv)\n \tint n \u003d 1, logs \u003d LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;\n \tstruct lws_context_creation_info info;\n \tstruct lws_context *context;\n-\tlws_sequencer_t *seq;\n+\tlws_seq_t *seq;\n \tstruct lws_vhost *vh;\n \tlws_seq_info_t i;\n \tstruct myseq *s;\n@@ -378,7 +378,7 @@ main(int argc, const char **argv)\n \ti.cb \u003d sequencer_cb;\n \ti.name \u003d \u0022seq\u0022;\n \n-\tseq \u003d lws_sequencer_create(\u0026i);\n+\tseq \u003d lws_seq_create(\u0026i);\n \tif (!seq) {\n \t\tlwsl_err(\u0022%s: unable to create sequencer\u005cn\u0022, __func__);\n \t\tgoto bail1;\n","s":{"c":1746418058,"u": 33006}}
],"g": 36183,"chitpc": 0,"ehitpc": 0,"indexed":0
,
"ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}