From 787cbd20330a6a3d9b024d47c2c35691c7b35cab Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Sat, 15 Aug 2026 11:07:15 +0200 Subject: [PATCH] multi: shrink expire timer indices The enum `exire_id` fits easily into a uint8_t. Use that type for storing expire timeout list indices. Closes #22591 --- lib/curl_trc.c | 8 ++++---- lib/multi.c | 49 ++++++++++++++++++++++++++++--------------------- lib/multiif.h | 2 +- lib/urldata.h | 4 ++-- 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/lib/curl_trc.c b/lib/curl_trc.c index 97f142af18..2bf81e8119 100644 --- a/lib/curl_trc.c +++ b/lib/curl_trc.c @@ -344,10 +344,10 @@ void Curl_trc_easy_timers(struct Curl_easy *data) struct expire_timers *timeouts = &data->state.timeouts; timediff_t base_us = Curl_timeouts_offset_us(&data->multi->timeouts, Curl_pgrs_now(data)); - expire_id eid = data->state.timeouts.first; - for(; eid < EXPIRE_LAST; eid = timeouts->next[eid]) { - CURL_TRC_TIMER(data, eid, "expires in %" FMT_TIMEDIFF_T "us", - timeouts->offset_us[eid] - base_us); + uint8_t id = data->state.timeouts.first; + for(; id < EXPIRE_LAST; id = timeouts->next[id]) { + CURL_TRC_TIMER(data, id, "expires in %" FMT_TIMEDIFF_T "us", + timeouts->offset_us[id] - base_us); } } } diff --git a/lib/multi.c b/lib/multi.c index 82d830488b..ceffe9911d 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -1128,7 +1128,7 @@ static CURLcode mstate_perform_pollset(struct Curl_easy *data, static size_t multi_timeouts_count(struct expire_timers *timeouts) { size_t n = 0; - expire_id eid = timeouts->first; + uint8_t eid = timeouts->first; for(; eid < EXPIRE_LAST; eid = timeouts->next[eid]) ++n; return n; @@ -3618,21 +3618,21 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi) static bool multi_timeouts_check(struct Curl_easy *data) { struct expire_timers *timeouts = &data->state.timeouts; - expire_id eid; + uint8_t id; int i = 0; - for(eid = timeouts->first; eid < EXPIRE_LAST; eid = timeouts->next[eid]) { + for(id = timeouts->first; id < EXPIRE_LAST; id = timeouts->next[id]) { if(++i >= EXPIRE_LAST) { failf(data, "expire timeouts looped: %d iterations and no end", i); return FALSE; } - if(eid == timeouts->next[eid]) { - failf(data, "expire timeouts wrong: %d points to itself", (int)eid); + if(id == timeouts->next[id]) { + failf(data, "expire timeouts wrong: %d points to itself", (int)id); return FALSE; } - if((timeouts->next[eid] < EXPIRE_LAST) && - (timeouts->offset_us[eid] > timeouts->offset_us[timeouts->next[eid]])) { + if((timeouts->next[id] < EXPIRE_LAST) && + (timeouts->offset_us[id] > timeouts->offset_us[timeouts->next[id]])) { failf(data, "expire timeouts not sorted: %d happens after %d but " - "is listed before", (int)eid, (int)timeouts->next[eid]); + "is listed before", (int)id, (int)timeouts->next[id]); return FALSE; } } @@ -3646,12 +3646,18 @@ static bool multi_timeouts_check(struct Curl_easy *data) static void multi_clear_timeout(struct Curl_easy *data, expire_id eid) { struct expire_timers *timeouts = &data->state.timeouts; - expire_id orig_first = timeouts->first; - expire_id *anchor = &timeouts->first; + uint8_t orig_first = timeouts->first; + uint8_t *anchor = &timeouts->first; + uint8_t id = (uint8_t)eid; + + if((unsigned)eid >= EXPIRE_LAST) { + DEBUGASSERT(0); + return; + } while(*anchor < EXPIRE_LAST) { - if(*anchor == eid) { - *anchor = timeouts->next[eid]; + if(*anchor == id) { + *anchor = timeouts->next[id]; break; } anchor = &timeouts->next[*anchor]; @@ -3684,25 +3690,26 @@ static CURLMcode multi_set_timeout(struct Curl_easy *data, expire_id eid) { struct expire_timers *timeouts = &data->state.timeouts; - expire_id *anchor = &timeouts->first; + uint8_t *anchor = &timeouts->first; + uint8_t id = (uint8_t)eid; - if(eid >= EXPIRE_LAST) { + if((unsigned)eid >= EXPIRE_LAST) { DEBUGASSERT(0); return CURLM_BAD_FUNCTION_ARGUMENT; } /* remove from list, store time and re-insert */ multi_clear_timeout(data, eid); - timeouts->offset_us[eid] = + timeouts->offset_us[id] = Curl_timeouts_offset_us(&data->multi->timeouts, stamp); while(*anchor < EXPIRE_LAST) { - if(timeouts->offset_us[*anchor] > timeouts->offset_us[eid]) + if(timeouts->offset_us[*anchor] > timeouts->offset_us[id]) break; anchor = &timeouts->next[*anchor]; } timeouts->next[eid] = *anchor; timeouts->next[eid] = *anchor; - *anchor = eid; + *anchor = id; DEBUGASSERT(multi_timeouts_check(data)); CURL_TRC_TIMER(data, eid, "set for %" FMT_TIMEDIFF_T "us", curlx_ptimediff_us(stamp, Curl_pgrs_now(data))); @@ -3723,7 +3730,7 @@ void Curl_expire(struct Curl_easy *data, { struct Curl_multi *multi = data->multi; struct expire_timers *timeouts = &data->state.timeouts; - expire_id prev_id = timeouts->first; + uint8_t prev_id = timeouts->first; struct curltime set; /* this is only interesting while there is still an associated multi struct @@ -3769,11 +3776,11 @@ void Curl_expire(struct Curl_easy *data, /* * Removes the expire timer. Marks it as done. */ -void Curl_expire_clear(struct Curl_easy *data, expire_id id) +void Curl_expire_clear(struct Curl_easy *data, expire_id eid) { /* remove the timer, if there */ - multi_clear_timeout(data, id); - CURL_TRC_TIMER(data, id, "cleared"); + multi_clear_timeout(data, eid); + CURL_TRC_TIMER(data, eid, "cleared"); } /* diff --git a/lib/multiif.h b/lib/multiif.h index 08d0b11064..16b9181cf8 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -28,7 +28,7 @@ */ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id eid); -void Curl_expire_clear(struct Curl_easy *data, expire_id id); +void Curl_expire_clear(struct Curl_easy *data, expire_id eid); void Curl_expire_clear_all(struct Curl_easy *data); CURLMcode Curl_update_timer(struct Curl_multi *multi) WARN_UNUSED_RESULT; void Curl_attach_connection(struct Curl_easy *data, diff --git a/lib/urldata.h b/lib/urldata.h index 886b48e0a9..bc7d9e6d4e 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -516,8 +516,8 @@ struct expire_timers { struct Curl_tree splaynode; /* for the splay stuff */ /* microsecond offset from Curl_timeouts base timestamp */ timediff_t offset_us[EXPIRE_LAST]; - expire_id next[EXPIRE_LAST]; - expire_id first; + uint8_t next[EXPIRE_LAST]; + uint8_t first; }; /* individual pieces of the URL */