]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: shctx: Move list between hot and avail list in O(1)
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 16 Nov 2023 16:38:12 +0000 (17:38 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 16 Nov 2023 18:35:10 +0000 (19:35 +0100)
Instead of iterating over all the elements of a given row when moving it
between the hot and available lists, we can make use of the last_reserved
pointer that already points to the last block of the list to perform the
move in O(1).

src/shctx.c

index 862adb68badc492f59b9ed8c05a9a99aad228793..19394fa175e37c6eaf7623467a0a19e5915e0729 100644 (file)
@@ -145,21 +145,21 @@ out:
  */
 void shctx_row_inc_hot(struct shared_context *shctx, struct shared_block *first)
 {
-       struct shared_block *block, *sblock;
-       int count = 0;
-
        if (first->refcount <= 0) {
 
-               block = first;
+               BUG_ON(!first->last_reserved);
 
-               list_for_each_entry_safe_from(block, sblock, &shctx->avail, list) {
+               /* Detach row from avail list, link first item's prev to last
+                * item's next. This allows to use the LIST_SPLICE_END_DETACHED
+                * macro. */
+               first->list.p->n = first->last_reserved->list.n;
+               first->last_reserved->list.n->p = first->list.p;
 
-                       shctx_block_set_hot(shctx, block);
+               /* Reattach to hot list */
+               first->list.p = &first->last_reserved->list;
+               LIST_SPLICE_END_DETACHED(&shctx->hot, &first->list);
 
-                       count++;
-                       if (count >= first->block_count)
-                               break;
-               }
+               shctx->nbav -= first->block_count;
        }
 
        first->refcount++;
@@ -170,25 +170,24 @@ void shctx_row_inc_hot(struct shared_context *shctx, struct shared_block *first)
  */
 void shctx_row_dec_hot(struct shared_context *shctx, struct shared_block *first)
 {
-       struct shared_block *block, *sblock;
-       int count = 0;
-
        first->refcount--;
 
        if (first->refcount <= 0) {
 
-               block = first;
+               BUG_ON(!first->last_reserved);
 
-               list_for_each_entry_safe_from(block, sblock, &shctx->hot, list) {
+               /* Detach row from hot list, link first item's prev to last
+                * item's next. This allows to use the LIST_SPLICE_END_DETACHED
+                * macro. */
+               first->list.p->n = first->last_reserved->list.n;
+               first->last_reserved->list.n->p = first->list.p;
 
-                       shctx_block_set_avail(shctx, block);
+               /* Reattach to avail list */
+               first->list.p = &first->last_reserved->list;
+               LIST_SPLICE_END_DETACHED(&shctx->avail, &first->list);
 
-                       count++;
-                       if (count >= first->block_count)
-                               break;
-               }
+               shctx->nbav += first->block_count;
        }
-
 }