{
struct stksess *ts;
struct eb32_node *eb;
+ struct list tofree_list;
int max_search; // no more than 50% misses
int max_per_bucket;
int done_per_bucket;
/* start from a random bucket number to avoid starvation in the last ones */
bucket = init_bucket = statistical_prng_range(CONFIG_HAP_TBL_BUCKETS - 1);
-
+ LIST_INIT(&tofree_list);
to_batch = STKTABLE_MAX_UPDATES_AT_ONCE;
max_search = to_batch * 2; // no more than 50% misses
ebmb_delete(&ts->key);
MT_LIST_DELETE(&ts->pend_updts);
eb32_delete(&ts->upd);
- __stksess_free(t, ts);
+ LIST_APPEND(&tofree_list, mt_list_to_list(&ts->pend_updts));
+
batched++;
done_per_bucket++;
bucket = 0;
} while (max_search > 0 && bucket != init_bucket);
+ while (!LIST_ISEMPTY(&tofree_list)) {
+ ts = LIST_ELEM(tofree_list.n, struct stksess *, pend_updts);
+ LIST_DELETE(mt_list_to_list(&ts->pend_updts));
+ __stksess_free(t, ts);
+ }
+
return batched;
}
struct stktable *t;
struct stksess *ts;
struct eb32_node *table_eb, *eb;
+ struct list tofree_list;
int updt_locked;
int to_visit;
int task_exp;
task_exp = TICK_ETERNITY;
+ LIST_INIT(&tofree_list);
+
bucket = (ps - &per_bucket[0]);
to_visit = STKTABLE_MAX_UPDATES_AT_ONCE;
ebmb_delete(&ts->key);
MT_LIST_DELETE(&ts->pend_updts);
eb32_delete(&ts->upd);
- __stksess_free(t, ts);
+ LIST_APPEND(&tofree_list, mt_list_to_list(&ts->pend_updts));
}
if (updt_locked)
if (!tick_isset(task_exp) || (tick_isset(next_exp_table) && tick_is_lt(next_exp_table, task_exp)))
task_exp = next_exp_table;
HA_RWLOCK_WRUNLOCK(STK_TABLE_LOCK, &t->buckets[bucket].sh_lock);
+
+ while (!LIST_ISEMPTY(&tofree_list)) {
+ ts = LIST_ELEM(tofree_list.n, struct stksess *, pend_updts);
+ LIST_DELETE(mt_list_to_list(&ts->pend_updts));
+ __stksess_free(t, ts);
+ }
+
tmpnode = eb32_next(table_eb);
if (table_eb->key != next_exp_table) {