From: Willy Tarreau Date: Tue, 11 Oct 2022 10:02:50 +0000 (+0200) Subject: MEDIUM: stick-table: switch the table lock to rwlock X-Git-Tag: v2.7-dev8~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=76642223f014f89cd1f374291798499f4fba7dde;p=thirdparty%2Fhaproxy.git MEDIUM: stick-table: switch the table lock to rwlock Right now a spinlock is used, but most accesses are for reads, so let's switch the lock to an rwlock and switch all accesses to exclusive locks for now. There should be no visible difference at this point. --- diff --git a/include/haproxy/stick_table-t.h b/include/haproxy/stick_table-t.h index 57888e041a..b423f2d276 100644 --- a/include/haproxy/stick_table-t.h +++ b/include/haproxy/stick_table-t.h @@ -199,7 +199,7 @@ struct stktable { const char *file; /* The file where the stick-table is declared. */ int line; /* The line in this the stick-table is declared. */ } conf; - __decl_thread(HA_SPINLOCK_T lock); /* spin lock related to the table */ + __decl_thread(HA_RWLOCK_T lock); /* lock related to the table */ }; extern struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES]; diff --git a/include/haproxy/stick_table.h b/include/haproxy/stick_table.h index d5a56d11bf..a495e7738e 100644 --- a/include/haproxy/stick_table.h +++ b/include/haproxy/stick_table.h @@ -198,7 +198,7 @@ static inline int __stksess_kill_if_expired(struct stktable *t, struct stksess * static inline void stksess_kill_if_expired(struct stktable *t, struct stksess *ts, int decrefcnt) { - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); if (decrefcnt) ts->ref_cnt--; @@ -206,7 +206,7 @@ static inline void stksess_kill_if_expired(struct stktable *t, struct stksess *t if (t->expire != TICK_ETERNITY && tick_is_expired(ts->expire, now_ms)) __stksess_kill_if_expired(t, ts); - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); } /* sets the stick counter's entry pointer */ diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index 0046e9ede4..975ed246ea 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -649,9 +649,9 @@ int hlua_stktable_lookup(lua_State *L) lua_settable(L, -3); hlua_stktable_entry(L, t, ts); - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ts->ref_cnt--; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return 1; } @@ -761,16 +761,16 @@ int hlua_stktable_dump(lua_State *L) lua_newtable(L); - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); eb = ebmb_first(&t->keys); for (n = eb; n; n = ebmb_next(n)) { ts = ebmb_entry(n, struct stksess, key); if (!ts) { - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return 1; } ts->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); /* multi condition/value filter */ skip_entry = 0; @@ -810,7 +810,7 @@ int hlua_stktable_dump(lua_State *L) } if (skip_entry) { - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ts->ref_cnt--; continue; } @@ -834,10 +834,10 @@ int hlua_stktable_dump(lua_State *L) lua_newtable(L); hlua_stktable_entry(L, t, ts); lua_settable(L, -3); - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ts->ref_cnt--; } - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return 1; } diff --git a/src/peers.c b/src/peers.c index d4aa69f232..e0fedbdb4a 100644 --- a/src/peers.c +++ b/src/peers.c @@ -1583,7 +1583,7 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, new_pushed = 1; if (!locked) - HA_SPIN_LOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock); while (1) { struct stksess *ts; @@ -1598,16 +1598,16 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, updateid = ts->upd.key; ts->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock); ret = peer_send_updatemsg(st, appctx, ts, updateid, new_pushed, use_timed); if (ret <= 0) { - HA_SPIN_LOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock); ts->ref_cnt--; break; } - HA_SPIN_LOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock); ts->ref_cnt--; st->last_pushed = updateid; @@ -1631,7 +1631,7 @@ static inline int peer_send_teachmsgs(struct appctx *appctx, struct peer *p, out: if (!locked) - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock); return ret; } @@ -2585,17 +2585,17 @@ static inline int peer_send_msgs(struct appctx *appctx, } if (!(peer->flags & PEER_F_TEACH_PROCESS)) { - HA_SPIN_LOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock); if (!(peer->flags & PEER_F_LEARN_ASSIGN) && (st->last_pushed != st->table->localupdate)) { repl = peer_send_teach_process_msgs(appctx, peer, st); if (repl <= 0) { - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock); return repl; } } - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock); } else if (!(peer->flags & PEER_F_TEACH_FINISHED)) { if (!(st->flags & SHTABLE_F_TEACH_STAGE1)) { @@ -2774,7 +2774,7 @@ static inline void init_accepted_peer(struct peer *peer, struct peers *peers) /* Init cursors */ for (st = peer->tables; st ; st = st->next) { st->last_get = st->last_acked = 0; - HA_SPIN_LOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock); /* if st->update appears to be in future it means * that the last acked value is very old and we * remain unconnected a too long time to use this @@ -2790,7 +2790,7 @@ static inline void init_accepted_peer(struct peer *peer, struct peers *peers) st->flags = 0; if ((int)(st->last_pushed - st->table->commitupdate) > 0) st->table->commitupdate = st->last_pushed; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock); } /* reset teaching and learning flags to 0 */ @@ -2829,7 +2829,7 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers) /* Init cursors */ for (st = peer->tables; st ; st = st->next) { st->last_get = st->last_acked = 0; - HA_SPIN_LOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &st->table->lock); /* if st->update appears to be in future it means * that the last acked value is very old and we * remain unconnected a too long time to use this @@ -2845,7 +2845,7 @@ static inline void init_connected_peer(struct peer *peer, struct peers *peers) st->flags = 0; if ((int)(st->last_pushed - st->table->commitupdate) > 0) st->table->commitupdate = st->last_pushed; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &st->table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &st->table->lock); } /* Init confirm counter */ diff --git a/src/stick_table.c b/src/stick_table.c index b1e7b59a5e..4e26a3ffdf 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -103,9 +103,9 @@ void stksess_free(struct stktable *t, struct stksess *ts) dict_entry_unref(&server_key_dict, stktable_data_cast(data, std_t_dict)); stktable_data_cast(data, std_t_dict) = NULL; } - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); __stksess_free(t, ts); - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); } /* @@ -132,11 +132,11 @@ int stksess_kill(struct stktable *t, struct stksess *ts, int decrefcnt) { int ret; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); if (decrefcnt) ts->ref_cnt--; ret = __stksess_kill(t, ts); - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return ret; } @@ -249,9 +249,9 @@ int stktable_trash_oldest(struct stktable *t, int to_batch) { int ret; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ret = __stktable_trash_oldest(t, to_batch); - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return ret; } @@ -297,9 +297,9 @@ struct stksess *stksess_new(struct stktable *t, struct stktable_key *key) { struct stksess *ts; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ts = __stksess_new(t, key); - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return ts; } @@ -335,11 +335,11 @@ struct stksess *stktable_lookup_key(struct stktable *t, struct stktable_key *key { struct stksess *ts; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ts = __stktable_lookup_key(t, key); if (ts) ts->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return ts; } @@ -373,11 +373,11 @@ struct stksess *stktable_lookup(struct stktable *t, struct stksess *ts) { struct stksess *lts; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); lts = __stktable_lookup(t, ts); if (lts) lts->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return lts; } @@ -437,11 +437,11 @@ void __stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local */ void stktable_touch_remote(struct stktable *t, struct stksess *ts, int decrefcnt) { - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); __stktable_touch_with_exp(t, ts, 0, ts->expire); if (decrefcnt) ts->ref_cnt--; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); } /* Update the expiration timer for but do not touch its expiration node. @@ -454,20 +454,20 @@ void stktable_touch_local(struct stktable *t, struct stksess *ts, int decrefcnt) { int expire = tick_add(now_ms, MS_TO_TICKS(t->expire)); - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); __stktable_touch_with_exp(t, ts, 1, expire); if (decrefcnt) ts->ref_cnt--; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); } /* Just decrease the ref_cnt of the current session. Does nothing if is NULL */ static void stktable_release(struct stktable *t, struct stksess *ts) { if (!ts) return; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); ts->ref_cnt--; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); } /* Insert new sticky session in the table. It is assumed that it does not @@ -516,11 +516,11 @@ struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key * { struct stksess *ts; - HA_SPIN_LOCK(STK_TABLE_LOCK, &table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &table->lock); ts = __stktable_get_entry(table, key); if (ts) ts->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &table->lock); return ts; } @@ -548,10 +548,10 @@ struct stksess *stktable_set_entry(struct stktable *table, struct stksess *nts) { struct stksess *ts; - HA_SPIN_LOCK(STK_TABLE_LOCK, &table->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &table->lock); ts = __stktable_set_entry(table, nts); ts->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &table->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &table->lock); return ts; } @@ -565,7 +565,7 @@ static int stktable_trash_expired(struct stktable *t) struct eb32_node *eb; int looped = 0; - HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &t->lock); eb = eb32_lookup_ge(&t->exps, now_ms - TIMER_LOOK_BACK); while (1) { @@ -620,7 +620,7 @@ static int stktable_trash_expired(struct stktable *t) /* We have found no task to expire in any tree */ t->exp_next = TICK_ETERNITY; out_unlock: - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->lock); return t->exp_next; } @@ -4783,16 +4783,16 @@ static int cli_io_handler_table(struct appctx *appctx) if (ctx->target && (strm_li(s)->bind_conf->level & ACCESS_LVL_MASK) >= ACCESS_LVL_OPER) { /* dump entries only if table explicitly requested */ - HA_SPIN_LOCK(STK_TABLE_LOCK, &ctx->t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &ctx->t->lock); eb = ebmb_first(&ctx->t->keys); if (eb) { ctx->entry = ebmb_entry(eb, struct stksess, key); ctx->entry->ref_cnt++; ctx->state = STATE_DUMP; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &ctx->t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &ctx->t->lock); break; } - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &ctx->t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &ctx->t->lock); } } ctx->t = ctx->t->next; @@ -4860,7 +4860,7 @@ static int cli_io_handler_table(struct appctx *appctx) HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ctx->entry->lock); - HA_SPIN_LOCK(STK_TABLE_LOCK, &ctx->t->lock); + HA_RWLOCK_WRLOCK(STK_TABLE_LOCK, &ctx->t->lock); ctx->entry->ref_cnt--; eb = ebmb_next(&ctx->entry->key); @@ -4872,7 +4872,7 @@ static int cli_io_handler_table(struct appctx *appctx) else if (!skip_entry && !ctx->entry->ref_cnt) __stksess_kill(ctx->t, old); ctx->entry->ref_cnt++; - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &ctx->t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &ctx->t->lock); break; } @@ -4882,7 +4882,7 @@ static int cli_io_handler_table(struct appctx *appctx) else if (!skip_entry && !ctx->entry->ref_cnt) __stksess_kill(ctx->t, ctx->entry); - HA_SPIN_UNLOCK(STK_TABLE_LOCK, &ctx->t->lock); + HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &ctx->t->lock); ctx->t = ctx->t->next; ctx->state = STATE_NEXT;