From: Christopher Faulet Date: Thu, 16 Oct 2025 09:37:54 +0000 (+0200) Subject: EXP: peers: Use try-lock operations when looping on the updates list X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=165a33e015565c55944958490e8b449083ade841;p=thirdparty%2Fhaproxy.git EXP: peers: Use try-lock operations when looping on the updates list --- diff --git a/src/peers.c b/src/peers.c index ab230d43c..94584aec2 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1549,7 +1549,6 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, struct shared_tab int ret, new_pushed, use_timed; int updates_sent = 0; struct stksess *ts = NULL; - struct mt_list back; TRACE_ENTER(PEERS_EV_SESS_IO, appctx, p, st); @@ -1562,79 +1561,69 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, struct shared_tab /* We force new pushed to 1 to force identifier in update message */ new_pushed = 1; - MT_LIST_FOR_EACH_ENTRY_LOCKED(ts, &st->last->upd, upd, back) { - if (ts == st->end) { - ret = 1; // done + while (1) { + struct mt_list el1, el2; + + if (st->last->upd.next == &st->end->upd || st->last->upd.next == &st->table->updates) + break; + + if (buffer_almost_full(&appctx->outbuf)) { + applet_have_more_data(appctx); + ret = -1; break; } - if (!(p->flags & PEER_F_TEACH_PROCESS) && ts->updt_type != STKSESS_UPDT_LOCAL) - continue; - else if (ts->updt_type != STKSESS_UPDT_LOCAL && ts->updt_type != STKSESS_UPDT_REMOTE) + if (updates_sent >= peers_max_updates_at_once) { + applet_have_more_data(appctx); + ret = -1; + break; + } + + el1 = mt_list_try_lock_full(&st->last->upd); + if (el1.prev == NULL) { + applet_have_more_data(appctx); + ret = -1; + break; + } + el2 = mt_list_lock_next(el1.next); + /* el2 = mt_list_try_lock_next(el1.next); */ + /* if (el2.next == NULL) { */ + /* mt_list_unlock_full(&st->last->upd, el1); */ + /* applet_have_more_data(appctx); */ + /* ret = -1; */ + /* break; */ + /* } */ + + ts = MT_LIST_ELEM(el1.next, typeof(ts), upd); + HA_ATOMIC_INC(&ts->ref_cnt); + + mt_list_unlock_full(&st->last->upd, el2); + mt_list_unlock_link(el1); + + if ((!(p->flags & PEER_F_TEACH_PROCESS) && ts->updt_type != STKSESS_UPDT_LOCAL) || + (ts->updt_type != STKSESS_UPDT_LOCAL && ts->updt_type != STKSESS_UPDT_REMOTE) || + (p->srv->shard && ts->shard != p->srv->shard) || + ts->updt_type == STKSESS_UPDT_MARKER) { + HA_ATOMIC_DEC(&ts->ref_cnt); continue; + } if (st != p->last_local_table) { ret = peer_send_switchmsg(st, appctx); - if (ret <= 0) + if (ret <= 0) { + HA_ATOMIC_DEC(&ts->ref_cnt); break; - + } p->last_local_table = st; } if (!_HA_ATOMIC_LOAD(&ts->seen)) _HA_ATOMIC_STORE(&ts->seen, 1); - if (p->srv->shard && ts->shard != p->srv->shard) - continue; - - if (updates_sent >= peers_max_updates_at_once) { - applet_have_more_data(appctx); - ret = -1; - } - else { - HA_ATOMIC_INC(&ts->ref_cnt); - ret = peer_send_updatemsg(st, appctx, ts, st->update_id, new_pushed, use_timed); - HA_ATOMIC_DEC(&ts->ref_cnt); - } - - if (ret <= 0) { - /* Insert marker before to process it again - * on next iteration. remains locked - * - * Before: - * : <==============> - * - * <==> ... <==> x x <==> ... - * - * x <==> TS <==> x - * - * .prev == and .prev->next == MT_LIST_BUSY - * - * Step 1: detach from the list - * Step 2: insert after - * - .prev = (or .prev) - * - .next = MT_LIST_BUSY (or .prev->next) - * Step 3: move before - * - .next = (or back.prev->next = ) - * - * Step 4: update .prev to point on - * - * After: - * : <==============> - * - * ... <==> <==> x x <==> ... - * - * x <==> TS <==> x - * - */ - MT_LIST_DELETE(&st->last->upd); - st->last->upd.next = back.prev->next; /* == MT_LIST_BUSY */ - __ha_barrier_atomic_store(); - st->last->upd.prev = back.prev; - back.prev->next = &st->last->upd; - back.prev = &st->last->upd; + ret = peer_send_updatemsg(st, appctx, ts, st->update_id, new_pushed, use_timed); + HA_ATOMIC_DEC(&ts->ref_cnt); + if (ret <= 0) break; - } p->last.table = st; p->last.id = st->update_id; @@ -1647,12 +1636,9 @@ int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, struct shared_tab updates_sent++; } - if (ret == 1) { - MT_LIST_DELETE(&st->last->upd); - MT_LIST_APPEND(&st->end->upd, &st->last->upd); + if (ret == 1) MT_LIST_DELETE(&st->end->upd); - } - + end: TRACE_LEAVE(PEERS_EV_SESS_IO, appctx, p, st); return ret; }