]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: peers: only read-lock peer_send_teachmsgs()
authorWilly Tarreau <w@1wt.eu>
Mon, 7 Aug 2023 17:39:27 +0000 (19:39 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 11 Aug 2023 17:03:35 +0000 (19:03 +0200)
This function doesn't need to be write-locked. It performs a lookup
of the next update at its index, atomically updates the ref_cnt on
the stksess, updates some shared_table fields on the local thread,
and updates the table's commitupdate. Now that this update is atomic
we don't need to keep the write lock during that period. In addition
this function's callers do not rely on the write lock to be held
either since it was droped during peer_send_updatemsg() anyway.

Now, when the function is entered with a write lock, it's downgraded
to a read lock, otherwise a read lock is grabbed. Updates are looked
up under the read lock and the message is sent without the lock. The
commitupdate is still performed under the read lock (so as not to
break the code too much), and the write lock is re-acquired when
leaving if needed. This allows multiple peers to look up updates in
parallel and to avoid stalling stick-table lookups.

src/peers.c

index 23f6e5d12b86584dc7355c58d581a0e19206e01c..616b6e4f8bef4db230ba119fc4568dbb9edc1589 100644 (file)
@@ -1576,9 +1576,9 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p,
        new_pushed = 1;
 
        if (locked)
-               HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock);
-
-       HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock);
+               HA_RWLOCK_WRTORD(STK_TABLE_LOCK, &st->table->lock);
+       else
+               HA_RWLOCK_RDLOCK(STK_TABLE_LOCK, &st->table->lock);
 
        while (1) {
                struct stksess *ts;
@@ -1600,10 +1600,10 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p,
                }
 
                HA_ATOMIC_INC(&ts->ref_cnt);
-               HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock);
+               HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &st->table->lock);
 
                ret = peer_send_updatemsg(st, appctx, ts, updateid, new_pushed, use_timed);
-               HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock);
+               HA_RWLOCK_RDLOCK(STK_TABLE_LOCK, &st->table->lock);
                HA_ATOMIC_DEC(&ts->ref_cnt);
                if (ret <= 0)
                        break;
@@ -1635,7 +1635,7 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p,
        }
 
  out:
-       HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock);
+       HA_RWLOCK_RDUNLOCK(STK_TABLE_LOCK, &st->table->lock);
 
        if (locked)
                HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock);