From dbae89e09cc80cc14e50a8e00f53848a1591b302 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 12 Oct 2022 10:00:50 +0000 Subject: [PATCH] MEDIUM: stick-table: always use atomic ops to requeue the table's task We're generalizing the change performed in previous commit "MEDIUM: stick-table: requeue the expiration task out of the exclusive lock" to stktable_requeue_exp() so that it can also be used by callers of __stktable_store(). At the moment there's still no visible change since it's still called under the write lock. However, the previous code in stitable_touch_with_exp() was updated to use this function. --- include/haproxy/stick_table.h | 1 + src/stick_table.c | 47 +++++++++++++++++------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/haproxy/stick_table.h b/include/haproxy/stick_table.h index c5cd3c8fe2..e78bbd646c 100644 --- a/include/haproxy/stick_table.h +++ b/include/haproxy/stick_table.h @@ -50,6 +50,7 @@ int parse_stick_table(const char *file, int linenum, char **args, struct stktable *t, char *id, char *nid, struct peers *peers); struct stksess *stktable_get_entry(struct stktable *table, struct stktable_key *key); struct stksess *stktable_set_entry(struct stktable *table, struct stksess *nts); +void stktable_requeue_exp(struct stktable *t, const struct stksess *ts); void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int decrefcount, int expire, int decrefcnt); void stktable_touch_remote(struct stktable *t, struct stksess *ts, int decrefcnt); void stktable_touch_local(struct stktable *t, struct stksess *ts, int decrefccount); diff --git a/src/stick_table.c b/src/stick_table.c index facd5fa786..57c1b17757 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -378,32 +378,11 @@ void stktable_touch_with_exp(struct stktable *t, struct stksess *ts, int local, { struct eb32_node * eb; int locked = 0; - int old_exp, new_exp; if (expire != HA_ATOMIC_LOAD(&ts->expire)) { /* we'll need to set the expiration and to wake up the expiration timer .*/ HA_ATOMIC_STORE(&ts->expire, expire); - if (t->expire) { - /* set both t->exp_next and the task's expire to the newest - * expiration date. - */ - old_exp = HA_ATOMIC_LOAD(&t->exp_next); - do { - new_exp = tick_first(expire, old_exp); - } while (new_exp != old_exp && - !HA_ATOMIC_CAS(&t->exp_next, &old_exp, new_exp) && - __ha_cpu_relax()); - - old_exp = HA_ATOMIC_LOAD(&t->exp_task->expire); - do { - new_exp = HA_ATOMIC_LOAD(&t->exp_next); - } while (new_exp != old_exp && - !HA_ATOMIC_CAS(&t->exp_task->expire, &old_exp, new_exp) && - __ha_cpu_relax()); - - task_queue(t->exp_task); - /* keep the lock */ - } + stktable_requeue_exp(t, ts); } /* If sync is enabled */ @@ -516,11 +495,31 @@ struct stksess *__stktable_store(struct stktable *t, struct stksess *ts) /* requeues the table's expiration task to take the recently added into * account. This is performed atomically and doesn't require any lock. */ -static void stktable_requeue_exp(struct stktable *t, const struct stksess *ts) +void stktable_requeue_exp(struct stktable *t, const struct stksess *ts) { + int old_exp, new_exp; + int expire = ts->expire; + if (!t->expire) return; - t->exp_task->expire = t->exp_next = tick_first(ts->expire, t->exp_next); + + /* set both t->exp_next and the task's expire to the newest + * expiration date. + */ + old_exp = HA_ATOMIC_LOAD(&t->exp_next); + do { + new_exp = tick_first(expire, old_exp); + } while (new_exp != old_exp && + !HA_ATOMIC_CAS(&t->exp_next, &old_exp, new_exp) && + __ha_cpu_relax()); + + old_exp = HA_ATOMIC_LOAD(&t->exp_task->expire); + do { + new_exp = HA_ATOMIC_LOAD(&t->exp_next); + } while (new_exp != old_exp && + !HA_ATOMIC_CAS(&t->exp_task->expire, &old_exp, new_exp) && + __ha_cpu_relax()); + task_queue(t->exp_task); }