]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
time-keeping: keep timestamp in multi, always update
authorStefan Eissing <stefan@eissing.org>
Thu, 18 Dec 2025 12:55:07 +0000 (13:55 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 18 Dec 2025 21:10:06 +0000 (22:10 +0100)
Always use curlx_now() when calling Curl_pgrs_now(data). Tests with the
"manual" updates to now proved differ more then 100ms in parallel testing.

Add `curlx_nowp()` to set current time into a struct curltime.
Add `curlx_ptimediff_ms() and friends, passing pointers.

Update documentation.

Closes #19998

61 files changed:
docs/internals/TIME-KEEPING.md
lib/asyn-ares.c
lib/asyn-thrdd.c
lib/cf-https-connect.c
lib/cf-ip-happy.c
lib/cf-socket.c
lib/cfilters.c
lib/conncache.c
lib/connect.c
lib/connect.h
lib/cshutdn.c
lib/curl_trc.c
lib/curlx/timeval.c
lib/curlx/timeval.h
lib/easy.c
lib/ftp.c
lib/hostip.c
lib/http.c
lib/http2.c
lib/imap.c
lib/mqtt.c
lib/multi.c
lib/multi_ev.c
lib/multi_ev.h
lib/multihandle.h
lib/multiif.h
lib/pingpong.c
lib/pingpong.h
lib/pop3.c
lib/progress.c
lib/progress.h
lib/psl.c
lib/rand.c
lib/ratelimit.c
lib/ratelimit.h
lib/request.c
lib/sendf.c
lib/setopt.c
lib/smtp.c
lib/splay.c
lib/splay.h
lib/telnet.c
lib/transfer.c
lib/url.c
lib/url.h
lib/vquic/curl_ngtcp2.c
lib/vquic/curl_osslq.c
lib/vquic/curl_quiche.c
lib/vquic/vquic.c
lib/vquic/vquic_int.h
lib/vssh/libssh2.c
lib/vtls/gtls.c
lib/vtls/openssl.c
lib/vtls/schannel.c
lib/vtls/schannel_int.h
lib/vtls/vtls.c
lib/vtls/wolfssl.c
tests/unit/unit1303.c
tests/unit/unit1309.c
tests/unit/unit1399.c
tests/unit/unit1607.c

index fc0020d6a419f5ba932973dc23442325e7674276..769c195d1c77e7043871f783d52fb61f6c7b8023 100644 (file)
@@ -11,10 +11,6 @@ time function is `curlx_now()` and it uses a **monotonic** clock on most platfor
 ensures that time only ever increases (the timestamps it gives are however not the "real"
 world clock).
 
-The simplest handling of transfer time would be to just always call `curlx_now()`. However
-there is a performance penalty to that - varying by platform - so this is not a desirable
-strategy. Processing thousands of transfers in a loop needs a smarter approach.
-
 ## Initial Approach (now historic)
 
 The loop processing functions called `curlx_now()` at the beginning and then passed
@@ -34,49 +30,16 @@ in the correct order: *queue -> nameloopup -> connect -> appconnect ->...*.)
 
 The strategy of handling transfer's time is now:
 
-* Keep a "now" timestamp in `data->progress.now`.
-* Perform time checks and event recording using `data->progress.now`.
-* Set `data->progress.now` at the start of API calls (e.g. `curl_multi_perform()`, etc.).
-* Set `data->progress.now` when recorded events happen (for precision).
-* Set `data->progress.now` on multi state changes.
-* Set `data->progress.now` in `pingpong` timeout handling, since `pingpong` is old and not always non-blocking.
-
-In addition to *setting* `data->progress.now` this timestamp can be *advanced* using 2 new methods:
-
-* `Curl_pgrs_now_at_least(data, &now)`: code that has a "now" timestamp can progress the `data`'s own "now" to be at least as new. If `data->progress.now` is already newer, no change is done. A transfer never goes **back**.
-* `Curl_pgrs_now_update(data1, data2)`: update the "now" in `data1` to be at least as new as the one in `data2`. If it already is newer, nothing changes.
-
-### Time Advancing Loops
-
-This advancing is used in the following way in loop like `curl_multi_perform()`:
-
-```C
-struct curltime now = curlx_now(); /* start of API call */
-forall data in transfers {
-  Curl_pgrs_set_at_least(data, now);
-  progress(data);   /* may update "now" */
-  now = data->progress.now;
-}
-```
-
-Transfers that update their "now" pass that timestamp to the next transfer processed.
-
-### Transfers triggering other transfers
-
-In HTTP/2 and HTTP/3 processing, incoming data causes actions on transfers other than
-the calling one. The protocols may receive data for any transfer on the connection and need
-to dispatch it:
-
-* a Close/Reset comes in for another transfer. That transfer is marked as "dirty", making sure it is processed in a timely manner.
-* Response Data arrives: this data is written out to the client. Before this is done, the "now" timestamp is updated via `Curl_pgrs_now_update(data, calling)` from the "calling" transfer.
-
-## Blocking Operations
+* Keep a "now" timestamp in the multi handle. Keep a fallback "now" timestamp in the easy handle.
+* Always use `Curl_pgrs_now(data)` to get the current time of a transfer.
+* Do not use `curlx_now()` directly for transfer handling (exceptions apply for loops).
 
-We still have places in `libcurl` where we do blocking operations. We should always use `Curl_pgrs_now_set(data)` afterwards since we cannot be sure how much time has passed. Since loop processing passed an updated "now" to the next transfer, a delay due to blocking is passed on.
+This has the following advantages:
 
-There are other places where we may lose track of time:
+* No need to pass a `struct curltime` around or pass a pointer to an outdated timestamp to other functions.
+* No need to calculate the exact `now` until it is really used.
+* Passing a `const` pointer is better than struct passing. Updating and passing a pointer to the same memory location for all transfers is even better.
 
-* Cache/Pool Locks: no "now" updates happen after a lock has been acquired. These locks should not be kept for a longer time.
-* User Callbacks: no "now" updates happen after callbacks have been invoked. The expectation is that those do not take long.
+Caveats:
 
-Should these assumptions prove wrong, we need to add updates.
+* do not store the pointer returned by `Curl_pgrs_now(data)` anywhere that outlives the current code invocation.
index 81b7090f2255f0f1fa1fec03b54c7b65e8e1bb62..a7704d1ca6acc17d833dd68430e6e4a97d9ac42c 100644 (file)
@@ -311,7 +311,8 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
      /* This is only set to non-zero if the timer was started. */
      (ares->happy_eyeballs_dns_time.tv_sec ||
       ares->happy_eyeballs_dns_time.tv_usec) &&
-     (curlx_timediff_ms(data->progress.now, ares->happy_eyeballs_dns_time) >=
+     (curlx_ptimediff_ms(Curl_pgrs_now(data),
+                        &ares->happy_eyeballs_dns_time) >=
       HAPPY_EYEBALLS_DNS_TIMEOUT)) {
     /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer
        running. */
@@ -439,14 +440,13 @@ CURLcode Curl_async_await(struct Curl_easy *data,
       result = CURLE_ABORTED_BY_CALLBACK;
     else {
       struct curltime now = curlx_now(); /* update in loop */
-      timediff_t elapsed_ms = curlx_timediff_ms(now, data->progress.now);
+      timediff_t elapsed_ms = curlx_ptimediff_ms(&now, Curl_pgrs_now(data));
       if(elapsed_ms <= 0)
         timeout_ms -= 1; /* always deduct at least 1 */
       else if(elapsed_ms > timeout_ms)
         timeout_ms = -1;
       else
         timeout_ms -= elapsed_ms;
-      Curl_pgrs_now_at_least(data, &now);
     }
     if(timeout_ms < 0)
       result = CURLE_OPERATION_TIMEDOUT;
@@ -582,7 +582,7 @@ static void async_ares_hostbyname_cb(void *user_data,
        timeout to prevent it. After all, we do not even know where in the
        c-ares retry cycle each request is.
     */
-    ares->happy_eyeballs_dns_time = data->progress.now;
+    ares->happy_eyeballs_dns_time = *Curl_pgrs_now(data);
     Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS);
   }
 }
index 408f05844dab4fe863809e732980c8423e0584d3..a2656f64cb43a0cf57153313d52e88626e5bff11 100644 (file)
@@ -63,6 +63,7 @@
 #include "url.h"
 #include "multiif.h"
 #include "curl_threads.h"
+#include "progress.h"
 #include "select.h"
 
 #ifdef USE_ARES
@@ -442,7 +443,7 @@ static bool async_thrdd_init(struct Curl_easy *data,
 
   /* passing addr_ctx to the thread adds a reference */
   addr_ctx->ref_count = 2;
-  addr_ctx->start = data->progress.now;
+  addr_ctx->start = *Curl_pgrs_now(data);
 
 #ifdef HAVE_GETADDRINFO
   addr_ctx->thread_hnd = Curl_thread_create(getaddrinfo_thread, addr_ctx);
@@ -655,8 +656,8 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data,
   else {
     /* poll for name lookup done with exponential backoff up to 250ms */
     /* should be fine even if this converts to 32-bit */
-    timediff_t elapsed = curlx_timediff_ms(data->progress.now,
-                                           data->progress.t_startsingle);
+    timediff_t elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data),
+                                            &data->progress.t_startsingle);
     if(elapsed < 0)
       elapsed = 0;
 
@@ -706,7 +707,8 @@ CURLcode Curl_async_pollset(struct Curl_easy *data, struct easy_pollset *ps)
     result = Curl_pollset_add_in(data, ps, thrdd->addr->sock_pair[0]);
 #else
     timediff_t milli;
-    timediff_t ms = curlx_timediff_ms(data->progress.now, thrdd->addr->start);
+    timediff_t ms =
+      curlx_ptimediff_ms(Curl_pgrs_now(data), &thrdd->addr->start);
     if(ms < 3)
       milli = 0;
     else if(ms <= 50)
index 104df248ebd5cf98ce7923fb81c11a09066345b0..849b45c773cb09523cbe1e09e57a68d20870b4c2 100644 (file)
@@ -35,6 +35,7 @@
 #include "multiif.h"
 #include "cf-https-connect.h"
 #include "http2.h"
+#include "progress.h"
 #include "select.h"
 #include "vquic/vquic.h"
 
@@ -149,7 +150,7 @@ static void cf_hc_baller_init(struct cf_hc_baller *b,
   struct Curl_cfilter *save = cf->next;
 
   cf->next = NULL;
-  b->started = data->progress.now;
+  b->started = *Curl_pgrs_now(data);
   switch(b->alpn_id) {
   case ALPN_h3:
     transport = TRNSPRT_QUIC;
@@ -212,12 +213,12 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
   if(reply_ms >= 0)
     CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms",
                 winner->name,
-                (int)curlx_timediff_ms(data->progress.now,
-                                       winner->started), reply_ms);
+                (int)curlx_ptimediff_ms(Curl_pgrs_now(data),
+                                        &winner->started), reply_ms);
   else
     CURL_TRC_CF(data, cf, "deferred handshake %s: %dms",
-                winner->name, (int)curlx_timediff_ms(data->progress.now,
-                                                     winner->started));
+                winner->name, (int)curlx_ptimediff_ms(Curl_pgrs_now(data),
+                                                      &winner->started));
 
   /* install the winning filter below this one. */
   cf->next = winner->cf;
@@ -265,7 +266,7 @@ static bool time_to_start_next(struct Curl_cfilter *cf,
                 ctx->ballers[idx].name);
     return TRUE;
   }
-  elapsed_ms = curlx_timediff_ms(now, ctx->started);
+  elapsed_ms = curlx_ptimediff_ms(&now, &ctx->started);
   if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) {
     CURL_TRC_CF(data, cf, "hard timeout of %" FMT_TIMEDIFF_T "ms reached, "
                 "starting %s",
@@ -308,7 +309,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
     for(i = 0; i < ctx->baller_count; i++)
       DEBUGASSERT(!ctx->ballers[i].cf);
     CURL_TRC_CF(data, cf, "connect, init");
-    ctx->started = data->progress.now;
+    ctx->started = *Curl_pgrs_now(data);
     cf_hc_baller_init(&ctx->ballers[0], cf, data, ctx->ballers[0].transport);
     if(ctx->baller_count > 1) {
       Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS);
@@ -327,7 +328,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf,
       }
     }
 
-    if(time_to_start_next(cf, data, 1, data->progress.now)) {
+    if(time_to_start_next(cf, data, 1, *Curl_pgrs_now(data))) {
       cf_hc_baller_init(&ctx->ballers[1], cf, data, ctx->ballers[1].transport);
     }
 
@@ -468,7 +469,7 @@ static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf,
     struct Curl_cfilter *cfb = ctx->ballers[i].cf;
     memset(&t, 0, sizeof(t));
     if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) {
-      if((t.tv_sec || t.tv_usec) && curlx_timediff_us(t, tmax) > 0)
+      if((t.tv_sec || t.tv_usec) && curlx_ptimediff_us(&t, &tmax) > 0)
         tmax = t;
     }
   }
index d6501d0079bbc5c852aa26a61f4deb30ae2809cc..36d53ed9c2341bf8cab38dc4ef0807a9b9b2616c 100644 (file)
@@ -393,7 +393,7 @@ evaluate:
   /* no attempt connected yet, start another one? */
   if(!ongoing) {
     if(!bs->started.tv_sec && !bs->started.tv_usec)
-      bs->started = data->progress.now;
+      bs->started = *Curl_pgrs_now(data);
     do_more = TRUE;
   }
   else {
@@ -403,7 +403,7 @@ evaluate:
       more_possible = cf_ai_iter_has_more(&bs->ipv6_iter);
 #endif
     do_more = more_possible &&
-      (curlx_timediff_ms(data->progress.now, bs->last_attempt_started) >=
+      (curlx_ptimediff_ms(Curl_pgrs_now(data), &bs->last_attempt_started) >=
        bs->attempt_delay_ms);
     if(do_more)
       CURL_TRC_CF(data, cf, "happy eyeballs timeout expired, "
@@ -442,7 +442,7 @@ evaluate:
       while(*panchor)
         panchor = &((*panchor)->next);
       *panchor = a;
-      bs->last_attempt_started = data->progress.now;
+      bs->last_attempt_started = *Curl_pgrs_now(data);
       bs->last_attempt_ai_family = ai_family;
       /* and run everything again */
       goto evaluate;
@@ -451,7 +451,7 @@ evaluate:
       /* tried all addresses, no success but some where inconclusive.
        * Let's restart the inconclusive ones. */
       timediff_t since_ms =
-        curlx_timediff_ms(data->progress.now, bs->last_attempt_started);
+        curlx_ptimediff_ms(Curl_pgrs_now(data), &bs->last_attempt_started);
       timediff_t delay_ms = bs->attempt_delay_ms - since_ms;
       if(delay_ms <= 0) {
         CURL_TRC_CF(data, cf, "all attempts inconclusive, restarting one");
@@ -464,7 +464,7 @@ evaluate:
           CURL_TRC_CF(data, cf, "restarted baller %d -> %d", i, result);
           if(result) /* serious failure */
             goto out;
-          bs->last_attempt_started = data->progress.now;
+          bs->last_attempt_started = *Curl_pgrs_now(data);
           goto evaluate;
         }
         DEBUGASSERT(0); /* should not come here */
@@ -499,7 +499,8 @@ out:
     next_expire_ms = Curl_timeleft_ms(data, TRUE);
     if(next_expire_ms <= 0) {
       failf(data, "Connection timeout after %" FMT_OFF_T " ms",
-        curlx_timediff_ms(data->progress.now, data->progress.t_startsingle));
+        curlx_ptimediff_ms(Curl_pgrs_now(data),
+                           &data->progress.t_startsingle));
       return CURLE_OPERATION_TIMEDOUT;
     }
 
@@ -511,7 +512,7 @@ out:
     if(more_possible) {
       timediff_t expire_ms, elapsed_ms;
       elapsed_ms =
-        curlx_timediff_ms(data->progress.now, bs->last_attempt_started);
+        curlx_ptimediff_ms(Curl_pgrs_now(data), &bs->last_attempt_started);
       expire_ms = CURLMAX(bs->attempt_delay_ms - elapsed_ms, 0);
       next_expire_ms = CURLMIN(next_expire_ms, expire_ms);
       if(next_expire_ms <= 0) {
@@ -587,7 +588,7 @@ static struct curltime cf_ip_ballers_max_time(struct cf_ip_ballers *bs,
   for(a = bs->running; a; a = a->next) {
     memset(&t, 0, sizeof(t));
     if(!a->cf->cft->query(a->cf, data, query, NULL, &t)) {
-      if((t.tv_sec || t.tv_usec) && curlx_timediff_us(t, tmax) > 0)
+      if((t.tv_sec || t.tv_usec) && curlx_ptimediff_us(&t, &tmax) > 0)
         tmax = t;
     }
   }
@@ -672,7 +673,8 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
           proxy_name ? "via " : "",
           proxy_name ? proxy_name : "",
           proxy_name ? " " : "",
-          curlx_timediff_ms(data->progress.now, data->progress.t_startsingle),
+          curlx_ptimediff_ms(Curl_pgrs_now(data),
+                             &data->progress.t_startsingle),
           curl_easy_strerror(result));
   }
 
@@ -704,7 +706,7 @@ static CURLcode start_connect(struct Curl_cfilter *cf,
   }
 
   CURL_TRC_CF(data, cf, "init ip ballers for transport %u", ctx->transport);
-  ctx->started = data->progress.now;
+  ctx->started = *Curl_pgrs_now(data);
   return cf_ip_ballers_init(&ctx->ballers, cf->conn->ip_version,
                             dns->addr, ctx->cf_create, ctx->transport,
                             data->set.happy_eyeballs_timeout);
index 4e122093cdf9589af8c92775c1dd737f04b07b54..121dcd4ec2f059aa8cb69d233ee7dcde3b702664 100644 (file)
@@ -1081,7 +1081,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
 
   (void)data;
   DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
-  ctx->started_at = data->progress.now;
+  ctx->started_at = *Curl_pgrs_now(data);
 #ifdef SOCK_NONBLOCK
   /* Do not tuck SOCK_NONBLOCK into socktype when opensocket callback is set
    * because we would not know how socketype is about to be used in the
@@ -1208,7 +1208,7 @@ out:
   }
   else if(isconnected) {
     set_local_ip(cf, data);
-    ctx->connected_at = data->progress.now;
+    ctx->connected_at = *Curl_pgrs_now(data);
     cf->connected = TRUE;
   }
   CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" FMT_SOCKET_T,
@@ -1327,7 +1327,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
   else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) {
     if(verifyconnect(ctx->sock, &ctx->error)) {
       /* we are connected with TCP, awesome! */
-      ctx->connected_at = data->progress.now;
+      ctx->connected_at = *Curl_pgrs_now(data);
       set_local_ip(cf, data);
       *done = TRUE;
       cf->connected = TRUE;
@@ -1409,7 +1409,8 @@ static void win_update_sndbuf_size(struct Curl_easy *data,
   ULONG ideal;
   DWORD ideallen;
 
-  if(curlx_timediff_ms(data->progress.now, ctx->last_sndbuf_query_at) > 1000) {
+  if(curlx_ptimediff_ms(Curl_pgrs_now(data),
+                        &ctx->last_sndbuf_query_at) > 1000) {
     if(!WSAIoctl(ctx->sock, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0,
                  &ideal, sizeof(ideal), &ideallen, 0, 0) &&
        ideal != ctx->sndbuf_size &&
@@ -1417,7 +1418,7 @@ static void win_update_sndbuf_size(struct Curl_easy *data,
                    (const char *)&ideal, sizeof(ideal))) {
       ctx->sndbuf_size = ideal;
     }
-    ctx->last_sndbuf_query_at = data->progress.now;
+    ctx->last_sndbuf_query_at = *Curl_pgrs_now(data);
   }
 }
 
@@ -1564,7 +1565,7 @@ static CURLcode cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
 
   CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, %zu", len, result, *pnread);
   if(!result && !ctx->got_first_byte) {
-    ctx->first_byte_at = data->progress.now;
+    ctx->first_byte_at = *Curl_pgrs_now(data);
     ctx->got_first_byte = TRUE;
   }
   return result;
@@ -1678,7 +1679,8 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf,
     return CURLE_OK;
   case CF_QUERY_CONNECT_REPLY_MS:
     if(ctx->got_first_byte) {
-      timediff_t ms = curlx_timediff_ms(ctx->first_byte_at, ctx->started_at);
+      timediff_t ms = curlx_ptimediff_ms(&ctx->first_byte_at,
+                                         &ctx->started_at);
       *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
     }
     else
@@ -2011,7 +2013,7 @@ static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf,
     timeout_ms = other_ms;
   else {
     /* subtract elapsed time */
-    timeout_ms -= curlx_timediff_ms(data->progress.now, ctx->started_at);
+    timeout_ms -= curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->started_at);
     if(!timeout_ms)
       /* avoid returning 0 as that means no timeout! */
       timeout_ms = -1;
@@ -2147,7 +2149,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf,
   cf_tcp_set_accepted_remote_ip(cf, data);
   set_local_ip(cf, data);
   ctx->active = TRUE;
-  ctx->connected_at = data->progress.now;
+  ctx->connected_at = *Curl_pgrs_now(data);
   cf->connected = TRUE;
   CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T
               ", remote=%s port=%d)",
@@ -2213,7 +2215,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
     goto out;
   Curl_conn_cf_add(data, conn, sockindex, cf);
 
-  ctx->started_at = data->progress.now;
+  ctx->started_at = *Curl_pgrs_now(data);
   conn->sock[sockindex] = ctx->sock;
   set_local_ip(cf, data);
   CURL_TRC_CF(data, cf, "set filter for listen socket fd=%" FMT_SOCKET_T
index 0c259e4439f4eef0c8665075860d930b22d1f59c..2ac99a4288bb128f37c33381bbceaf14b7ca2f70 100644 (file)
@@ -502,7 +502,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
        * socket and ip related information. */
       cf_cntrl_update_info(data, data->conn);
       conn_report_connect_stats(cf, data);
-      data->conn->keepalive = data->progress.now;
+      data->conn->keepalive = *Curl_pgrs_now(data);
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
       result = cf_verboseconnect(data, cf);
 #endif
index d9efb61a079d70941b916af3a0c7277b52310e2b..7e0e2c9084edab1c8a490d2d34d0f82832120fea 100644 (file)
@@ -206,7 +206,6 @@ void Curl_cpool_destroy(struct cpool *cpool)
                cpool->share ? "[SHARE] " : "", cpool->num_conn);
     /* Move all connections to the shutdown list */
     sigpipe_init(&pipe_st);
-    Curl_pgrs_now_set(cpool->idata);
     CPOOL_LOCK(cpool, cpool->idata);
     conn = cpool_get_first(cpool);
     while(conn) {
@@ -275,7 +274,7 @@ static struct cpool_bundle *cpool_add_bundle(struct cpool *cpool,
 
 static struct connectdata *
 cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle,
-                             struct curltime *pnow)
+                             const struct curltime *pnow)
 {
   struct Curl_llist_node *curr;
   timediff_t highscore = -1;
@@ -289,7 +288,7 @@ cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle,
 
     if(!CONN_INUSE(conn)) {
       /* Set higher score for the age passed since the connection was used */
-      score = curlx_timediff_ms(*pnow, conn->lastused);
+      score = curlx_ptimediff_ms(pnow, &conn->lastused);
 
       if(score > highscore) {
         highscore = score;
@@ -302,7 +301,7 @@ cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle,
 }
 
 static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool,
-                                                 struct curltime *pnow)
+                                                 const struct curltime *pnow)
 {
   struct Curl_hash_iterator iter;
   struct Curl_llist_node *curr;
@@ -325,7 +324,7 @@ static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool,
       if(CONN_INUSE(conn) || conn->bits.close || conn->connect_only)
         continue;
       /* Set higher score for the age passed since the connection was used */
-      score = curlx_timediff_ms(*pnow, conn->lastused);
+      score = curlx_ptimediff_ms(pnow, &conn->lastused);
       if(score > highscore) {
         highscore = score;
         oldest_idle = conn;
@@ -356,7 +355,6 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
   if(!dest_limit && !total_limit)
     return CPOOL_LIMIT_OK;
 
-  Curl_pgrs_now_update(cpool->idata, data);
   CPOOL_LOCK(cpool, cpool->idata);
   if(dest_limit) {
     size_t live;
@@ -377,7 +375,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
         /* The bundle is full. Extract the oldest connection that may
          * be removed now, if there is one. */
         oldest_idle = cpool_bundle_get_oldest_idle(bundle,
-                                                   &data->progress.now);
+                                                   Curl_pgrs_now(data));
         if(!oldest_idle)
           break;
         /* disconnect the old conn and continue */
@@ -409,7 +407,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
       }
       else {
         struct connectdata *oldest_idle =
-          cpool_get_oldest_idle(cpool, &data->progress.now);
+          cpool_get_oldest_idle(cpool, Curl_pgrs_now(data));
         if(!oldest_idle)
           break;
         /* disconnect the old conn and continue */
@@ -429,7 +427,6 @@ int Curl_cpool_check_limits(struct Curl_easy *data,
 
 out:
   CPOOL_UNLOCK(cpool, cpool->idata);
-  Curl_pgrs_now_update(data, cpool->idata);
   return result;
 }
 
@@ -539,7 +536,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
     maxconnects = data->multi->maxconnects;
   }
 
-  conn->lastused = data->progress.now; /* it was used up until now */
+  conn->lastused = *Curl_pgrs_now(data); /* it was used up until now */
   if(cpool && maxconnects) {
     /* may be called form a callback already under lock */
     bool do_lock = !CPOOL_IS_LOCKED(cpool);
@@ -549,7 +546,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data,
       infof(data, "Connection pool is full, closing the oldest of %zu/%u",
             cpool->num_conn, maxconnects);
 
-      oldest_idle = cpool_get_oldest_idle(cpool, &data->progress.now);
+      oldest_idle = cpool_get_oldest_idle(cpool, Curl_pgrs_now(data));
       kept = (oldest_idle != conn);
       if(oldest_idle) {
         Curl_conn_terminate(data, oldest_idle, FALSE);
@@ -636,7 +633,6 @@ static void cpool_discard_conn(struct cpool *cpool,
    * If we do a shutdown for an aborted transfer, the server might think
    * it was successful otherwise (for example an ftps: upload). This is
    * not what we want. */
-  Curl_pgrs_now_update(cpool->idata, data);
   if(aborted)
     done = TRUE;
   if(!done) {
@@ -702,13 +698,24 @@ void Curl_conn_terminate(struct Curl_easy *data,
     CPOOL_UNLOCK(cpool, data);
 }
 
+struct cpool_reaper_ctx {
+  size_t checked;
+  size_t reaped;
+};
+
 static int cpool_reap_dead_cb(struct Curl_easy *data,
                               struct connectdata *conn, void *param)
 {
-  (void)param;
-  if((!CONN_INUSE(conn) && conn->bits.no_reuse) ||
-     Curl_conn_seems_dead(conn, data)) {
+  struct cpool_reaper_ctx *reaper = param;
+  bool terminate = !CONN_INUSE(conn) && conn->bits.no_reuse;
+
+  if(!terminate) {
+    reaper->checked++;
+    terminate = Curl_conn_seems_dead(conn, data);
+  }
+  if(terminate) {
     /* stop the iteration here, pass back the connection that was pruned */
+    reaper->reaped++;
     Curl_conn_terminate(data, conn, FALSE);
     return 1;
   }
@@ -725,18 +732,20 @@ static int cpool_reap_dead_cb(struct Curl_easy *data,
 void Curl_cpool_prune_dead(struct Curl_easy *data)
 {
   struct cpool *cpool = cpool_get_instance(data);
+  struct cpool_reaper_ctx reaper;
   timediff_t elapsed;
 
   if(!cpool)
     return;
 
+  memset(&reaper, 0, sizeof(reaper));
   CPOOL_LOCK(cpool, data);
-  elapsed = curlx_timediff_ms(data->progress.now, cpool->last_cleanup);
+  elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &cpool->last_cleanup);
 
   if(elapsed >= 1000L) {
-    while(cpool_foreach(data, cpool, NULL, cpool_reap_dead_cb))
+    while(cpool_foreach(data, cpool, &reaper, cpool_reap_dead_cb))
       ;
-    cpool->last_cleanup = data->progress.now;
+    cpool->last_cleanup = *Curl_pgrs_now(data);
   }
   CPOOL_UNLOCK(cpool, data);
 }
@@ -745,8 +754,8 @@ static int conn_upkeep(struct Curl_easy *data,
                        struct connectdata *conn,
                        void *param)
 {
-  struct curltime *now = param;
-  Curl_conn_upkeep(data, conn, now);
+  (void)param;
+  Curl_conn_upkeep(data, conn);
   return 0; /* continue iteration */
 }
 
@@ -758,7 +767,7 @@ CURLcode Curl_cpool_upkeep(struct Curl_easy *data)
     return CURLE_OK;
 
   CPOOL_LOCK(cpool, data);
-  cpool_foreach(data, cpool, &data->progress.now, conn_upkeep);
+  cpool_foreach(data, cpool, NULL, conn_upkeep);
   CPOOL_UNLOCK(cpool, data);
   return CURLE_OK;
 }
index 42d5cd7a3fc48b1434ccd65f20def5020e3645cb..d9926d8697daac33db65e8227d9e84d4f35ae43d 100644 (file)
@@ -112,8 +112,9 @@ enum alpnid Curl_str2alpnid(const struct Curl_str *cstr)
  * @param duringconnect TRUE iff connect timeout is also taken into account.
  * @unittest: 1303
  */
-timediff_t Curl_timeleft_ms(struct Curl_easy *data,
-                            bool duringconnect)
+timediff_t Curl_timeleft_now_ms(struct Curl_easy *data,
+                                const struct curltime *pnow,
+                                bool duringconnect)
 {
   timediff_t timeleft_ms = 0;
   timediff_t ctimeleft_ms = 0;
@@ -129,7 +130,7 @@ timediff_t Curl_timeleft_ms(struct Curl_easy *data,
 
   if(data->set.timeout) {
     timeleft_ms = data->set.timeout -
-      curlx_timediff_ms(data->progress.now, data->progress.t_startop);
+      curlx_ptimediff_ms(pnow, &data->progress.t_startop);
     if(!timeleft_ms)
       timeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
   }
@@ -139,7 +140,7 @@ timediff_t Curl_timeleft_ms(struct Curl_easy *data,
   ctimeout_ms = (data->set.connecttimeout > 0) ?
     data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT;
   ctimeleft_ms = ctimeout_ms -
-    curlx_timediff_ms(data->progress.now, data->progress.t_startsingle);
+    curlx_ptimediff_ms(pnow, &data->progress.t_startsingle);
   if(!ctimeleft_ms)
     ctimeleft_ms = -1; /* 0 is "no limit", fake 1 ms expiry */
   if(!timeleft_ms)
@@ -149,13 +150,19 @@ timediff_t Curl_timeleft_ms(struct Curl_easy *data,
   return (ctimeleft_ms < timeleft_ms) ? ctimeleft_ms : timeleft_ms;
 }
 
+timediff_t Curl_timeleft_ms(struct Curl_easy *data,
+                            bool duringconnect)
+{
+  return Curl_timeleft_now_ms(data, Curl_pgrs_now(data), duringconnect);
+}
+
 void Curl_shutdown_start(struct Curl_easy *data, int sockindex,
                          int timeout_ms)
 {
   struct connectdata *conn = data->conn;
 
   DEBUGASSERT(conn);
-  conn->shutdown.start[sockindex] = data->progress.now;
+  conn->shutdown.start[sockindex] = *Curl_pgrs_now(data);
   conn->shutdown.timeout_ms = (timeout_ms > 0) ?
     (timediff_t)timeout_ms :
     ((data->set.shutdowntimeout > 0) ?
@@ -176,8 +183,8 @@ timediff_t Curl_shutdown_timeleft(struct Curl_easy *data,
     return 0; /* not started or no limits */
 
   left_ms = conn->shutdown.timeout_ms -
-            curlx_timediff_ms(data->progress.now,
-                              conn->shutdown.start[sockindex]);
+            curlx_ptimediff_ms(Curl_pgrs_now(data),
+                               &conn->shutdown.start[sockindex]);
   return left_ms ? left_ms : -1;
 }
 
index 09776e636f9c9f1770b90de3fb74973deb2b2ed2..5b59c6cf25334b92a19a809ad3cce8a48113e221 100644 (file)
@@ -40,6 +40,9 @@ enum alpnid Curl_str2alpnid(const struct Curl_str *str);
    to the timeouts set */
 timediff_t Curl_timeleft_ms(struct Curl_easy *data,
                             bool duringconnect);
+timediff_t Curl_timeleft_now_ms(struct Curl_easy *data,
+                                const struct curltime *pnow,
+                                bool duringconnect);
 
 #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
 
index 21ab1209ebc44fb361e9a73c3388b2903ef71ad3..4a403b261ec5dabf94c31ccca598ab698f3b1d07 100644 (file)
@@ -266,7 +266,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
                                   struct Curl_easy *data,
                                   int timeout_ms)
 {
-  struct curltime started = data->progress.now;
+  struct curltime started = *Curl_pgrs_now(data);
   struct Curl_llist_node *e;
   SIGPIPE_VARIABLE(pipe_st);
 
@@ -289,8 +289,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn,
     }
 
     /* wait for activity, timeout or "nothing" */
-    Curl_pgrs_now_set(data); /* update in loop */
-    spent_ms = curlx_timediff_ms(data->progress.now, started);
+    spent_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &started);
     if(spent_ms >= (timediff_t)timeout_ms) {
       CURL_TRC_M(data, "[SHUTDOWN] shutdown finished, %s",
                  (timeout_ms > 0) ? "timeout" : "best effort done");
index 8308f49c5dbb6d0e84aa7c42aa476e0a5fe27e41..d9932ae7f0cef067b15e14b9e531e8856db95736 100644 (file)
@@ -42,6 +42,7 @@
 #include "cf-haproxy.h"
 #include "cf-https-connect.h"
 #include "cf-ip-happy.h"
+#include "progress.h"
 #include "socks.h"
 #include "curlx/strparse.h"
 #include "vtls/vtls.h"
@@ -314,11 +315,12 @@ void Curl_trc_easy_timers(struct Curl_easy *data)
   if(CURL_TRC_TIMER_is_verbose(data)) {
     struct Curl_llist_node *e = Curl_llist_head(&data->state.timeoutlist);
     if(e) {
+      const struct curltime *pnow = Curl_pgrs_now(data);
       while(e) {
         struct time_node *n = Curl_node_elem(e);
         e = Curl_node_next(e);
         CURL_TRC_TIMER(data, n->eid, "expires in %" FMT_TIMEDIFF_T "ns",
-                       curlx_timediff_us(n->time, data->progress.now));
+                       curlx_ptimediff_us(&n->time, pnow));
       }
     }
   }
index 490dcf0838e7b8e626a32b4edcdc0ad57298128a..d1521ad418425442b29a65f27d4608541e0b9db7 100644 (file)
@@ -47,9 +47,8 @@ void curlx_now_init(void)
 }
 
 /* In case of bug fix this function has a counterpart in tool_util.c */
-struct curltime curlx_now(void)
+void curlx_pnow(struct curltime *pnow)
 {
-  struct curltime now;
   bool isVistaOrGreater;
   isVistaOrGreater = Curl_isVistaOrGreater;
   if(isVistaOrGreater) { /* QPC timer might have issues pre-Vista */
@@ -58,8 +57,8 @@ struct curltime curlx_now(void)
     freq = Curl_freq;
     DEBUGASSERT(freq.QuadPart);
     QueryPerformanceCounter(&count);
-    now.tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
-    now.tv_usec = (int)((count.QuadPart % freq.QuadPart) * 1000000 /
+    pnow->tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
+    pnow->tv_usec = (int)((count.QuadPart % freq.QuadPart) * 1000000 /
                         freq.QuadPart);
   }
   else {
@@ -73,16 +72,15 @@ struct curltime curlx_now(void)
 #pragma warning(pop)
 #endif
 
-    now.tv_sec = (time_t)(milliseconds / 1000);
-    now.tv_usec = (int)((milliseconds % 1000) * 1000);
+    pnow->tv_sec = (time_t)(milliseconds / 1000);
+    pnow->tv_usec = (int)((milliseconds % 1000) * 1000);
   }
-  return now;
 }
 
 #elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \
   defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW)
 
-struct curltime curlx_now(void)
+void curlx_pnow(struct curltime *pnow)
 {
   /*
   ** clock_gettime() is granted to be increased monotonically when the
@@ -94,7 +92,6 @@ struct curltime curlx_now(void)
 #ifdef HAVE_GETTIMEOFDAY
   struct timeval now;
 #endif
-  struct curltime cnow;
   struct timespec tsnow;
 
   /*
@@ -116,8 +113,8 @@ struct curltime curlx_now(void)
     have_clock_gettime &&
 #endif
     (clock_gettime(CLOCK_MONOTONIC_RAW, &tsnow) == 0)) {
-    cnow.tv_sec = tsnow.tv_sec;
-    cnow.tv_usec = (int)(tsnow.tv_nsec / 1000);
+    pnow->tv_sec = tsnow.tv_sec;
+    pnow->tv_usec = (int)(tsnow.tv_nsec / 1000);
   }
   else
 #endif
@@ -128,8 +125,8 @@ struct curltime curlx_now(void)
     have_clock_gettime &&
 #endif
     (clock_gettime(CLOCK_MONOTONIC, &tsnow) == 0)) {
-    cnow.tv_sec = tsnow.tv_sec;
-    cnow.tv_usec = (int)(tsnow.tv_nsec / 1000);
+    pnow->tv_sec = tsnow.tv_sec;
+    pnow->tv_usec = (int)(tsnow.tv_nsec / 1000);
   }
   /*
   ** Even when the configure process has truly detected monotonic clock
@@ -139,16 +136,15 @@ struct curltime curlx_now(void)
 #ifdef HAVE_GETTIMEOFDAY
   else {
     (void)gettimeofday(&now, NULL);
-    cnow.tv_sec = now.tv_sec;
-    cnow.tv_usec = (int)now.tv_usec;
+    pnow->tv_sec = now.tv_sec;
+    pnow->tv_usec = (int)now.tv_usec;
   }
 #else
   else {
-    cnow.tv_sec = time(NULL);
-    cnow.tv_usec = 0;
+    pnow->tv_sec = time(NULL);
+    pnow->tv_usec = 0;
   }
 #endif
-  return cnow;
 }
 
 #elif defined(HAVE_MACH_ABSOLUTE_TIME)
@@ -156,7 +152,7 @@ struct curltime curlx_now(void)
 #include <stdint.h>
 #include <mach/mach_time.h>
 
-struct curltime curlx_now(void)
+void curlx_pnow(struct curltime *pnow)
 {
   /*
   ** Monotonic timer on macOS is provided by mach_absolute_time(), which
@@ -165,7 +161,6 @@ struct curltime curlx_now(void)
   ** mach_timebase_info().
   */
   static mach_timebase_info_data_t timebase;
-  struct curltime cnow;
   uint64_t usecs;
 
   if(timebase.denom == 0)
@@ -176,15 +171,13 @@ struct curltime curlx_now(void)
   usecs /= timebase.denom;
   usecs /= 1000;
 
-  cnow.tv_sec = usecs / 1000000;
-  cnow.tv_usec = (int)(usecs % 1000000);
-
-  return cnow;
+  pnow->tv_sec = usecs / 1000000;
+  pnow->tv_usec = (int)(usecs % 1000000);
 }
 
 #elif defined(HAVE_GETTIMEOFDAY)
 
-struct curltime curlx_now(void)
+void curlx_pnow(struct curltime *pnow)
 {
   /*
   ** gettimeofday() is not granted to be increased monotonically, due to
@@ -192,42 +185,52 @@ struct curltime curlx_now(void)
   ** forward or backward in time.
   */
   struct timeval now;
-  struct curltime ret;
   (void)gettimeofday(&now, NULL);
-  ret.tv_sec = now.tv_sec;
-  ret.tv_usec = (int)now.tv_usec;
-  return ret;
+  pnow->tv_sec = now.tv_sec;
+  pnow->tv_usec = (int)now.tv_usec;
 }
 
 #else
 
-struct curltime curlx_now(void)
+void curlx_pnow(struct curltime *pnow)
 {
   /*
   ** time() returns the value of time in seconds since the Epoch.
   */
-  struct curltime now;
-  now.tv_sec = time(NULL);
-  now.tv_usec = 0;
-  return now;
+  pnow->tv_sec = time(NULL);
+  pnow->tv_usec = 0;
 }
 
 #endif
 
+struct curltime curlx_now(void)
+{
+  struct curltime now;
+  curlx_pnow(&now);
+  return now;
+}
+
 /*
  * Returns: time difference in number of milliseconds. For too large diffs it
  * returns max value.
  *
  * @unittest: 1323
  */
-timediff_t curlx_timediff_ms(struct curltime newer, struct curltime older)
+timediff_t curlx_ptimediff_ms(const struct curltime *newer,
+                              const struct curltime *older)
 {
-  timediff_t diff = (timediff_t)newer.tv_sec - older.tv_sec;
+  timediff_t diff = (timediff_t)newer->tv_sec - older->tv_sec;
   if(diff >= (TIMEDIFF_T_MAX / 1000))
     return TIMEDIFF_T_MAX;
   else if(diff <= (TIMEDIFF_T_MIN / 1000))
     return TIMEDIFF_T_MIN;
-  return diff * 1000 + (newer.tv_usec - older.tv_usec) / 1000;
+  return diff * 1000 + (newer->tv_usec - older->tv_usec) / 1000;
+}
+
+
+timediff_t curlx_timediff_ms(struct curltime newer, struct curltime older)
+{
+  return curlx_ptimediff_ms(&newer, &older);
 }
 
 /*
@@ -249,14 +252,20 @@ timediff_t curlx_timediff_ceil_ms(struct curltime newer,
  * Returns: time difference in number of microseconds. For too large diffs it
  * returns max value.
  */
-timediff_t curlx_timediff_us(struct curltime newer, struct curltime older)
+timediff_t curlx_ptimediff_us(const struct curltime *newer,
+                              const struct curltime *older)
 {
-  timediff_t diff = (timediff_t)newer.tv_sec - older.tv_sec;
+  timediff_t diff = (timediff_t)newer->tv_sec - older->tv_sec;
   if(diff >= (TIMEDIFF_T_MAX / 1000000))
     return TIMEDIFF_T_MAX;
   else if(diff <= (TIMEDIFF_T_MIN / 1000000))
     return TIMEDIFF_T_MIN;
-  return diff * 1000000 + newer.tv_usec - older.tv_usec;
+  return diff * 1000000 + newer->tv_usec - older->tv_usec;
+}
+
+timediff_t curlx_timediff_us(struct curltime newer, struct curltime older)
+{
+  return curlx_ptimediff_us(&newer, &older);
 }
 
 #if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR <= 3)
index 9cb57af2b73f6a7a60b792f11d255a932b8f1fb9..533e80e5e3c2836e05f0f1a204389466c46f08dc 100644 (file)
@@ -39,6 +39,7 @@ void curlx_now_init(void);
 #endif
 
 struct curltime curlx_now(void);
+void curlx_pnow(struct curltime *pnow);
 
 /*
  * Make sure that the first argument (newer) is the more recent time and older
@@ -47,6 +48,8 @@ struct curltime curlx_now(void);
  * Returns: the time difference in number of milliseconds.
  */
 timediff_t curlx_timediff_ms(struct curltime newer, struct curltime older);
+timediff_t curlx_ptimediff_ms(const struct curltime *newer,
+                              const struct curltime *older);
 
 /*
  * Make sure that the first argument (newer) is the more recent time and older
@@ -64,6 +67,8 @@ timediff_t curlx_timediff_ceil_ms(struct curltime newer,
  * Returns: the time difference in number of microseconds.
  */
 timediff_t curlx_timediff_us(struct curltime newer, struct curltime older);
+timediff_t curlx_ptimediff_us(const struct curltime *newer,
+                              const struct curltime *older);
 
 CURLcode curlx_gmtime(time_t intime, struct tm *store);
 
index d7d766a4f8ad264213d0a929273c0854e24a24df..e86f7f7404288cc47df32a464634ec1b6634d130 100644 (file)
@@ -607,11 +607,11 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
     CURLMsg *msg;
     struct pollfd fds[4];
     int pollrc;
-    struct curltime before;
+    struct curltime start;
     const unsigned int numfds = populate_fds(fds, ev);
 
     /* get the time stamp to use to figure out how long poll takes */
-    before = curlx_now();
+    curlx_pnow(&start);
 
     result = poll_fds(ev, fds, numfds, &pollrc);
     if(result)
@@ -647,7 +647,7 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
         /* If nothing updated the timeout, we decrease it by the spent time.
          * If it was updated, it has the new timeout time stored already.
          */
-        timediff_t spent_ms = curlx_timediff_ms(curlx_now(), before);
+        timediff_t spent_ms = curlx_timediff_ms(curlx_now(), start);
         if(spent_ms > 0) {
 #if DEBUG_EV_POLL
         curl_mfprintf(stderr, "poll timeout %ldms not updated, decrease by "
@@ -995,7 +995,6 @@ CURL *curl_easy_duphandle(CURL *d)
   if(dupset(outcurl, data))
     goto fail;
 
-  Curl_pgrs_now_set(outcurl); /* start of API call */
   outcurl->progress.hide     = data->progress.hide;
   outcurl->progress.callback = data->progress.callback;
 
@@ -1155,7 +1154,6 @@ CURLcode curl_easy_pause(CURL *d, int action)
   if(Curl_is_in_callback(data))
     recursive = TRUE;
 
-  Curl_pgrs_now_set(data); /* start of API call */
   recv_paused = Curl_xfer_recv_is_paused(data);
   recv_paused_new = (action & CURLPAUSE_RECV);
   send_paused = Curl_xfer_send_is_paused(data);
@@ -1180,7 +1178,7 @@ CURLcode curl_easy_pause(CURL *d, int action)
       Curl_multi_mark_dirty(data); /* make it run */
       /* On changes, tell application to update its timers. */
       if(changed) {
-        if(Curl_update_timer(data->multi, &data->progress.now) && !result)
+        if(Curl_update_timer(data->multi) && !result)
           result = CURLE_ABORTED_BY_CALLBACK;
       }
     }
index 00f3385440e5422120fb99be496fcc55ba8ac8d9..f84ac839f7846fc9263cffd54c640711536b95d8 100644 (file)
--- a/lib/ftp.c
+++ b/lib/ftp.c
@@ -3179,7 +3179,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
     conn->bits.ftp_use_control_ssl = TRUE;
   }
 
-  Curl_pp_init(pp, &data->progress.now); /* once per transfer */
+  Curl_pp_init(pp, Curl_pgrs_now(data)); /* once per transfer */
 
   /* When we connect, we start in the state where we await the 220
      response */
@@ -3315,7 +3315,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
      * data has been transferred. This happens when doing through NATs etc that
      * abandon old silent connections.
      */
-    pp->response = data->progress.now; /* timeout relative now */
+    pp->response = *Curl_pgrs_now(data); /* timeout relative now */
     result = getftpresponse(data, &nread, &ftpcode);
 
     if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) {
@@ -3435,7 +3435,7 @@ static CURLcode ftp_sendquote(struct Curl_easy *data,
 
       result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd);
       if(!result) {
-        pp->response = data->progress.now; /* timeout relative now */
+        pp->response = *Curl_pgrs_now(data); /* timeout relative now */
         result = getftpresponse(data, &nread, &ftpcode);
       }
       if(result)
index eb59193d2c412f672cb7b0bf8cc53181a66173ce..b18e5e0bd401bb3b0f37194217eed3364e9e5c4f 100644 (file)
@@ -57,6 +57,7 @@
 #include "multiif.h"
 #include "doh.h"
 #include "curlx/warnless.h"
+#include "progress.h"
 #include "select.h"
 #include "strcase.h"
 #include "easy_lock.h"
@@ -191,7 +192,7 @@ static int dnscache_entry_is_stale(void *datap, void *hc)
 
   if(dns->timestamp.tv_sec || dns->timestamp.tv_usec) {
     /* get age in milliseconds */
-    timediff_t age = curlx_timediff_ms(prune->now, dns->timestamp);
+    timediff_t age = curlx_ptimediff_ms(&prune->now, &dns->timestamp);
     if(!dns->addr)
       age *= 2; /* negative entries age twice as fast */
     if(age >= prune->max_age_ms)
@@ -265,7 +266,7 @@ void Curl_dnscache_prune(struct Curl_easy *data)
   do {
     /* Remove outdated and unused entries from the hostcache */
     timediff_t oldest_ms =
-      dnscache_prune(&dnscache->entries, timeout_ms, data->progress.now);
+      dnscache_prune(&dnscache->entries, timeout_ms, *Curl_pgrs_now(data));
 
     if(Curl_hash_count(&dnscache->entries) > MAX_DNS_CACHE_SIZE)
       /* prune the ones over half this age */
@@ -331,7 +332,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data,
     /* See whether the returned entry is stale. Done before we release lock */
     struct dnscache_prune_data user;
 
-    user.now = data->progress.now;
+    user.now = *Curl_pgrs_now(data);
     user.max_age_ms = data->set.dns_cache_timeout_ms;
     user.oldest_ms = 0;
 
@@ -520,7 +521,7 @@ Curl_dnscache_mk_entry(struct Curl_easy *data,
     dns->timestamp.tv_usec = 0; /* an entry that never goes stale */
   }
   else {
-    dns->timestamp = data->progress.now;
+    dns->timestamp = *Curl_pgrs_now(data);
   }
   dns->hostport = port;
   if(hostlen)
@@ -1136,8 +1137,8 @@ clean_up:
      the time we spent until now! */
   if(prev_alarm) {
     /* there was an alarm() set before us, now put it back */
-    timediff_t elapsed_secs = curlx_timediff_ms(data->progress.now,
-                                                data->conn->created) / 1000;
+    timediff_t elapsed_secs = curlx_ptimediff_ms(Curl_pgrs_now(data),
+                                                 &data->conn->created) / 1000;
 
     /* the alarm period is counted in even number of seconds */
     unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs);
index ea62219542ad3c28d33161695a0c022621ef6098..fce6c7ccb826e5e9dc0ff2dd250056e506ca6f36 100644 (file)
@@ -4980,7 +4980,7 @@ static CURLcode cr_exp100_read(struct Curl_easy *data,
     DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE, "
            "timeout %dms", data->set.expect_100_timeout));
     ctx->state = EXP100_AWAITING_CONTINUE;
-    ctx->start = data->progress.now;
+    ctx->start = *Curl_pgrs_now(data);
     Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
     *nread = 0;
     *eos = FALSE;
@@ -4991,7 +4991,7 @@ static CURLcode cr_exp100_read(struct Curl_easy *data,
     *eos = FALSE;
     return CURLE_READ_ERROR;
   case EXP100_AWAITING_CONTINUE:
-    ms = curlx_timediff_ms(data->progress.now, ctx->start);
+    ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->start);
     if(ms < data->set.expect_100_timeout) {
       DEBUGF(infof(data, "cr_exp100_read, AWAITING_CONTINUE, not expired"));
       *nread = 0;
index dc71f206901f5f87083eb8d645d2dc1f7eb42b90..d547cf4894f93233fe87bd1b638a062b48d74f21 100644 (file)
@@ -306,8 +306,8 @@ static void h2_stream_hash_free(unsigned int id, void *stream)
 static int32_t cf_h2_get_desired_local_win(struct Curl_cfilter *cf,
                                            struct Curl_easy *data)
 {
-  curl_off_t avail =
-    Curl_rlimit_avail(&data->progress.dl.rlimit, &data->progress.now);
+  curl_off_t avail = Curl_rlimit_avail(&data->progress.dl.rlimit,
+                                       Curl_pgrs_now(data));
 
   (void)cf;
   if(avail < CURL_OFF_T_MAX) { /* limit in place */
@@ -1424,7 +1424,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   struct Curl_cfilter *cf = userp;
   struct cf_h2_ctx *ctx = cf->ctx;
   struct h2_stream_ctx *stream;
-  struct Curl_easy *data_s, *calling = CF_DATA_CURRENT(cf);
+  struct Curl_easy *data_s;
   (void)flags;
 
   DEBUGASSERT(stream_id); /* should never be a zero stream ID here */
@@ -1445,8 +1445,6 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
   stream = H2_STREAM_CTX(ctx, data_s);
   if(!stream)
     return NGHTTP2_ERR_CALLBACK_FAILURE;
-  if(calling)
-    Curl_pgrs_now_update(data_s, calling);
 
   h2_xfer_write_resp(cf, data_s, stream, (const char *)mem, len, FALSE);
 
index 8b8bd9ca035a50f72fe3a7b71486024e16ba12ec..1547d9f7e94529fba751c145eacbb64b67b69ae0 100644 (file)
@@ -1994,7 +1994,7 @@ static CURLcode imap_setup_connection(struct Curl_easy *data,
   Curl_sasl_init(&imapc->sasl, data, &saslimap);
 
   curlx_dyn_init(&imapc->dyn, DYN_IMAP_CMD);
-  Curl_pp_init(pp, &data->progress.now);
+  Curl_pp_init(pp, Curl_pgrs_now(data));
 
   if(Curl_conn_meta_set(conn, CURL_META_IMAP_CONN, imapc, imap_conn_dtor))
     return CURLE_OUT_OF_MEMORY;
index bd6d25331d1b07ea3315ca6c24938934bb0db832..7587d373b6c4fa10aee58f4b2e018d8664c27497 100644 (file)
@@ -186,7 +186,7 @@ static CURLcode mqtt_send(struct Curl_easy *data,
   result = Curl_xfer_send(data, buf, len, FALSE, &n);
   if(result)
     return result;
-  mq->lastTime = data->progress.now;
+  mq->lastTime = *Curl_pgrs_now(data);
   Curl_debug(data, CURLINFO_HEADER_OUT, buf, n);
   if(len != n) {
     size_t nsend = len - n;
@@ -770,7 +770,7 @@ MQTT_SUBACK_COMING:
     }
 
     /* we received something */
-    mq->lastTime = data->progress.now;
+    mq->lastTime = *Curl_pgrs_now(data);
 
     /* if QoS is set, message contains packet id */
     result = Curl_client_write(data, CLIENTWRITE_BODY, buffer, nread);
@@ -800,7 +800,7 @@ static CURLcode mqtt_do(struct Curl_easy *data, bool *done)
 
   if(!mq)
     return CURLE_FAILED_INIT;
-  mq->lastTime = data->progress.now;
+  mq->lastTime = *Curl_pgrs_now(data);
   mq->pingsent = FALSE;
 
   result = mqtt_connect(data);
@@ -839,8 +839,8 @@ static CURLcode mqtt_ping(struct Curl_easy *data)
   if(mqtt->state == MQTT_FIRST &&
      !mq->pingsent &&
      data->set.upkeep_interval_ms > 0) {
-    struct curltime t = data->progress.now;
-    timediff_t diff = curlx_timediff_ms(t, mq->lastTime);
+    struct curltime t = *Curl_pgrs_now(data);
+    timediff_t diff = curlx_ptimediff_ms(&t, &mq->lastTime);
 
     if(diff > data->set.upkeep_interval_ms) {
       /* 0xC0 is PINGREQ, and 0x00 is remaining length */
@@ -898,7 +898,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done)
     Curl_debug(data, CURLINFO_HEADER_IN, (const char *)&mq->firstbyte, 1);
 
     /* we received something */
-    mq->lastTime = data->progress.now;
+    mq->lastTime = *Curl_pgrs_now(data);
 
     /* remember the first byte */
     mq->npacket = 0;
index 8d4c6c3da70292deb29c56daa0cb3cd960478854..289ab0714b3a6342d59fb4f327ddfa8ecc018ba5 100644 (file)
@@ -81,6 +81,7 @@
 
 #define CURL_MULTI_HANDLE 0x000bab1e
 
+
 #ifdef DEBUGBUILD
 /* On a debug build, we want to fail hard on multi handles that
  * are not NULL, but no longer have the MAGIC touch. This gives
 
 static void move_pending_to_connect(struct Curl_multi *multi,
                                     struct Curl_easy *data);
-static CURLMcode add_next_timeout(struct curltime now,
+static CURLMcode add_next_timeout(const struct curltime *pnow,
                                   struct Curl_multi *multi,
                                   struct Curl_easy *d);
 static void multi_timeout(struct Curl_multi *multi,
-                          struct curltime *pnow,
                           struct curltime *expire_time,
                           long *timeout_ms);
 static void process_pending_handles(struct Curl_multi *multi);
@@ -108,6 +108,12 @@ static void multi_xfer_bufs_free(struct Curl_multi *multi);
 static void multi_xfer_tbl_dump(struct Curl_multi *multi);
 #endif
 
+static const struct curltime *multi_now(struct Curl_multi *multi)
+{
+  curlx_pnow(&multi->now);
+  return &multi->now;
+}
+
 /* function pointer called once when switching TO a state */
 typedef void (*init_multistate_func)(struct Curl_easy *data);
 
@@ -167,7 +173,6 @@ static void mstate(struct Curl_easy *data, CURLMstate state
 #endif
 
   /* really switching state */
-  Curl_pgrs_now_set(data);
   data->mstate = state;
   switch(state) {
   case MSTATE_DONE:
@@ -449,7 +454,6 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
     Curl_uint32_bset_clear(&multi->msgsent);
   }
 
-  Curl_pgrs_now_set(data); /* start of API call */
   if(data->multi_easy) {
     /* if this easy handle was previously used for curl_easy_perform(), there
        is a private multi handle here that we can kill */
@@ -503,7 +507,7 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
 
   /* Necessary in event based processing, where dirty handles trigger
    * a timeout callback invocation. */
-  mresult = Curl_update_timer(multi, &data->progress.now);
+  mresult = Curl_update_timer(multi);
   if(mresult) {
     data->multi = NULL; /* not anymore */
     Curl_uint32_tbl_remove(&multi->xfers, data->mid);
@@ -784,7 +788,6 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
-  Curl_pgrs_now_set(data); /* start of API call */
   premature = (data->mstate < MSTATE_COMPLETED);
 
   /* If the 'state' is not INIT or COMPLETED, we might need to do something
@@ -883,7 +886,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d)
   process_pending_handles(multi);
 
   if(removed_timer) {
-    mresult = Curl_update_timer(multi, &data->progress.now);
+    mresult = Curl_update_timer(multi);
     if(mresult)
       return mresult;
   }
@@ -951,11 +954,11 @@ static CURLcode multi_adjust_pollset(struct Curl_easy *data,
   CURLcode result = CURLE_OK;
 
   if(ps->n) {
-    bool send_blocked =
-      (Curl_rlimit_avail(&data->progress.dl.rlimit, &data->progress.now) <= 0);
-    bool recv_blocked =
-      (Curl_rlimit_avail(&data->progress.ul.rlimit, &data->progress.now) <= 0);
+    const struct curltime *pnow = Curl_pgrs_now(data);
+    bool send_blocked, recv_blocked;
 
+    recv_blocked = (Curl_rlimit_avail(&data->progress.dl.rlimit, pnow) <= 0);
+    send_blocked = (Curl_rlimit_avail(&data->progress.ul.rlimit, pnow) <= 0);
     if(send_blocked || recv_blocked) {
       int i;
       for(i = 0; i <= SECONDARYSOCKET; ++i) {
@@ -1226,7 +1229,6 @@ CURLMcode curl_multi_fdset(CURLM *m,
   struct Curl_multi *multi = m;
   struct easy_pollset ps;
   unsigned int i, mid;
-  struct curltime now = curlx_now(); /* start of API call */
   (void)exc_fd_set;
 
   if(!GOOD_MULTI_HANDLE(multi))
@@ -1245,7 +1247,6 @@ CURLMcode curl_multi_fdset(CURLM *m,
         continue;
       }
 
-      Curl_pgrs_now_at_least(data, &now);
       Curl_multi_pollset(data, &ps);
       for(i = 0; i < ps.n; i++) {
         if(!FDSET_SOCK(ps.sockets[i]))
@@ -1287,7 +1288,6 @@ CURLMcode curl_multi_waitfds(CURLM *m,
   struct Curl_multi *multi = m;
   struct easy_pollset ps;
   unsigned int need = 0, mid;
-  struct curltime now = curlx_now(); /* start of API call */
 
   if(!ufds && (size || !fd_count))
     return CURLM_BAD_FUNCTION_ARGUMENT;
@@ -1309,7 +1309,6 @@ CURLMcode curl_multi_waitfds(CURLM *m,
         Curl_uint32_bset_remove(&multi->dirty, mid);
         continue;
       }
-      Curl_pgrs_now_at_least(data, &now);
       Curl_multi_pollset(data, &ps);
       need += Curl_waitfds_add_ps(&cwfds, &ps);
     } while(Curl_uint32_bset_next(&multi->process, mid, &mid));
@@ -1362,7 +1361,6 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
   unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */
   struct Curl_easy *data = NULL;
   CURLMcode mresult = CURLM_OK;
-  struct curltime now = curlx_now(); /* start of API call */
   uint32_t mid;
 
 #ifdef USE_WINSOCK
@@ -1395,13 +1393,11 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
         Curl_uint32_bset_remove(&multi->dirty, mid);
         continue;
       }
-      Curl_pgrs_now_at_least(data, &now);
       Curl_multi_pollset(data, &ps);
       if(Curl_pollfds_add_ps(&cpfds, &ps)) {
         mresult = CURLM_OUT_OF_MEMORY;
         goto out;
       }
-      now = data->progress.now;
     } while(Curl_uint32_bset_next(&multi->process, mid, &mid));
   }
 
@@ -1462,7 +1458,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
    * poll. Collecting the sockets may install new timers by protocols
    * and connection filters.
    * Use the shorter one of the internal and the caller requested timeout. */
-  multi_timeout(multi, &now, &expire_time, &timeout_internal);
+  multi_timeout(multi, &expire_time, &timeout_internal);
   if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
     timeout_ms = (int)timeout_internal;
 
@@ -1583,7 +1579,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
     long sleep_ms = 0;
 
     /* Avoid busy-looping when there is nothing particular to wait for */
-    multi_timeout(multi, &now, &expire_time, &sleep_ms);
+    multi_timeout(multi, &expire_time, &sleep_ms);
     if(sleep_ms) {
       if(sleep_ms > timeout_ms)
         sleep_ms = timeout_ms;
@@ -1780,8 +1776,9 @@ static bool multi_handle_timeout(struct Curl_easy *data,
                                  CURLcode *result)
 {
   bool connect_timeout = data->mstate < MSTATE_DO;
-  timediff_t timeout_ms =
-    Curl_timeleft_ms(data, connect_timeout);
+  timediff_t timeout_ms;
+
+  timeout_ms = Curl_timeleft_ms(data, connect_timeout);
   if(timeout_ms < 0) {
     /* Handle timed out */
     struct curltime since;
@@ -1791,23 +1788,26 @@ static bool multi_handle_timeout(struct Curl_easy *data,
       since = data->progress.t_startop;
     if(data->mstate == MSTATE_RESOLVING)
       failf(data, "Resolving timed out after %" FMT_TIMEDIFF_T
-            " milliseconds", curlx_timediff_ms(data->progress.now, since));
+            " milliseconds",
+            curlx_ptimediff_ms(Curl_pgrs_now(data), &since));
     else if(data->mstate == MSTATE_CONNECTING)
       failf(data, "Connection timed out after %" FMT_TIMEDIFF_T
-            " milliseconds", curlx_timediff_ms(data->progress.now, since));
+            " milliseconds",
+            curlx_ptimediff_ms(Curl_pgrs_now(data), &since));
     else {
       struct SingleRequest *k = &data->req;
       if(k->size != -1) {
         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
               " milliseconds with %" FMT_OFF_T " out of %"
               FMT_OFF_T " bytes received",
-              curlx_timediff_ms(data->progress.now, since),
+              curlx_ptimediff_ms(Curl_pgrs_now(data), &since),
               k->bytecount, k->size);
       }
       else {
         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
               " milliseconds with %" FMT_OFF_T " bytes received",
-              curlx_timediff_ms(data->progress.now, since), k->bytecount);
+              curlx_ptimediff_ms(Curl_pgrs_now(data), &since),
+              k->bytecount);
       }
     }
     *result = CURLE_OPERATION_TIMEDOUT;
@@ -1935,14 +1935,13 @@ static CURLcode multi_follow(struct Curl_easy *data,
 
 static CURLcode mspeed_check(struct Curl_easy *data)
 {
+  const struct curltime *pnow = Curl_pgrs_now(data);
   timediff_t recv_wait_ms = 0;
   timediff_t send_wait_ms = 0;
 
   /* check if our send/recv limits require idle waits */
-  send_wait_ms =
-    Curl_rlimit_wait_ms(&data->progress.ul.rlimit, &data->progress.now);
-  recv_wait_ms =
-    Curl_rlimit_wait_ms(&data->progress.dl.rlimit, &data->progress.now);
+  send_wait_ms = Curl_rlimit_wait_ms(&data->progress.ul.rlimit, pnow);
+  recv_wait_ms = Curl_rlimit_wait_ms(&data->progress.dl.rlimit, pnow);
 
   if(send_wait_ms || recv_wait_ms) {
     if(data->mstate != MSTATE_RATELIMITING) {
@@ -2765,11 +2764,10 @@ statemachine_end:
 }
 
 static CURLMcode multi_perform(struct Curl_multi *multi,
-                               struct curltime *pnow,
                                int *running_handles)
 {
   CURLMcode returncode = CURLM_OK;
-  struct Curl_tree *t = NULL;
+  struct curltime start = *multi_now(multi);
   uint32_t mid;
   SIGPIPE_VARIABLE(pipe_st);
 
@@ -2793,9 +2791,7 @@ static CURLMcode multi_perform(struct Curl_multi *multi,
         continue;
       }
       sigpipe_apply(data, &pipe_st);
-      Curl_pgrs_now_at_least(data, pnow);
       mresult = multi_runsingle(multi, data);
-      *pnow = data->progress.now; /* in case transfer updated */
       if(mresult)
         returncode = mresult;
     } while(Curl_uint32_bset_next(&multi->process, mid, &mid));
@@ -2818,22 +2814,25 @@ static CURLMcode multi_perform(struct Curl_multi *multi,
    * then and then we risk this loop to remove timers that actually have not
    * been handled!
    */
-  do {
-    multi->timetree = Curl_splaygetbest(*pnow, multi->timetree, &t);
-    if(t) {
-      /* the removed may have another timeout in queue */
-      struct Curl_easy *data = Curl_splayget(t);
-      (void)add_next_timeout(*pnow, multi, data);
-      if(data->mstate == MSTATE_PENDING) {
-        bool stream_unused;
-        CURLcode result_unused;
-        if(multi_handle_timeout(data, &stream_unused, &result_unused)) {
-          infof(data, "PENDING handle timeout");
-          move_pending_to_connect(multi, data);
+  if(multi->timetree) {
+    struct Curl_tree *t = NULL;
+    do {
+      multi->timetree = Curl_splaygetbest(&start, multi->timetree, &t);
+      if(t) {
+        /* the removed may have another timeout in queue */
+        struct Curl_easy *data = Curl_splayget(t);
+        (void)add_next_timeout(&start, multi, data);
+        if(data->mstate == MSTATE_PENDING) {
+          bool stream_unused;
+          CURLcode result_unused;
+          if(multi_handle_timeout(data, &stream_unused, &result_unused)) {
+            infof(data, "PENDING handle timeout");
+            move_pending_to_connect(multi, data);
+          }
         }
       }
-    }
-  } while(t);
+    } while(t);
+  }
 
   if(running_handles) {
     unsigned int running = Curl_multi_xfers_running(multi);
@@ -2841,20 +2840,19 @@ static CURLMcode multi_perform(struct Curl_multi *multi,
   }
 
   if(CURLM_OK >= returncode)
-    returncode = Curl_update_timer(multi, pnow);
+    returncode = Curl_update_timer(multi);
 
   return returncode;
 }
 
 CURLMcode curl_multi_perform(CURLM *m, int *running_handles)
 {
-  struct curltime now = curlx_now(); /* start of API call */
   struct Curl_multi *multi = m;
 
   if(!GOOD_MULTI_HANDLE(multi))
     return CURLM_BAD_HANDLE;
 
-  return multi_perform(multi, &now, running_handles);
+  return multi_perform(multi, running_handles);
 }
 
 CURLMcode curl_multi_cleanup(CURLM *m)
@@ -3015,7 +3013,7 @@ void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s)
  * The splay tree only has each sessionhandle as a single node and the nearest
  * timeout is used to sort it on.
  */
-static CURLMcode add_next_timeout(struct curltime now,
+static CURLMcode add_next_timeout(const struct curltime *pnow,
                                   struct Curl_multi *multi,
                                   struct Curl_easy *d)
 {
@@ -3029,7 +3027,7 @@ static CURLMcode add_next_timeout(struct curltime now,
   for(e = Curl_llist_head(list); e;) {
     struct Curl_llist_node *n = Curl_node_next(e);
     struct time_node *node = Curl_node_elem(e);
-    timediff_t diff = curlx_timediff_us(node->time, now);
+    timediff_t diff = curlx_ptimediff_us(&node->time, pnow);
     if(diff <= 0)
       /* remove outdated entry */
       Curl_node_remove(e);
@@ -3052,7 +3050,7 @@ static CURLMcode add_next_timeout(struct curltime now,
 
     /* Insert this node again into the splay. Keep the timer in the list in
        case we need to recompute future timers. */
-    multi->timetree = Curl_splayinsert(*tv, multi->timetree,
+    multi->timetree = Curl_splayinsert(tv, multi->timetree,
                                        &d->state.timenode);
   }
   return CURLM_OK;
@@ -3060,12 +3058,12 @@ static CURLMcode add_next_timeout(struct curltime now,
 
 struct multi_run_ctx {
   struct Curl_multi *multi;
-  struct curltime now;
   size_t run_xfers;
   SIGPIPE_MEMBER(pipe_st);
 };
 
-static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc)
+static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc,
+                                        const struct curltime *ts)
 {
   struct Curl_multi *multi = mrc->multi;
   struct Curl_easy *data = NULL;
@@ -3079,7 +3077,7 @@ static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc)
   while(1) {
     /* Check if there is one (more) expired timer to deal with! This function
        extracts a matching node if there is one */
-    multi->timetree = Curl_splaygetbest(mrc->now, multi->timetree, &t);
+    multi->timetree = Curl_splaygetbest(ts, multi->timetree, &t);
     if(!t)
       return;
 
@@ -3095,7 +3093,7 @@ static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc)
       }
     }
 #endif
-    (void)add_next_timeout(mrc->now, multi, data);
+    (void)add_next_timeout(ts, multi, data);
     Curl_multi_mark_dirty(data);
   }
 }
@@ -3121,9 +3119,7 @@ static CURLMcode multi_run_dirty(struct multi_run_ctx *mrc)
         mrc->run_xfers++;
         sigpipe_apply(data, &mrc->pipe_st);
         /* runsingle() clears the dirty mid */
-        Curl_pgrs_now_at_least(data, &mrc->now);
         mresult = multi_runsingle(multi, data);
-        mrc->now = data->progress.now; /* in case transfer updated */
 
         if(CURLM_OK >= mresult) {
           /* reassess event handling of data */
@@ -3155,17 +3151,15 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
   (void)ev_bitmask;
   memset(&mrc, 0, sizeof(mrc));
   mrc.multi = multi;
-  mrc.now = curlx_now(); /* start of API call */
   sigpipe_init(&mrc.pipe_st);
 
   if(checkall) {
     /* *perform() deals with running_handles on its own */
-    mresult = multi_perform(multi, &mrc.now, running_handles);
+    mresult = multi_perform(multi, running_handles);
 
     if(mresult != CURLM_BAD_HANDLE) {
       /* Reassess event status of all active transfers */
-      mresult = Curl_multi_ev_assess_xfer_bset(multi, &multi->process,
-                                              &mrc.now);
+      mresult = Curl_multi_ev_assess_xfer_bset(multi, &multi->process);
     }
     goto out;
   }
@@ -3183,7 +3177,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
     memset(&multi->last_expire_ts, 0, sizeof(multi->last_expire_ts));
   }
 
-  multi_mark_expired_as_dirty(&mrc);
+  multi_mark_expired_as_dirty(&mrc, multi_now(multi));
   mresult = multi_run_dirty(&mrc);
   if(mresult)
     goto out;
@@ -3194,7 +3188,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
      * to set a 0 timeout and call us again, we run them here.
      * Do that only once or it might be unfair to transfers on other
      * sockets. */
-    multi_mark_expired_as_dirty(&mrc);
+    multi_mark_expired_as_dirty(&mrc, &multi->now);
     mresult = multi_run_dirty(&mrc);
   }
 
@@ -3213,7 +3207,7 @@ out:
   }
 
   if(CURLM_OK >= mresult)
-    mresult = Curl_update_timer(multi, &mrc.now);
+    mresult = Curl_update_timer(multi);
   return mresult;
 }
 
@@ -3366,7 +3360,6 @@ static bool multi_has_dirties(struct Curl_multi *multi)
 }
 
 static void multi_timeout(struct Curl_multi *multi,
-                          struct curltime *pnow,
                           struct curltime *expire_time,
                           long *timeout_ms)
 {
@@ -3381,13 +3374,14 @@ static void multi_timeout(struct Curl_multi *multi,
   }
 
   if(multi_has_dirties(multi)) {
-    *expire_time = *pnow;
+    *expire_time = *multi_now(multi);
     *timeout_ms = 0;
     return;
   }
   else if(multi->timetree) {
+    const struct curltime *pnow = multi_now(multi);
     /* splay the lowest to the bottom */
-    multi->timetree = Curl_splay(tv_zero, multi->timetree);
+    multi->timetree = Curl_splay(&tv_zero, multi->timetree);
     /* this will not return NULL from a non-empty tree, but some compilers
      * are not convinced of that. Analyzers are hard. */
     *expire_time = multi->timetree ? multi->timetree->key : tv_zero;
@@ -3395,9 +3389,10 @@ static void multi_timeout(struct Curl_multi *multi,
     /* 'multi->timetree' will be non-NULL here but the compilers sometimes
        yell at us if we assume so */
     if(multi->timetree &&
-       curlx_timediff_us(multi->timetree->key, *pnow) > 0) {
+       curlx_ptimediff_us(&multi->timetree->key, pnow) > 0) {
       /* some time left before expiration */
-      timediff_t diff_ms = curlx_timediff_ceil_ms(multi->timetree->key, *pnow);
+      timediff_t diff_ms =
+        curlx_timediff_ceil_ms(multi->timetree->key, *pnow);
 #ifndef CURL_DISABLE_VERBOSE_STRINGS
       data = Curl_splayget(multi->timetree);
 #endif
@@ -3437,7 +3432,6 @@ CURLMcode curl_multi_timeout(CURLM *m,
 {
   struct curltime expire_time;
   struct Curl_multi *multi = m;
-  struct curltime now = curlx_now(); /* start of API call */
 
   /* First, make some basic checks that the CURLM handle is a good handle */
   if(!GOOD_MULTI_HANDLE(multi))
@@ -3446,7 +3440,7 @@ CURLMcode curl_multi_timeout(CURLM *m,
   if(multi->in_callback)
     return CURLM_RECURSIVE_API_CALL;
 
-  multi_timeout(multi, &now, &expire_time, timeout_ms);
+  multi_timeout(multi, &expire_time, timeout_ms);
   return CURLM_OK;
 }
 
@@ -3454,8 +3448,7 @@ CURLMcode curl_multi_timeout(CURLM *m,
  * Tell the application it should update its timers, if it subscribes to the
  * update timer callback.
  */
-CURLMcode Curl_update_timer(struct Curl_multi *multi,
-                            struct curltime *pnow)
+CURLMcode Curl_update_timer(struct Curl_multi *multi)
 {
   struct curltime expire_ts;
   long timeout_ms;
@@ -3464,7 +3457,7 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi,
 
   if(!multi->timer_cb || multi->dead)
     return CURLM_OK;
-  multi_timeout(multi, pnow, &expire_ts, &timeout_ms);
+  multi_timeout(multi, &expire_ts, &timeout_ms);
 
   if(timeout_ms < 0 && multi->last_timeout_ms < 0) {
     /* nothing to do */
@@ -3479,7 +3472,7 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi,
     CURL_TRC_M(multi->admin, "[TIMER] set %ldms, none before", timeout_ms);
     set_value = TRUE;
   }
-  else if(curlx_timediff_us(multi->last_expire_ts, expire_ts)) {
+  else if(curlx_ptimediff_us(&multi->last_expire_ts, &expire_ts)) {
     /* We had a timeout before and have one now, the absolute timestamp
      * differs. The relative timeout_ms may be the same, but the starting
      * point differs. Let the application restart its timer. */
@@ -3535,8 +3528,7 @@ static void multi_deltimeout(struct Curl_easy *data, expire_id eid)
  */
 static CURLMcode multi_addtimeout(struct Curl_easy *data,
                                   struct curltime *stamp,
-                                  expire_id eid,
-                                  const struct curltime *nowp)
+                                  expire_id eid)
 {
   struct Curl_llist_node *e;
   struct time_node *node;
@@ -3544,7 +3536,6 @@ static CURLMcode multi_addtimeout(struct Curl_easy *data,
   size_t n;
   struct Curl_llist *timeoutlist = &data->state.timeoutlist;
 
-  (void)nowp;
   node = &data->state.expires[eid];
 
   /* copy the timestamp and id */
@@ -3556,7 +3547,7 @@ static CURLMcode multi_addtimeout(struct Curl_easy *data,
     /* find the correct spot in the list */
     for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) {
       struct time_node *check = Curl_node_elem(e);
-      timediff_t diff = curlx_timediff_ms(check->time, node->time);
+      timediff_t diff = curlx_ptimediff_ms(&check->time, &node->time);
       if(diff > 0)
         break;
       prev = e;
@@ -3567,7 +3558,7 @@ static CURLMcode multi_addtimeout(struct Curl_easy *data,
 
   Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
   CURL_TRC_TIMER(data, eid, "set for %" FMT_TIMEDIFF_T "ns",
-                 curlx_timediff_us(node->time, *nowp));
+                 curlx_ptimediff_us(&node->time, Curl_pgrs_now(data)));
   return CURLM_OK;
 }
 
@@ -3585,7 +3576,7 @@ void Curl_expire_ex(struct Curl_easy *data,
 
   DEBUGASSERT(id < EXPIRE_LAST);
 
-  set = data->progress.now;
+  set = *Curl_pgrs_now(data);
   set.tv_sec += (time_t)(milli / 1000); /* may be a 64 to 32-bit conversion */
   set.tv_usec += (int)(milli % 1000) * 1000;
 
@@ -3599,13 +3590,13 @@ void Curl_expire_ex(struct Curl_easy *data,
 
   /* Add it to the timer list. It must stay in the list until it has expired
      in case we need to recompute the minimum timer later. */
-  multi_addtimeout(data, &set, id, &data->progress.now);
+  multi_addtimeout(data, &set, id);
 
   if(curr_expire->tv_sec || curr_expire->tv_usec) {
     /* This means that the struct is added as a node in the splay tree.
        Compare if the new time is earlier, and only remove-old/add-new if it
        is. */
-    timediff_t diff = curlx_timediff_ms(set, *curr_expire);
+    timediff_t diff = curlx_ptimediff_ms(&set, curr_expire);
     int rc;
 
     if(diff > 0) {
@@ -3626,7 +3617,7 @@ void Curl_expire_ex(struct Curl_easy *data,
      value since it is our local minimum. */
   *curr_expire = set;
   Curl_splayset(&data->state.timenode, data);
-  multi->timetree = Curl_splayinsert(*curr_expire, multi->timetree,
+  multi->timetree = Curl_splayinsert(curr_expire, multi->timetree,
                                      &data->state.timenode);
 }
 
index 85e2bd6c60dfd84cc288ec2c0a7f07e862eb719e..906b1c718367d9b0e279321ed82a162c9d2f8a5b 100644 (file)
@@ -538,8 +538,7 @@ CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi,
 }
 
 CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi,
-                                         struct uint32_bset *set,
-                                         struct curltime *pnow)
+                                         struct uint32_bset *set)
 {
   uint32_t mid;
   CURLMcode mresult = CURLM_OK;
@@ -548,7 +547,6 @@ CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi,
     do {
       struct Curl_easy *data = Curl_multi_get_easy(multi, mid);
       if(data) {
-        Curl_pgrs_now_at_least(data, pnow);
         mresult = Curl_multi_ev_assess_xfer(multi, data);
       }
     } while(!mresult && Curl_uint32_bset_next(set, mid, &mid));
index d9794ed86529e22e5fdd985c2517d92690c3ffaa..4e5b2a454d2670950a01ae538a9ea56bf3504988 100644 (file)
@@ -55,8 +55,7 @@ CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi,
                                     struct Curl_easy *data);
 /* Assess all easy handles on the list */
 CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi,
-                                         struct uint32_bset *set,
-                                         struct curltime *pnow);
+                                         struct uint32_bset *set);
 /* Assess the connection by getting its current pollset */
 CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi,
                                     struct Curl_easy *data,
index d71958c414f281a047763c7c2ea66e0f33a51d17..2bf06322a8990a090eb851bf49b39d3c19d51002 100644 (file)
@@ -116,6 +116,8 @@ struct Curl_multi {
   struct PslCache psl;
 #endif
 
+  /* current time for transfers running in this multi handle */
+  struct curltime now;
   /* timetree points to the splay-tree of time nodes to figure out expire
      times of all currently set timers */
   struct Curl_tree *timetree;
@@ -170,6 +172,9 @@ struct Curl_multi {
   unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of
                                entries we are allowed to grow the connection
                                cache to */
+#ifdef DEBUGBUILD
+  unsigned int now_access_count;
+#endif
 #define IPV6_UNKNOWN 0
 #define IPV6_DEAD    1
 #define IPV6_WORKS   2
index 42651c5150c23cbc9e108e3e6aa58603935826b7..f4dc24a3e97a44829a1a4525e4661a26f00b4c8f 100644 (file)
@@ -33,8 +33,7 @@ void Curl_expire_ex(struct Curl_easy *data,
                     timediff_t milli, expire_id id);
 bool Curl_expire_clear(struct Curl_easy *data);
 void Curl_expire_done(struct Curl_easy *data, expire_id id);
-CURLMcode Curl_update_timer(struct Curl_multi *multi,
-                            struct curltime *pnow) WARN_UNUSED_RESULT;
+CURLMcode Curl_update_timer(struct Curl_multi *multi) WARN_UNUSED_RESULT;
 void Curl_attach_connection(struct Curl_easy *data,
                             struct connectdata *conn);
 void Curl_detach_connection(struct Curl_easy *data);
@@ -163,4 +162,6 @@ void Curl_multi_mark_dirty(struct Curl_easy *data);
 /* Clear transfer from the dirty set. */
 void Curl_multi_clear_dirty(struct Curl_easy *data);
 
+void Curl_multi_set_now(struct Curl_multi *multi);
+
 #endif /* HEADER_CURL_MULTIIF_H */
index fcfd991d81538edd2955eaf4be22c8b4cb01565a..6c64164e48623170c39ece6ef4c0cb8d7eb6c04d 100644 (file)
@@ -53,14 +53,10 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data,
      supposed to govern the response for any given server response, not for
      the time from connect to the given server response. */
 
-  /* pingpong can spend some time processing, always update
-   * the transfer timestamp before checking timeouts. */
-  Curl_pgrs_now_set(data);
-
   /* Without a requested timeout, we only wait 'response_time' seconds for the
      full response to arrive before we bail out */
   timeout_ms = response_time -
-               curlx_timediff_ms(data->progress.now, pp->response);
+               curlx_ptimediff_ms(Curl_pgrs_now(data), &pp->response);
 
   if(data->set.timeout && !disconnecting) {
     /* if timeout is requested, find out how much overall remains */
@@ -139,7 +135,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
 }
 
 /* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct pingpong *pp, struct curltime *pnow)
+void Curl_pp_init(struct pingpong *pp, const struct curltime *pnow)
 {
   DEBUGASSERT(!pp->initialised);
   pp->nread_resp = 0;
@@ -212,7 +208,7 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data,
   else {
     pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
-    pp->response = data->progress.now;
+    pp->response = *Curl_pgrs_now(data);
   }
 
   return CURLE_OK;
@@ -403,7 +399,7 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data,
   else {
     pp->sendthis = NULL;
     pp->sendleft = pp->sendsize = 0;
-    pp->response = data->progress.now;
+    pp->response = *Curl_pgrs_now(data);
   }
   return CURLE_OK;
 }
index a41d76308cbe2bccae20fe0c4d8ae70b88f39607..b3780571c480e5a503e15155e09a1f0cdedb3ee3 100644 (file)
@@ -87,7 +87,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data, struct pingpong *pp,
                            bool block, bool disconnecting);
 
 /* initialize stuff to prepare for reading a fresh new response */
-void Curl_pp_init(struct pingpong *pp, struct curltime *pnow);
+void Curl_pp_init(struct pingpong *pp, const struct curltime *pnow);
 
 /* Returns timeout in ms. 0 or negative number means the timeout has already
    triggered */
index 1fd22116c5a4b7dd86746e19c2ffde39ddbb386c..478dd7bc19225ec8e4db3e40ee6b800cd3809a7d 100644 (file)
@@ -1297,7 +1297,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done)
   Curl_sasl_init(&pop3c->sasl, data, &saslpop3);
 
   /* Initialise the pingpong layer */
-  Curl_pp_init(pp, &data->progress.now);
+  Curl_pp_init(pp, Curl_pgrs_now(data));
 
   /* Parse the URL options */
   result = pop3_parse_url_options(conn);
index e11a1ff82fa32d8d0a533bf653912baa08531938..ed842cefcdda0f712566cebfb80698a443a81f9a 100644 (file)
@@ -102,7 +102,7 @@ static void pgrs_speedinit(struct Curl_easy *data)
  * @unittest: 1606
  */
 UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data,
-                                  struct curltime *pnow)
+                                  const struct curltime *pnow)
 {
   if(!data->set.low_speed_time || !data->set.low_speed_limit ||
      Curl_xfer_recv_is_paused(data) || Curl_xfer_send_is_paused(data))
@@ -116,7 +116,8 @@ UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data,
         data->state.keeps_speed = *pnow;
       else {
         /* how long has it been under the limit */
-        timediff_t howlong = curlx_timediff_ms(*pnow, data->state.keeps_speed);
+        timediff_t howlong =
+          curlx_ptimediff_ms(pnow, &data->state.keeps_speed);
 
         if(howlong >= data->set.low_speed_time * 1000) {
           /* too long */
@@ -141,23 +142,12 @@ UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data,
   return CURLE_OK;
 }
 
-void Curl_pgrs_now_set(struct Curl_easy *data)
+const struct curltime *Curl_pgrs_now(struct Curl_easy *data)
 {
-  data->progress.now = curlx_now();
-}
-
-void Curl_pgrs_now_at_least(struct Curl_easy *data, struct curltime *pts)
-{
-  if((pts->tv_sec > data->progress.now.tv_sec) ||
-     ((pts->tv_sec == data->progress.now.tv_sec) &&
-      (pts->tv_usec > data->progress.now.tv_usec))) {
-    data->progress.now = *pts;
-  }
-}
-
-void Curl_pgrs_now_update(struct Curl_easy *data, struct Curl_easy *other)
-{
-  Curl_pgrs_now_at_least(data, &other->progress.now);
+  struct curltime *pnow = data->multi ?
+                          &data->multi->now : &data->progress.now;
+  curlx_pnow(pnow);
+  return pnow;
 }
 
 /*
@@ -251,7 +241,7 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
   case TIMER_POSTQUEUE:
     /* Queue time is accumulative from all involved redirects */
     data->progress.t_postqueue +=
-      curlx_timediff_us(timestamp, data->progress.t_startqueue);
+      curlx_ptimediff_us(&timestamp, &data->progress.t_startqueue);
     break;
   case TIMER_STARTACCEPT:
     data->progress.t_acceptdata = timestamp;
@@ -287,13 +277,14 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
     delta = &data->progress.t_posttransfer;
     break;
   case TIMER_REDIRECT:
-    data->progress.t_redirect = curlx_timediff_us(timestamp,
-                                                 data->progress.start);
+    data->progress.t_redirect = curlx_ptimediff_us(&timestamp,
+                                                   &data->progress.start);
     data->progress.t_startqueue = timestamp;
     break;
   }
   if(delta) {
-    timediff_t us = curlx_timediff_us(timestamp, data->progress.t_startsingle);
+    timediff_t us = curlx_ptimediff_us(&timestamp,
+                                       &data->progress.t_startsingle);
     if(us < 1)
       us = 1; /* make sure at least one microsecond passed */
     *delta += us;
@@ -309,15 +300,15 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer,
  */
 void Curl_pgrsTime(struct Curl_easy *data, timerid timer)
 {
-  Curl_pgrs_now_set(data); /* update on real progress */
-  Curl_pgrsTimeWas(data, timer, data->progress.now);
+  Curl_pgrsTimeWas(data, timer, *Curl_pgrs_now(data));
 }
 
 void Curl_pgrsStartNow(struct Curl_easy *data)
 {
   struct Progress *p = &data->progress;
+
   p->speeder_c = 0; /* reset the progress meter display */
-  p->start = data->progress.now;
+  p->start = *Curl_pgrs_now(data);
   p->is_t_startransfer_set = FALSE;
   p->dl.cur_size = 0;
   p->ul.cur_size = 0;
@@ -330,7 +321,7 @@ void Curl_pgrs_download_inc(struct Curl_easy *data, size_t delta)
 {
   if(delta) {
     data->progress.dl.cur_size += delta;
-    Curl_rlimit_drain(&data->progress.dl.rlimit, delta, &data->progress.now);
+    Curl_rlimit_drain(&data->progress.dl.rlimit, delta, Curl_pgrs_now(data));
   }
 }
 
@@ -338,7 +329,7 @@ void Curl_pgrs_upload_inc(struct Curl_easy *data, size_t delta)
 {
   if(delta) {
     data->progress.ul.cur_size += delta;
-    Curl_rlimit_drain(&data->progress.ul.rlimit, delta, &data->progress.now);
+    Curl_rlimit_drain(&data->progress.ul.rlimit, delta, Curl_pgrs_now(data));
   }
 }
 
@@ -394,7 +385,8 @@ static curl_off_t trspeed(curl_off_t size, /* number of bytes */
 }
 
 /* returns TRUE if it is time to show the progress meter */
-static bool progress_calc(struct Curl_easy *data, struct curltime *pnow)
+static bool progress_calc(struct Curl_easy *data,
+                          const struct curltime *pnow)
 {
   struct Progress * const p = &data->progress;
   int i_next, i_oldest, i_latest;
@@ -402,7 +394,7 @@ static bool progress_calc(struct Curl_easy *data, struct curltime *pnow)
   curl_off_t amount;
 
   /* The time spent so far (from the start) in microseconds */
-  p->timespent = curlx_timediff_us(*pnow, p->start);
+  p->timespent = curlx_ptimediff_us(pnow, &p->start);
   p->dl.speed = trspeed(p->dl.cur_size, p->timespent);
   p->ul.speed = trspeed(p->ul.cur_size, p->timespent);
 
@@ -422,7 +414,7 @@ static bool progress_calc(struct Curl_easy *data, struct curltime *pnow)
 
   /* Make a new record only when some time has passed.
    * Too frequent calls otherwise ruin the history. */
-  if(curlx_timediff_ms(*pnow, p->speed_time[i_latest]) >= 1000) {
+  if(curlx_ptimediff_ms(pnow, &p->speed_time[i_latest]) >= 1000) {
     p->speeder_c++;
     i_latest = i_next;
     p->speed_amount[i_latest] = p->dl.cur_size + p->ul.cur_size;
@@ -449,8 +441,8 @@ static bool progress_calc(struct Curl_easy *data, struct curltime *pnow)
   /* How much we transferred between oldest and current records */
   amount = p->speed_amount[i_latest] - p->speed_amount[i_oldest];
   /* How long this took */
-  duration_ms = curlx_timediff_ms(p->speed_time[i_latest],
-                                  p->speed_time[i_oldest]);
+  duration_ms = curlx_ptimediff_ms(&p->speed_time[i_latest],
+                                   &p->speed_time[i_oldest]);
   if(duration_ms <= 0)
     duration_ms = 1;
 
@@ -635,7 +627,8 @@ static CURLcode pgrsupdate(struct Curl_easy *data, bool showprogress)
   return CURLE_OK;
 }
 
-static CURLcode pgrs_update(struct Curl_easy *data, struct curltime *pnow)
+static CURLcode pgrs_update(struct Curl_easy *data,
+                            const struct curltime *pnow)
 {
   bool showprogress = progress_calc(data, pnow);
   return pgrsupdate(data, showprogress);
@@ -643,16 +636,16 @@ static CURLcode pgrs_update(struct Curl_easy *data, struct curltime *pnow)
 
 CURLcode Curl_pgrsUpdate(struct Curl_easy *data)
 {
-  return pgrs_update(data, &data->progress.now);
+  return pgrs_update(data, Curl_pgrs_now(data));
 }
 
 CURLcode Curl_pgrsCheck(struct Curl_easy *data)
 {
   CURLcode result;
 
-  result = pgrs_update(data, &data->progress.now);
+  result = pgrs_update(data, Curl_pgrs_now(data));
   if(!result && !data->req.done)
-    result = pgrs_speedcheck(data, &data->progress.now);
+    result = pgrs_speedcheck(data, Curl_pgrs_now(data));
   return result;
 }
 
@@ -661,5 +654,5 @@ CURLcode Curl_pgrsCheck(struct Curl_easy *data)
  */
 void Curl_pgrsUpdate_nometer(struct Curl_easy *data)
 {
-  (void)progress_calc(data, &data->progress.now);
+  (void)progress_calc(data, Curl_pgrs_now(data));
 }
index 2154ff60bdfa760bba3b132bf6d70ec6fce767e9..f368c2475ef937df6c9ea75fc5185ed9a0fcfd87 100644 (file)
@@ -44,16 +44,8 @@ typedef enum {
   TIMER_LAST /* must be last */
 } timerid;
 
-#define CURL_PGRS_NOW_MONOTONIC
-
-/* Set current time in data->progress.now */
-void Curl_pgrs_now_set(struct Curl_easy *data);
-/* Advance `now` timestamp at least to given timestamp.
- * No effect it data's `now` is already later than `pts`. */
-void Curl_pgrs_now_at_least(struct Curl_easy *data, struct curltime *pts);
-/* `data` progressing continues after `other` processing. Advance `data`s
- * now timestamp to at least `other's` timestamp. */
-void Curl_pgrs_now_update(struct Curl_easy *data, struct Curl_easy *other);
+/* Get the current timestamp of the transfer */
+const struct curltime *Curl_pgrs_now(struct Curl_easy *data);
 
 int Curl_pgrsDone(struct Curl_easy *data);
 void Curl_pgrsStartNow(struct Curl_easy *data);
@@ -93,7 +85,7 @@ void Curl_pgrsEarlyData(struct Curl_easy *data, curl_off_t sent);
 
 #ifdef UNITTESTS
 UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data,
-                                  struct curltime *pnow);
+                                  const struct curltime *pnow);
 #endif
 
 #endif /* HEADER_CURL_PROGRESS_H */
