MEDIUM: peers: only read-lock peer_send_teachmsgs()

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.
This commit is contained in:
Willy Tarreau 2023-08-07 19:39:27 +02:00
parent d4f8286e45
commit 29982ea769

View 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);