index 0be51e44020a690cb72cef2992c39c8a33be1fd6..a089402eced45ce2670f0b0374d3316bbf9eaec2 100644 (file)
--- a/lib/psl.c
+++ b/lib/psl.c
@@ -29,6 +29,7 @@
 #ifdef USE_LIBPSL
 
 #include "psl.h"
+#include "progress.h"
 #include "curl_share.h"
 
 void Curl_psl_destroy(struct PslCache *pslcache)
@@ -41,25 +42,18 @@ void Curl_psl_destroy(struct PslCache *pslcache)
   }
 }
 
-static time_t now_seconds(void)
-{
-  struct curltime now = curlx_now();
-
-  return now.tv_sec;
-}
-
 const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy)
 {
   struct PslCache *pslcache = easy->psl;
   const psl_ctx_t *psl;
-  time_t now;
+  time_t now_sec;
 
   if(!pslcache)
     return NULL;
 
   Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED);
-  now = now_seconds();
-  if(!pslcache->psl || pslcache->expires <= now) {
+  now_sec = Curl_pgrs_now(easy)->tv_sec;
+  if(!pslcache->psl || pslcache->expires <= now_sec) {
     /* Let a chance to other threads to do the job: avoids deadlock. */
     Curl_share_unlock(easy, CURL_LOCK_DATA_PSL);
 
@@ -67,8 +61,10 @@ const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy)
     Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE);
 
     /* Recheck in case another thread did the job. */
-    now = now_seconds();
-    if(!pslcache->psl || pslcache->expires <= now) {
+    if(pslcache->expires <= now_sec) {
+      now_sec = Curl_pgrs_now(easy)->tv_sec;
+    }
+    if(!pslcache->psl || pslcache->expires <= now_sec) {
       bool dynamic = FALSE;
       time_t expires = TIME_T_MAX;
 
@@ -76,7 +72,8 @@ const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy)
       psl = psl_latest(NULL);
       dynamic = psl != NULL;
       /* Take care of possible time computation overflow. */
-      expires = now < TIME_T_MAX - PSL_TTL ? now + PSL_TTL : TIME_T_MAX;
+      expires = (now_sec < TIME_T_MAX - PSL_TTL) ?
+                (now_sec + PSL_TTL) : TIME_T_MAX;
 
       /* Only get the built-in PSL if we do not already have the "latest". */
       if(!psl && !pslcache->dynamic)
index 88324e918ae9c4aea1abc00c4163fbe99ae18b3d..a5694233fcbdac1ac1faa20e899eb6d19aaf9a44 100644 (file)
@@ -119,7 +119,8 @@ static CURLcode weak_random(struct Curl_easy *data,
     static bool seeded = FALSE;
     unsigned int rnd;
     if(!seeded) {
-      struct curltime now = curlx_now();
+      struct curltime now;
+      curlx_pnow(&now);
       randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
       randseed = randseed * 1103515245 + 12345;
       randseed = randseed * 1103515245 + 12345;
index 5c2e005133138fab4d400d3e7b3f76c1c4077c97..dc1a545201089c899d08f8c091681cec79ecc271 100644 (file)
@@ -25,6 +25,7 @@
 #include "curl_setup.h"
 
 #include "curlx/timeval.h"
+#include "progress.h"
 #include "ratelimit.h"
 
 
@@ -35,7 +36,7 @@
 void Curl_rlimit_init(struct Curl_rlimit *r,
                       curl_off_t rate_per_s,
                       curl_off_t burst_per_s,
-                      struct curltime *pts)
+                      const struct curltime *pts)
 {
   curl_off_t rate_steps;
 
@@ -62,7 +63,7 @@ void Curl_rlimit_init(struct Curl_rlimit *r,
   r->blocked = FALSE;
 }
 
-void Curl_rlimit_start(struct Curl_rlimit *r, struct curltime *pts)
+void Curl_rlimit_start(struct Curl_rlimit *r, const struct curltime *pts)
 {
   r->tokens = r->rate_per_step;
   r->spare_us = 0;
@@ -80,7 +81,7 @@ bool Curl_rlimit_is_blocked(struct Curl_rlimit *r)
 }
 
 static void ratelimit_update(struct Curl_rlimit *r,
-                             struct curltime *pts)
+                             const struct curltime *pts)
 {
   timediff_t elapsed_us, elapsed_steps;
   curl_off_t token_gain;
@@ -89,7 +90,7 @@ static void ratelimit_update(struct Curl_rlimit *r,
   if((r->ts.tv_sec == pts->tv_sec) && (r->ts.tv_usec == pts->tv_usec))
     return;
 
-  elapsed_us = curlx_timediff_us(*pts, r->ts);
+  elapsed_us = curlx_ptimediff_us(pts, &r->ts);
   if(elapsed_us < 0) { /* not going back in time */
     DEBUGASSERT(0);
     return;
@@ -120,7 +121,7 @@ static void ratelimit_update(struct Curl_rlimit *r,
 }
 
 curl_off_t Curl_rlimit_avail(struct Curl_rlimit *r,
-                             struct curltime *pts)
+                             const struct curltime *pts)
 {
   if(r->blocked)
     return 0;
@@ -134,7 +135,7 @@ curl_off_t Curl_rlimit_avail(struct Curl_rlimit *r,
 
 void Curl_rlimit_drain(struct Curl_rlimit *r,
                        size_t tokens,
-                       struct curltime *pts)
+                       const struct curltime *pts)
 {
   if(r->blocked || !r->rate_per_step)
     return;
@@ -157,7 +158,7 @@ void Curl_rlimit_drain(struct Curl_rlimit *r,
 }
 
 timediff_t Curl_rlimit_wait_ms(struct Curl_rlimit *r,
-                               struct curltime *pts)
+                               const struct curltime *pts)
 {
   timediff_t wait_us, elapsed_us;
 
@@ -172,7 +173,7 @@ timediff_t Curl_rlimit_wait_ms(struct Curl_rlimit *r,
   wait_us = (1 + (-r->tokens / r->rate_per_step)) * r->step_us;
   wait_us -= r->spare_us;
 
-  elapsed_us = curlx_timediff_us(*pts, r->ts);
+  elapsed_us = curlx_ptimediff_us(pts, &r->ts);
   if(elapsed_us >= wait_us)
     return 0;
   wait_us -= elapsed_us;
@@ -181,7 +182,7 @@ timediff_t Curl_rlimit_wait_ms(struct Curl_rlimit *r,
 
 void Curl_rlimit_block(struct Curl_rlimit *r,
                        bool activate,
-                       struct curltime *pts)
+                       const struct curltime *pts)
 {
   if(!activate == !r->blocked)
     return;
index b5a7c56fce48798161fb1f9174388b10268844a4..aa576451263c702b27c06bd5bd89a47f68326fa0 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "curlx/timeval.h"
 
+struct Curl_easy;
+
 /* This is a rate limiter that provides "tokens" to be consumed
  * per second with a "burst" rate limitation. Example:
  * A rate limit of 1 megabyte per second with a burst rate of 1.5MB.
@@ -62,14 +64,14 @@ struct Curl_rlimit {
 void Curl_rlimit_init(struct Curl_rlimit *r,
                       curl_off_t rate_per_s,
                       curl_off_t burst_per_s,
-                      struct curltime *pts);
+                      const struct curltime *pts);
 
 /* Start ratelimiting with the given timestamp. Resets available tokens. */
-void Curl_rlimit_start(struct Curl_rlimit *r, struct curltime *pts);
+void Curl_rlimit_start(struct Curl_rlimit *r, const struct curltime *pts);
 
 /* How many milliseconds to wait until token are available again. */
 timediff_t Curl_rlimit_wait_ms(struct Curl_rlimit *r,
-                               struct curltime *pts);
+                               const struct curltime *pts);
 
 /* Return if rate limiting of tokens is active */
 bool Curl_rlimit_active(struct Curl_rlimit *r);
@@ -77,16 +79,16 @@ bool Curl_rlimit_is_blocked(struct Curl_rlimit *r);
 
 /* Return how many tokens are available to spend, may be negative */
 curl_off_t Curl_rlimit_avail(struct Curl_rlimit *r,
-                             struct curltime *pts);
+                             const struct curltime *pts);
 
 /* Drain tokens from the ratelimit, return how many are now available. */
 void Curl_rlimit_drain(struct Curl_rlimit *r,
                        size_t tokens,
-                       struct curltime *pts);
+                       const struct curltime *pts);
 
 /* Block/unblock ratelimiting. A blocked ratelimit has 0 tokens available. */
 void Curl_rlimit_block(struct Curl_rlimit *r,
                        bool activate,
-                       struct curltime *pts);
+                       const struct curltime *pts);
 
 #endif /* HEADER_Curl_rlimit_H */
index 03dde6ab6d62a3785b769e3afd1f6a957c3659c0..8d5144f61069887f22fcbe22c15d4c673bf381ad 100644 (file)
@@ -90,7 +90,7 @@ CURLcode Curl_req_soft_reset(struct SingleRequest *req,
 CURLcode Curl_req_start(struct SingleRequest *req,
                         struct Curl_easy *data)
 {
-  req->start = data->progress.now;
+  req->start = *Curl_pgrs_now(data);
   return Curl_req_soft_reset(req, data);
 }
 
index c236d558e627a70bfdcbe076638d25ddd38a8cbd..7ab6af8b69dc041a96c1c741681d72bbacaa5af6 100644 (file)
@@ -230,7 +230,7 @@ static CURLcode cw_download_write(struct Curl_easy *data,
   if(!ctx->started_response &&
      !(type & (CLIENTWRITE_INFO | CLIENTWRITE_CONNECT))) {
     Curl_pgrsTime(data, TIMER_STARTTRANSFER);
-    Curl_rlimit_start(&data->progress.dl.rlimit, &data->progress.now);
+    Curl_rlimit_start(&data->progress.dl.rlimit, Curl_pgrs_now(data));
     ctx->started_response = TRUE;
   }
 
@@ -1202,13 +1202,13 @@ CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen,
     DEBUGASSERT(data->req.reader_stack);
   }
   if(!data->req.reader_started) {
-    Curl_rlimit_start(&data->progress.ul.rlimit, &data->progress.now);
+    Curl_rlimit_start(&data->progress.ul.rlimit, Curl_pgrs_now(data));
     data->req.reader_started = TRUE;
   }
 
   if(Curl_rlimit_active(&data->progress.ul.rlimit)) {
-    curl_off_t ul_avail =
-      Curl_rlimit_avail(&data->progress.ul.rlimit, &data->progress.now);
+    curl_off_t ul_avail = Curl_rlimit_avail(&data->progress.ul.rlimit,
+                                            Curl_pgrs_now(data));
     if(ul_avail <= 0) {
       result = CURLE_OK;
       *eos = FALSE;
index 627865dc31ce92cd88c090ccd0426eef086a58c1..3c4350e539b173183293846b6ff33e8bbf9f9e96 100644 (file)
@@ -2814,7 +2814,7 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     s->max_send_speed = offt;
     Curl_rlimit_init(&data->progress.ul.rlimit, offt, offt,
-                     &data->progress.now);
+                     Curl_pgrs_now(data));
     break;
   case CURLOPT_MAX_RECV_SPEED_LARGE:
     /*
@@ -2825,7 +2825,7 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option,
       return CURLE_BAD_FUNCTION_ARGUMENT;
     s->max_recv_speed = offt;
     Curl_rlimit_init(&data->progress.dl.rlimit, offt, offt,
-                     &data->progress.now);
+                     Curl_pgrs_now(data));
     break;
   case CURLOPT_RESUME_FROM_LARGE:
     /*
index 8ae7bc169dca78b6392c59f1a33e4b714f5ef90d..026e3efc0fc11f7692ed34db3daec71c386d0a2a 100644 (file)
@@ -1441,7 +1441,7 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done)
   Curl_sasl_init(&smtpc->sasl, data, &saslsmtp);
 
   /* Initialise the pingpong layer */
-  Curl_pp_init(&smtpc->pp, &data->progress.now);
+  Curl_pp_init(&smtpc->pp, Curl_pgrs_now(data));
 
   /* Parse the URL options */
   result = smtp_parse_url_options(data->conn, smtpc);
index d036d27f548e526867e3ef98bec11a1f2eddfdad..a95eb10d8502dcffafed7019d40abd925083fa16 100644 (file)
  *  zero          : when i is equal   to   j
  *  positive when : when i is larger  than j
  */
-#define compare(i, j) curlx_timediff_us(i, j)
+#define splay_compare(i, j) curlx_ptimediff_us(i, j)
 
 /*
  * Splay using the key i (which may or may not be in the tree.) The starting
  * root is t.
  */
-struct Curl_tree *Curl_splay(struct curltime i,
+struct Curl_tree *Curl_splay(const struct curltime *pkey,
                              struct Curl_tree *t)
 {
   struct Curl_tree N, *l, *r, *y;
@@ -51,11 +51,11 @@ struct Curl_tree *Curl_splay(struct curltime i,
   l = r = &N;
 
   for(;;) {
-    timediff_t comp = compare(i, t->key);
+    timediff_t comp = splay_compare(pkey, &t->key);
     if(comp < 0) {
       if(!t->smaller)
         break;
-      if(compare(i, t->smaller->key) < 0) {
+      if(splay_compare(pkey, &t->smaller->key) < 0) {
         y = t->smaller;                           /* rotate smaller */
         t->smaller = y->larger;
         y->larger = t;
@@ -70,7 +70,7 @@ struct Curl_tree *Curl_splay(struct curltime i,
     else if(comp > 0) {
       if(!t->larger)
         break;
-      if(compare(i, t->larger->key) > 0) {
+      if(splay_compare(pkey, &t->larger->key) > 0) {
         y = t->larger;                          /* rotate larger */
         t->larger = y->smaller;
         y->smaller = t;
@@ -103,16 +103,16 @@ static const struct curltime SPLAY_SUBNODE = {
  *
  * @unittest: 1309
  */
-struct Curl_tree *Curl_splayinsert(struct curltime i,
+struct Curl_tree *Curl_splayinsert(const struct curltime *pkey,
                                    struct Curl_tree *t,
                                    struct Curl_tree *node)
 {
   DEBUGASSERT(node);
 
   if(t) {
-    t = Curl_splay(i, t);
+    t = Curl_splay(pkey, t);
     DEBUGASSERT(t);
-    if(compare(i, t->key) == 0) {
+    if(splay_compare(pkey, &t->key) == 0) {
       /* There already exists a node in the tree with the same key. Build a
          doubly-linked circular list of nodes. We add the new 'node' struct to
          the end of this list. */
@@ -130,7 +130,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
   if(!t) {
     node->smaller = node->larger = NULL;
   }
-  else if(compare(i, t->key) < 0) {
+  else if(splay_compare(pkey, &t->key) < 0) {
     node->smaller = t->smaller;
     node->larger = t;
     t->smaller = NULL;
@@ -140,7 +140,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
     node->smaller = t;
     t->larger = NULL;
   }
-  node->key = i;
+  node->key = *pkey;
 
   /* no identical nodes (yet), we are the only one in the list of nodes */
   node->samen = node;
@@ -151,7 +151,7 @@ struct Curl_tree *Curl_splayinsert(struct curltime i,
 /* Finds and deletes the best-fit node from the tree. Return a pointer to the
    resulting tree. best-fit means the smallest node if it is not larger than
    the key */
-struct Curl_tree *Curl_splaygetbest(struct curltime i,
+struct Curl_tree *Curl_splaygetbest(const struct curltime *pkey,
                                     struct Curl_tree *t,
                                     struct Curl_tree **removed)
 {
@@ -164,9 +164,9 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i,
   }
 
   /* find smallest */
-  t = Curl_splay(tv_zero, t);
+  t = Curl_splay(&tv_zero, t);
   DEBUGASSERT(t);
-  if(compare(i, t->key) < 0) {
+  if(splay_compare(pkey, &t->key) < 0) {
     /* even the smallest is too big */
     *removed = NULL;
     return t;
@@ -218,7 +218,7 @@ int Curl_splayremove(struct Curl_tree *t,
 
   DEBUGASSERT(removenode);
 
-  if(compare(SPLAY_SUBNODE, removenode->key) == 0) {
+  if(splay_compare(&SPLAY_SUBNODE, &removenode->key) == 0) {
     /* It is a subnode within a 'same' linked list and thus we can unlink it
        easily. */
     DEBUGASSERT(removenode->samen != removenode);
@@ -236,7 +236,7 @@ int Curl_splayremove(struct Curl_tree *t,
     return 0;
   }
 
-  t = Curl_splay(removenode->key, t);
+  t = Curl_splay(&removenode->key, t);
   DEBUGASSERT(t);
 
   /* First make sure that we got the same root node as the one we want
@@ -268,7 +268,7 @@ int Curl_splayremove(struct Curl_tree *t,
     if(!t->smaller)
       x = t->larger;
     else {
-      x = Curl_splay(removenode->key, t->smaller);
+      x = Curl_splay(&removenode->key, t->smaller);
       DEBUGASSERT(x);
       x->larger = t->larger;
     }
index ccc3781ec16780d8c38e3df98e8611720ef04661..3a256b5713c8b2239ef2a8866ee673e2e7f5d0bd 100644 (file)
@@ -36,14 +36,14 @@ struct Curl_tree {
   void *ptr;                 /* data the splay code does not care about */
 };
 
-struct Curl_tree *Curl_splay(struct curltime i,
+struct Curl_tree *Curl_splay(const struct curltime *pkey,
                              struct Curl_tree *t);
 
-struct Curl_tree *Curl_splayinsert(struct curltime key,
+struct Curl_tree *Curl_splayinsert(const struct curltime *pkey,
                                    struct Curl_tree *t,
                                    struct Curl_tree *newnode);
 
-struct Curl_tree *Curl_splaygetbest(struct curltime key,
+struct Curl_tree *Curl_splaygetbest(const struct curltime *pkey,
                                     struct Curl_tree *t,
                                     struct Curl_tree **removed);
 
index 4a25527388c9ad9bd81f1a7302147e153cf518b7..e517b0c1384beb554252571c03fb0638ec459f8a 100644 (file)
@@ -1507,8 +1507,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
     } /* switch */
 
     if(data->set.timeout) {
-      Curl_pgrs_now_set(data);
-      if(curlx_timediff_ms(data->progress.now, conn->created) >=
+      if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->created) >=
          data->set.timeout) {
         failf(data, "Time-out");
         result = CURLE_OPERATION_TIMEDOUT;
@@ -1627,8 +1626,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
     } /* poll switch statement */
 
     if(data->set.timeout) {
-      Curl_pgrs_now_set(data);
-      if(curlx_timediff_ms(data->progress.now, conn->created) >=
+      if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->created) >=
          data->set.timeout) {
         failf(data, "Time-out");
         result = CURLE_OPERATION_TIMEDOUT;
index 5407ba4477f65b0f7616d2b44d32f33dfffa361f..6e190f46c0b663228865871ff8d367dcd989ac14 100644 (file)
@@ -261,7 +261,7 @@ static CURLcode sendrecv_dl(struct Curl_easy *data,
 
     if(bytestoread && Curl_rlimit_active(&data->progress.dl.rlimit)) {
       curl_off_t dl_avail = Curl_rlimit_avail(&data->progress.dl.rlimit,
-                                              &data->progress.now);
+                                              Curl_pgrs_now(data));
       /* DEBUGF(infof(data, "dl_rlimit, available=%" FMT_OFF_T, dl_avail));
        */
       /* In case of rate limited downloads: if this loop already got
@@ -399,15 +399,15 @@ CURLcode Curl_sendrecv(struct Curl_easy *data)
         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
               " milliseconds with %" FMT_OFF_T " out of %"
               FMT_OFF_T " bytes received",
-              curlx_timediff_ms(data->progress.now,
-                                data->progress.t_startsingle),
+              curlx_ptimediff_ms(Curl_pgrs_now(data),
+                                 &data->progress.t_startsingle),
               k->bytecount, k->size);
       }
       else {
         failf(data, "Operation timed out after %" FMT_TIMEDIFF_T
               " milliseconds with %" FMT_OFF_T " bytes received",
-              curlx_timediff_ms(data->progress.now,
-                                data->progress.t_startsingle),
+              curlx_ptimediff_ms(Curl_pgrs_now(data),
+                                 &data->progress.t_startsingle),
               k->bytecount);
       }
       result = CURLE_OPERATION_TIMEDOUT;
@@ -903,7 +903,7 @@ bool Curl_xfer_recv_is_paused(struct Curl_easy *data)
 CURLcode Curl_xfer_pause_send(struct Curl_easy *data, bool enable)
 {
   CURLcode result = CURLE_OK;
-  Curl_rlimit_block(&data->progress.ul.rlimit, enable, &data->progress.now);
+  Curl_rlimit_block(&data->progress.ul.rlimit, enable, Curl_pgrs_now(data));
   if(!enable && Curl_creader_is_paused(data))
     result = Curl_creader_unpause(data);
   Curl_pgrsSendPause(data, enable);
@@ -913,7 +913,7 @@ CURLcode Curl_xfer_pause_send(struct Curl_easy *data, bool enable)
 CURLcode Curl_xfer_pause_recv(struct Curl_easy *data, bool enable)
 {
   CURLcode result = CURLE_OK;
-  Curl_rlimit_block(&data->progress.dl.rlimit, enable, &data->progress.now);
+  Curl_rlimit_block(&data->progress.dl.rlimit, enable, Curl_pgrs_now(data));
   if(!enable && Curl_cwriter_is_paused(data))
     result = Curl_cwriter_unpause(data);
   Curl_conn_ev_data_pause(data, enable);
index fe5c3f38da0411b4f5845001955d1a71dbeb6c86..29d6b3442219e17b5370d5148373c45fb3dd60d6 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -514,7 +514,6 @@ CURLcode Curl_open(struct Curl_easy **curl)
 #endif
   Curl_netrc_init(&data->state.netrc);
   Curl_init_userdefined(data);
-  Curl_pgrs_now_set(data); /* on easy handle create */
 
   *curl = data;
   return CURLE_OK;
@@ -638,7 +637,7 @@ static bool conn_maxage(struct Curl_easy *data,
   timediff_t age_ms;
 
   if(data->set.conn_max_idle_ms) {
-    age_ms = curlx_timediff_ms(now, conn->lastused);
+    age_ms = curlx_ptimediff_ms(&now, &conn->lastused);
     if(age_ms > data->set.conn_max_idle_ms) {
       infof(data, "Too old connection (%" FMT_TIMEDIFF_T
             " ms idle, max idle is %" FMT_TIMEDIFF_T " ms), disconnect it",
@@ -648,7 +647,7 @@ static bool conn_maxage(struct Curl_easy *data,
   }
 
   if(data->set.conn_max_age_ms) {
-    age_ms = curlx_timediff_ms(now, conn->created);
+    age_ms = curlx_ptimediff_ms(&now, &conn->created);
     if(age_ms > data->set.conn_max_age_ms) {
       infof(data,
             "Too old connection (created %" FMT_TIMEDIFF_T
@@ -673,7 +672,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
        use */
     bool dead;
 
-    if(conn_maxage(data, conn, data->progress.now)) {
+    if(conn_maxage(data, conn, *Curl_pgrs_now(data))) {
       /* avoid check if already too old */
       dead = TRUE;
     }
@@ -722,11 +721,11 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
 }
 
 CURLcode Curl_conn_upkeep(struct Curl_easy *data,
-                          struct connectdata *conn,
-                          struct curltime *now)
+                          struct connectdata *conn)
 {
   CURLcode result = CURLE_OK;
-  if(curlx_timediff_ms(*now, conn->keepalive) <= data->set.upkeep_interval_ms)
+  if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->keepalive) <=
+     data->set.upkeep_interval_ms)
     return result;
 
   /* briefly attach for action */
@@ -744,7 +743,7 @@ CURLcode Curl_conn_upkeep(struct Curl_easy *data,
   }
   Curl_detach_connection(data);
 
-  conn->keepalive = *now;
+  conn->keepalive = *Curl_pgrs_now(data);
   return result;
 }
 
@@ -1341,7 +1340,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
   conn->remote_port = -1; /* unknown at this point */
 
   /* Store creation time to help future close decision making */
-  conn->created = data->progress.now;
+  conn->created = *Curl_pgrs_now(data);
 
   /* Store current time to give a baseline to keepalive connection times. */
   conn->keepalive = conn->created;
@@ -3261,7 +3260,8 @@ static CURLcode resolve_server(struct Curl_easy *data,
   else if(result == CURLE_OPERATION_TIMEDOUT) {
     failf(data, "Failed to resolve %s '%s' with timeout after %"
           FMT_TIMEDIFF_T " ms", peertype, ehost->dispname,
-          curlx_timediff_ms(data->progress.now, data->progress.t_startsingle));
+          curlx_ptimediff_ms(Curl_pgrs_now(data),
+                             &data->progress.t_startsingle));
     return CURLE_OPERATION_TIMEDOUT;
   }
   else if(result) {
index 6c2f1e144c579bc23e2c7c3acfe7344e53112885..3a8d57c377f6fe18502f23c3bc5c261bf15b1724 100644 (file)
--- a/lib/url.h
+++ b/lib/url.h
@@ -90,8 +90,7 @@ bool Curl_conn_seems_dead(struct connectdata *conn,
  * Perform upkeep operations on the connection.
  */
 CURLcode Curl_conn_upkeep(struct Curl_easy *data,
-                          struct connectdata *conn,
-                          struct curltime *now);
+                          struct connectdata *conn);
 
 /**
  * Always eval all arguments, return the first result != CURLE_OK.
index 881f06760d85c739c15f648b113a09b19f37da0a..6087481f5928ca027bdeb75c6c3529b7451ae07b 100644 (file)
@@ -389,10 +389,11 @@ static void pktx_update_time(struct Curl_easy *data,
                              struct Curl_cfilter *cf)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  const struct curltime *pnow = Curl_pgrs_now(data);
 
-  vquic_ctx_update_time(data, &ctx->q);
-  pktx->ts = (ngtcp2_tstamp)ctx->q.last_op.tv_sec * NGTCP2_SECONDS +
-             (ngtcp2_tstamp)ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS;
+  vquic_ctx_update_time(&ctx->q, pnow);
+  pktx->ts = (ngtcp2_tstamp)pnow->tv_sec * NGTCP2_SECONDS +
+             (ngtcp2_tstamp)pnow->tv_usec * NGTCP2_MICROSECONDS;
 }
 
 static void pktx_init(struct pkt_io_ctx *pktx,
@@ -400,13 +401,14 @@ static void pktx_init(struct pkt_io_ctx *pktx,
                       struct Curl_easy *data)
 {
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
+  const struct curltime *pnow = Curl_pgrs_now(data);
 
   pktx->cf = cf;
   pktx->data = data;
   ngtcp2_path_storage_zero(&pktx->ps);
-  vquic_ctx_set_time(data, &ctx->q);
-  pktx->ts = (ngtcp2_tstamp)ctx->q.last_op.tv_sec * NGTCP2_SECONDS +
-             (ngtcp2_tstamp)ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS;
+  vquic_ctx_set_time(&ctx->q, pnow);
+  pktx->ts = (ngtcp2_tstamp)pnow->tv_sec * NGTCP2_SECONDS +
+             (ngtcp2_tstamp)pnow->tv_usec * NGTCP2_MICROSECONDS;
 }
 
 static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
@@ -505,8 +507,7 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
   if(!ctx || !data)
     return NGHTTP3_ERR_CALLBACK_FAILURE;
 
-  Curl_pgrs_now_set(data); /* real change */
-  ctx->handshake_at = data->progress.now;
+  ctx->handshake_at = *Curl_pgrs_now(data);
   ctx->tls_handshake_complete = TRUE;
   Curl_vquic_report_handshake(&ctx->tls, cf, data);
 
@@ -520,7 +521,7 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data)
                 "ms, remote transport[max_udp_payload=%" PRIu64
                 ", initial_max_data=%" PRIu64
                 "]",
-               curlx_timediff_ms(ctx->handshake_at, ctx->started_at),
+               curlx_ptimediff_ms(&ctx->handshake_at, &ctx->started_at),
                rp->max_udp_payload_size, rp->initial_max_data);
   }
 #endif
@@ -1058,7 +1059,8 @@ static void cf_ngtcp2_ack_stream(struct Curl_cfilter *cf,
   /* How many byte to ack on the stream? */
 
   /* how much does rate limiting allow us to acknowledge? */
-  avail = Curl_rlimit_avail(&data->progress.dl.rlimit, &data->progress.now);
+  avail = Curl_rlimit_avail(&data->progress.dl.rlimit,
+                            Curl_pgrs_now(data));
   if(avail == CURL_OFF_T_MAX) { /* no rate limit, ack all */
     ack_len = stream->download_unacked;
   }
@@ -1082,7 +1084,6 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
   struct Curl_cfilter *cf = user_data;
   struct cf_ngtcp2_ctx *ctx = cf->ctx;
   struct Curl_easy *data = stream_user_data;
-  struct Curl_easy *calling = CF_DATA_CURRENT(cf);
   struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
 
   (void)conn;
@@ -1090,8 +1091,6 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id,
 
   if(!stream)
     return NGHTTP3_ERR_CALLBACK_FAILURE;
-  if(calling)
-    Curl_pgrs_now_update(data, calling);
 
   h3_xfer_write_resp(cf, data, stream, (const char *)buf, blen, FALSE);
   CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu", stream->id, blen);
@@ -2637,7 +2636,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf,
   CF_DATA_SAVE(save, cf, data);
 
   if(!ctx->qconn) {
-    ctx->started_at = data->progress.now;
+    ctx->started_at = *Curl_pgrs_now(data);
     result = cf_connect_start(cf, data, &pktx);
     if(result)
       goto out;
@@ -2750,7 +2749,8 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf,
   }
   case CF_QUERY_CONNECT_REPLY_MS:
     if(ctx->q.got_first_byte) {
-      timediff_t ms = curlx_timediff_ms(ctx->q.first_byte_at, ctx->started_at);
+      timediff_t ms = curlx_ptimediff_ms(&ctx->q.first_byte_at,
+                                         &ctx->started_at);
       *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
     }
     else
@@ -2812,7 +2812,7 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf,
   rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn);
   if(rp && rp->max_idle_timeout) {
     timediff_t idletime_ms =
-      curlx_timediff_ms(data->progress.now, ctx->q.last_io);
+      curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->q.last_io);
     if(idletime_ms > 0) {
       uint64_t max_idle_ms =
         (uint64_t)(rp->max_idle_timeout / NGTCP2_MILLISECONDS);
index 44a12526f0118ec9526d27527e2c3bafdc38d854..dc79fe399cc2e2e3cec5f7c564ca287f00eb480b 100644 (file)
@@ -1650,7 +1650,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf,
     if(acked_len > 0 || (eos && !s->send_blocked)) {
       /* Since QUIC buffers the data written internally, we can tell
        * nghttp3 that it can move forward on it */
-      ctx->q.last_io = curlx_now();
+      ctx->q.last_io = *Curl_pgrs_now(data);
       rv = nghttp3_conn_add_write_offset(ctx->h3.conn, s->id, acked_len);
       if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) {
         failf(data, "nghttp3_conn_add_write_offset returned error: %s",
@@ -1766,7 +1766,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
   CF_DATA_SAVE(save, cf, data);
 
   if(!ctx->tls.ossl.ssl) {
-    ctx->started_at = data->progress.now;
+    ctx->started_at = *Curl_pgrs_now(data);
     result = cf_osslq_ctx_start(cf, data);
     if(result)
       goto out;
@@ -1776,7 +1776,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
     int readable = SOCKET_READABLE(ctx->q.sockfd, 0);
     if(readable > 0 && (readable & CURL_CSELECT_IN)) {
       ctx->got_first_byte = TRUE;
-      ctx->first_byte_at = data->progress.now;
+      ctx->first_byte_at = *Curl_pgrs_now(data);
     }
   }
 
@@ -1797,14 +1797,13 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
       /* if not recorded yet, take the timestamp before we called
        * SSL_do_handshake() as the time we received the first packet. */
       ctx->got_first_byte = TRUE;
-      ctx->first_byte_at = data->progress.now;
+      ctx->first_byte_at = *Curl_pgrs_now(data);
     }
     /* Record the handshake complete with a new time stamp. */
-    Curl_pgrs_now_set(data);
-    ctx->handshake_at = data->progress.now;
-    ctx->q.last_io = data->progress.now;
+    ctx->handshake_at = *Curl_pgrs_now(data);
+    ctx->q.last_io = *Curl_pgrs_now(data);
     CURL_TRC_CF(data, cf, "handshake complete after %" FMT_TIMEDIFF_T "ms",
-                curlx_timediff_ms(data->progress.now, ctx->started_at));
+                curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->started_at));
     result = cf_osslq_verify_peer(cf, data);
     if(!result) {
       CURL_TRC_CF(data, cf, "peer verified");
@@ -1816,17 +1815,17 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf,
     int detail = SSL_get_error(ctx->tls.ossl.ssl, err);
     switch(detail) {
     case SSL_ERROR_WANT_READ:
-      ctx->q.last_io = data->progress.now;
+      ctx->q.last_io = *Curl_pgrs_now(data);
       CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_RECV");
       goto out;
     case SSL_ERROR_WANT_WRITE:
-      ctx->q.last_io = data->progress.now;
+      ctx->q.last_io = *Curl_pgrs_now(data);
       CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_SEND");
       result = CURLE_OK;
       goto out;
 #ifdef SSL_ERROR_WANT_ASYNC
     case SSL_ERROR_WANT_ASYNC:
-      ctx->q.last_io = data->progress.now;
+      ctx->q.last_io = *Curl_pgrs_now(data);
       CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_ASYNC");
       result = CURLE_OK;
       goto out;
@@ -2240,7 +2239,7 @@ static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf,
       goto out;
     }
     CURL_TRC_CF(data, cf, "negotiated idle timeout: %" PRIu64 "ms", idle_ms);
-    idletime = curlx_timediff_ms(data->progress.now, ctx->q.last_io);
+    idletime = curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->q.last_io);
     if(idle_ms && idletime > 0 && (uint64_t)idletime > idle_ms)
       goto out;
   }
@@ -2330,7 +2329,8 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf,
   }
   case CF_QUERY_CONNECT_REPLY_MS:
     if(ctx->got_first_byte) {
-      timediff_t ms = curlx_timediff_ms(ctx->first_byte_at, ctx->started_at);
+      timediff_t ms = curlx_ptimediff_ms(&ctx->first_byte_at,
+                                         &ctx->started_at);
       *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
     }
     else
index 4ee12dc005128fdaa748fcf2a3908e9d5f279c2d..abf1a23c20d70ac45ebaf2f7dd36cdd6efac3766 100644 (file)
@@ -499,7 +499,6 @@ static void cf_quiche_recv_body(struct Curl_cfilter *cf,
 }
 
 static void cf_quiche_process_ev(struct Curl_cfilter *cf,
-                                 struct Curl_easy *calling,
                                  struct Curl_easy *data,
                                  struct h3_stream_ctx *stream,
                                  quiche_h3_event *ev)
@@ -507,7 +506,6 @@ static void cf_quiche_process_ev(struct Curl_cfilter *cf,
   if(!stream)
     return;
 
-  Curl_pgrs_now_update(data, calling);
   switch(quiche_h3_event_type(ev)) {
   case QUICHE_H3_EVENT_HEADERS: {
     struct cb_ctx cb_ctx;
@@ -563,7 +561,6 @@ struct cf_quich_disp_ctx {
   uint64_t stream_id;
   struct Curl_cfilter *cf;
   struct Curl_multi *multi;
-  struct Curl_easy *calling;
   quiche_h3_event *ev;
 };
 
@@ -575,7 +572,7 @@ static bool cf_quiche_disp_event(uint32_t mid, void *val, void *user_data)
   if(stream->id == dctx->stream_id) {
     struct Curl_easy *sdata = Curl_multi_get_easy(dctx->multi, mid);
     if(sdata)
-      cf_quiche_process_ev(dctx->cf, dctx->calling, sdata, stream, dctx->ev);
+      cf_quiche_process_ev(dctx->cf, sdata, stream, dctx->ev);
     return FALSE; /* stop iterating */
   }
   return TRUE;
@@ -602,7 +599,7 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
       stream = H3_STREAM_CTX(ctx, data);
       if(stream && stream->id == (uint64_t)rv) {
         /* event for calling transfer */
-        cf_quiche_process_ev(cf, data, data, stream, ev);
+        cf_quiche_process_ev(cf, data, stream, ev);
         quiche_h3_event_free(ev);
         if(stream->xfer_result)
           return stream->xfer_result;
@@ -613,7 +610,6 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf,
         struct cf_quich_disp_ctx dctx;
         dctx.stream_id = (uint64_t)rv;
         dctx.cf = cf;
-        dctx.calling = data;
         dctx.multi = data->multi;
         dctx.ev = ev;
         Curl_uint32_hash_visit(&ctx->streams, cf_quiche_disp_event, &dctx);
@@ -869,7 +865,7 @@ static CURLcode cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
   *pnread = 0;
   (void)buf;
   (void)blen;
-  vquic_ctx_update_time(data, &ctx->q);
+  vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data));
 
   if(!stream)
     return CURLE_RECV_ERROR;
@@ -1079,7 +1075,7 @@ static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data,
   CURLcode result;
 
   *pnwritten = 0;
-  vquic_ctx_update_time(data, &ctx->q);
+  vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data));
 
   result = cf_process_ingress(cf, data);
   if(result)
@@ -1356,7 +1352,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
   }
 
   *done = FALSE;
-  vquic_ctx_update_time(data, &ctx->q);
+  vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data));
 
   if(!ctx->qconn) {
     result = cf_quiche_ctx_open(cf, data);
@@ -1379,7 +1375,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf,
   if(quiche_conn_is_established(ctx->qconn)) {
     ctx->handshake_at = ctx->q.last_op;
     CURL_TRC_CF(data, cf, "handshake complete after %" FMT_TIMEDIFF_T "ms",
-                curlx_timediff_ms(ctx->handshake_at, ctx->started_at));
+                curlx_ptimediff_ms(&ctx->handshake_at, &ctx->started_at));
     result = cf_quiche_verify_peer(cf, data);
     if(!result) {
       CURL_TRC_CF(data, cf, "peer verified");
@@ -1438,7 +1434,7 @@ static CURLcode cf_quiche_shutdown(struct Curl_cfilter *cf,
     int err;
 
     ctx->shutdown_started = TRUE;
-    vquic_ctx_update_time(data, &ctx->q);
+    vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data));
     err = quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0);
     if(err) {
       CURL_TRC_CF(data, cf, "error %d adding shutdown packet, "
@@ -1509,7 +1505,8 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf,
   }
   case CF_QUERY_CONNECT_REPLY_MS:
     if(ctx->q.got_first_byte) {
-      timediff_t ms = curlx_timediff_ms(ctx->q.first_byte_at, ctx->started_at);
+      timediff_t ms = curlx_ptimediff_ms(&ctx->q.first_byte_at,
+                                         &ctx->started_at);
       *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX;
     }
     else
index 03da05dccecff75208d906010fde9cd7980e8543..3bc6835184521a9657fc09163ef9bc028c35cd47 100644 (file)
@@ -95,7 +95,7 @@ CURLcode vquic_ctx_init(struct Curl_easy *data,
     }
   }
 #endif
-  vquic_ctx_set_time(data, qctx);
+  vquic_ctx_set_time(qctx, Curl_pgrs_now(data));
 
   return CURLE_OK;
 }
@@ -105,17 +105,16 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx)
   Curl_bufq_free(&qctx->sendbuf);
 }
 
-void vquic_ctx_set_time(struct Curl_easy *data,
-                        struct cf_quic_ctx *qctx)
+void vquic_ctx_set_time(struct cf_quic_ctx *qctx,
+                        const struct curltime *pnow)
 {
-  qctx->last_op = data->progress.now;
+  qctx->last_op = *pnow;
 }
 
-void vquic_ctx_update_time(struct Curl_easy *data,
-                           struct cf_quic_ctx *qctx)
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx,
+                           const struct curltime *pnow)
 {
-  Curl_pgrs_now_set(data);
-  qctx->last_op = data->progress.now;
+  qctx->last_op = *pnow;
 }
 
 static CURLcode send_packet_no_gso(struct Curl_cfilter *cf,
index efe4e2c816f1ea0e885b34b94cb77667dfdaaaad..82f22b45a88f323e82e4bce9cdada214e53b10d5 100644 (file)
@@ -58,11 +58,11 @@ CURLcode vquic_ctx_init(struct Curl_easy *data,
                         struct cf_quic_ctx *qctx);
 void vquic_ctx_free(struct cf_quic_ctx *qctx);
 
-void vquic_ctx_set_time(struct Curl_easy *data,
-                        struct cf_quic_ctx *qctx);
+void vquic_ctx_set_time(struct cf_quic_ctx *qctx,
+                        const struct curltime *pnow);
 
-void vquic_ctx_update_time(struct Curl_easy *data,
-                           struct cf_quic_ctx *qctx);
+void vquic_ctx_update_time(struct cf_quic_ctx *qctx,
+                           const struct curltime *pnow);
 
 void vquic_push_blocked_pkt(struct Curl_cfilter *cf,
                             struct cf_quic_ctx *qctx,
index 0f023078eb9ccfaf671053a8d0d07172fa3e3dcb..0cabe28dbb475198d169f9b0b7c9894471d96300 100644 (file)
@@ -3119,13 +3119,12 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
                                     bool disconnect)
 {
   CURLcode result = CURLE_OK;
-  struct curltime start = data->progress.now;
+  struct curltime start = *Curl_pgrs_now(data);
 
   while((sshc->state != SSH_STOP) && !result) {
     bool block;
     timediff_t left_ms = 1000;
 
-    Curl_pgrs_now_set(data); /* timeout disconnect */
     result = ssh_statemachine(data, sshc, sshp, &block);
     if(result)
       break;
@@ -3141,7 +3140,7 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data,
         return CURLE_OPERATION_TIMEDOUT;
       }
     }
-    else if(curlx_timediff_ms(data->progress.now, start) > 1000) {
+    else if(curlx_ptimediff_ms(Curl_pgrs_now(data), &start) > 1000) {
       /* disconnect timeout */
       failf(data, "Disconnect timed out");
       result = CURLE_OK;
index 9e8836773796de49d48824e94edf8d6a10cf02f3..543173ae5810e2c7c88646aaef86bdd34add0559 100644 (file)
@@ -412,7 +412,7 @@ CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data,
   }
 
   shared->refcount = 1;
-  shared->time = data->progress.now;
+  shared->time = *Curl_pgrs_now(data);
   *pcreds = shared;
   return CURLE_OK;
 }
@@ -559,11 +559,11 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf,
 /* key to use at `multi->proto_hash` */
 #define MPROTO_GTLS_X509_KEY   "tls:gtls:x509:share"
 
-static bool gtls_shared_creds_expired(const struct Curl_easy *data,
+static bool gtls_shared_creds_expired(struct Curl_easy *data,
                                       const struct gtls_shared_creds *sc)
 {
   const struct ssl_general_config *cfg = &data->set.general_ssl;
-  timediff_t elapsed_ms = curlx_timediff_ms(data->progress.now, sc->time);
+  timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &sc->time);
   timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
 
   if(timeout_ms < 0)
index d09e2d1a71905903ea45b5f84f1fcc454cd36fc9..619fb2e2d077d8ec107300cd62ed4c60428c99d9 100644 (file)
@@ -53,6 +53,7 @@
 #include "openssl.h"
 #include "../connect.h"
 #include "../slist.h"
+#include "../progress.h"
 #include "../select.h"
 #include "../curlx/wait.h"
 #include "vtls.h"
@@ -3212,14 +3213,14 @@ static void oss_x509_share_free(void *key, size_t key_len, void *p)
   curlx_free(share);
 }
 
-static bool ossl_cached_x509_store_expired(const struct Curl_easy *data,
+static bool ossl_cached_x509_store_expired(struct Curl_easy *data,
                                            const struct ossl_x509_share *mb)
 {
   const struct ssl_general_config *cfg = &data->set.general_ssl;
   if(cfg->ca_cache_timeout < 0)
     return FALSE;
   else {
-    timediff_t elapsed_ms = curlx_timediff_ms(data->progress.now, mb->time);
+    timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time);
     timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
 
     return elapsed_ms >= timeout_ms;
@@ -3241,7 +3242,7 @@ static bool ossl_cached_x509_store_different(struct Curl_cfilter *cf,
 }
 
 static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
-                                              const struct Curl_easy *data,
+                                              struct Curl_easy *data,
                                               bool *pempty)
 {
   struct Curl_multi *multi = data->multi;
@@ -3264,7 +3265,7 @@ static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf,
 }
 
 static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
-                                       const struct Curl_easy *data,
+                                       struct Curl_easy *data,
                                        X509_STORE *store,
                                        bool is_empty)
 {
@@ -3310,7 +3311,7 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf,
       curlx_free(share->CAfile);
     }
 
-    share->time = data->progress.now;
+    share->time = *Curl_pgrs_now(data);
     share->store = store;
     share->store_is_empty = is_empty;
     share->CAfile = CAfile;
index 2aa889bde29cb783083043c7000dbee3d099bc3c..986b65ec03d3104392d3dcbc3a52097f6a6dfd82 100644 (file)
@@ -1722,7 +1722,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data,
     connssl->connecting_state = ssl_connect_2;
     memset(rs, 0, sizeof(*rs));
     rs->io_need = CURL_SSL_IO_NEED_SEND;
-    rs->start_time = curlx_now();
+    rs->start_time = *Curl_pgrs_now(data);
     rs->started = TRUE;
   }
 
@@ -1731,7 +1731,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data,
     curl_socket_t readfd, writefd;
     timediff_t elapsed;
 
-    elapsed = curlx_timediff_ms(curlx_now(), rs->start_time);
+    elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &rs->start_time);
     if(elapsed >= MAX_RENEG_BLOCK_TIME) {
       failf(data, "schannel: renegotiation timeout");
       result = CURLE_SSL_CONNECT_ERROR;
@@ -1797,7 +1797,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data,
       if(result)
         break;
 
-      elapsed = curlx_timediff_ms(curlx_now(), rs->start_time);
+      elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &rs->start_time);
       if(elapsed >= MAX_RENEG_BLOCK_TIME) {
         failf(data, "schannel: renegotiation timeout");
         result = CURLE_SSL_CONNECT_ERROR;
@@ -2723,7 +2723,7 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl,
 }
 
 HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
-                                               const struct Curl_easy *data)
+                                               struct Curl_easy *data)
 {
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
   struct Curl_multi *multi = data->multi;
@@ -2732,7 +2732,6 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
   const struct ssl_general_config *cfg = &data->set.general_ssl;
   timediff_t timeout_ms;
   timediff_t elapsed_ms;
-  struct curltime now;
   unsigned char info_blob_digest[CURL_SHA256_DIGEST_LENGTH];
 
   DEBUGASSERT(multi);
@@ -2758,8 +2757,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
      negative timeout means retain forever. */
   timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
   if(timeout_ms >= 0) {
-    now = curlx_now();
-    elapsed_ms = curlx_timediff_ms(now, share->time);
+    elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &share->time);
     if(elapsed_ms >= timeout_ms) {
       return NULL;
     }
@@ -2803,7 +2801,7 @@ static void schannel_cert_share_free(void *key, size_t key_len, void *p)
 }
 
 bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
-                                         const struct Curl_easy *data,
+                                         struct Curl_easy *data,
                                          HCERTSTORE cert_store)
 {
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
index 88f03aaf68c4222b0b657aaf11488af82782053a..0146bf861917936a7db20b8022acbbdf55deddfa 100644 (file)
@@ -158,10 +158,10 @@ struct num_ip_data {
 };
 
 HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf,
-                                               const struct Curl_easy *data);
+                                               struct Curl_easy *data);
 
 bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf,
-                                         const struct Curl_easy *data,
+                                         struct Curl_easy *data,
                                          HCERTSTORE cert_store);
 
 #endif /* USE_SCHANNEL */
index 171e3731e8f7afd1c05a36b7041d17a853ec337a..643009a229a7f7c110782b29f857defd846d12be 100644 (file)
@@ -1371,8 +1371,7 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
   if(!result && *done) {
     cf->connected = TRUE;
     if(connssl->state == ssl_connection_complete) {
-      Curl_pgrs_now_set(data);
-      connssl->handshake_done = data->progress.now;
+      connssl->handshake_done = *Curl_pgrs_now(data);
     }
     /* Connection can be deferred when sending early data */
     DEBUGASSERT(connssl->state == ssl_connection_complete ||
index 3632d962ef58fb0ef199276a3494e2307ea093ce..c2c66715c20e83fe5489987515a278ac4b26c800 100644 (file)
@@ -723,11 +723,11 @@ static void wssl_x509_share_free(void *key, size_t key_len, void *p)
   curlx_free(share);
 }
 
-static bool wssl_cached_x509_store_expired(const struct Curl_easy *data,
+static bool wssl_cached_x509_store_expired(struct Curl_easy *data,
                                            const struct wssl_x509_share *mb)
 {
   const struct ssl_general_config *cfg = &data->set.general_ssl;
-  timediff_t elapsed_ms = curlx_timediff_ms(data->progress.now, mb->time);
+  timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time);
   timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000;
 
   if(timeout_ms < 0)
@@ -747,7 +747,7 @@ static bool wssl_cached_x509_store_different(struct Curl_cfilter *cf,
 }
 
 static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
-                                                  const struct Curl_easy *data)
+                                                      struct Curl_easy *data)
 {
   struct Curl_multi *multi = data->multi;
   struct wssl_x509_share *share;
@@ -767,7 +767,7 @@ static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf,
 }
 
 static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
-                                       const struct Curl_easy *data,
+                                       struct Curl_easy *data,
                                        WOLFSSL_X509_STORE *store)
 {
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
@@ -810,7 +810,7 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf,
       curlx_free(share->CAfile);
     }
 
-    share->time = data->progress.now;
+    share->time = *Curl_pgrs_now(data);
     share->store = store;
     share->CAfile = CAfile;
   }
index 5bdb3f70036db3d884ab49f551e0721ab8bad2f7..ca2d349bc454dac5ef9a727e9064a559c0025cd4 100644 (file)
@@ -148,7 +148,7 @@ static CURLcode test_unit1303(const char *arg)
     NOW(run[i].now_s, run[i].now_us);
     TIMEOUTS(run[i].timeout_ms, run[i].connecttimeout_ms);
     easy->progress.now = now;
-    timeout = Curl_timeleft_ms(easy, run[i].connecting);
+    timeout = Curl_timeleft_now_ms(easy, &now, run[i].connecting);
     if(timeout != run[i].result)
       fail(run[i].comment);
   }
index 46596544c6102c68b89b4b240d065ec4f433a846..b5620dcdbbaa10470d0cacf8c6a0e6ef70040ecc 100644 (file)
@@ -78,7 +78,7 @@ static CURLcode test_unit1309(const char *arg)
     key.tv_usec = (541 * i) % 1023;
     storage[i] = key.tv_usec;
     Curl_splayset(&nodes[i], &storage[i]);
-    root = Curl_splayinsert(key, root, &nodes[i]);
+    root = Curl_splayinsert(&key, root, &nodes[i]);
   }
 
   puts("Result:");
@@ -111,7 +111,7 @@ static CURLcode test_unit1309(const char *arg)
     for(j = 0; j <= i % 3; j++) {
       storage[i * 3 + j] = key.tv_usec * 10 + j;
       Curl_splayset(&nodes[i * 3 + j], &storage[i * 3 + j]);
-      root = Curl_splayinsert(key, root, &nodes[i * 3 + j]);
+      root = Curl_splayinsert(&key, root, &nodes[i * 3 + j]);
     }
   }
 
@@ -119,12 +119,12 @@ static CURLcode test_unit1309(const char *arg)
   for(i = 0; i <= 1100; i += 100) {
     curl_mprintf("Removing nodes not larger than %d\n", i);
     tv_now.tv_usec = i;
-    root = Curl_splaygetbest(tv_now, root, &removed);
+    root = Curl_splaygetbest(&tv_now, root, &removed);
     while(removed) {
       curl_mprintf("removed payload %zu[%zu]\n",
                    *(size_t *)Curl_splayget(removed) / 10,
                    *(size_t *)Curl_splayget(removed) % 10);
-      root = Curl_splaygetbest(tv_now, root, &removed);
+      root = Curl_splaygetbest(&tv_now, root, &removed);
     }
   }
 
index e02bf08bd97fd4440f848057f366e9ac6912904e..9ce182c1547d709ec117555cd00952c412e72b84 100644 (file)
@@ -78,6 +78,7 @@ static CURLcode test_unit1399(const char *arg)
   struct Curl_easy data;
   struct curltime now = curlx_now();
 
+  data.multi = NULL;
   data.progress.now = now;
   data.progress.t_nslookup = 0;
   data.progress.t_connect = 0;
index 202cc3b9c6c53fb0783a96414d5bb9b71982c6d5..111a5d2f4e45fe284253f5509fb17f59df00a43e 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "urldata.h"
 #include "connect.h"
+#include "progress.h"
 #include "curl_share.h"
 
 static CURLcode t1607_setup(void)