]> err.no Git - varnish/commitdiff
Store stevedores in a circular list. The head pointer keeps moving from
authordes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 20 Jul 2007 10:23:12 +0000 (10:23 +0000)
committerdes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Fri, 20 Jul 2007 10:23:12 +0000 (10:23 +0000)
one stevedore to the next.  The LRU code is invoked as soon as any of the
stevedores fills up.

This algorithm is far from ideal, and will not work well with differently
sized stevedores, but it has the advantage of being simple and lock-free.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1734 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/stevedore.c
varnish-cache/bin/varnishd/stevedore.h

index b018e3f11ce31dac0b76b5b4431ff15d1d26b8ec..79352dfa7b273bfd2a7338bb9c8bd57b6abb72f2 100644 (file)
 #include "heritage.h"
 #include "stevedore.h"
 
+/*
+ * Stevedores are kept in a circular list with the head pointer
+ * continuously moving from one element to the next.
+ */
+
 extern struct stevedore sma_stevedore;
 extern struct stevedore smf_stevedore;
 
-static TAILQ_HEAD(stevedore_head, stevedore) stevedores;
+static struct stevedore * volatile stevedores;
 
 struct storage *
 STV_alloc(size_t size)
 {
        struct storage *st;
-       struct stevedore *stv, *stv_first;
+       struct stevedore *stv;
 
-       /* Simple round robin selecting of a stevedore. */
-       stv_first = TAILQ_FIRST(&stevedores);
-       stv = stv_first;
-       do {
-               AN(stv->alloc);
-               st = stv->alloc(stv, size);
-               TAILQ_REMOVE(&stevedores, stv, stevedore_list);
-               TAILQ_INSERT_TAIL(&stevedores, stv, stevedore_list);
-               if (st != NULL)
-                       return (st);
-       } while ((stv = TAILQ_FIRST(&stevedores)) != stv_first);
+       for (;;) {
+               /* pick a stevedore and bump the head along */
+               stv = stevedores = stevedores->next;
 
-       /* No stevedore with enough space is found. Make room in the first
-        * one in the list, and move it to the end. Ensuring the round-robin.
-        */
-       stv = TAILQ_FIRST(&stevedores);
-       TAILQ_REMOVE(&stevedores, stv, stevedore_list);
-       TAILQ_INSERT_TAIL(&stevedores, stv, stevedore_list);
-
-       do {
-               if ((st = stv->alloc(stv, size)) == NULL)
-                       AN(LRU_DiscardOne());
-       } while (st == NULL);
+               /* try to allocate from it */
+               if ((st = stv->alloc(stv, size)) != NULL) {
+                       CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
+                       return (st);
+               }
 
-       return (st);
+               /* no luck; free some space and keep trying */
+               AN(LRU_DiscardOne());
+       }
 }
 
 void
 STV_trim(struct storage *st, size_t size)
 {
 
+       CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
        AN(st->stevedore);
        if (st->stevedore->trim)
                st->stevedore->trim(st, size);
@@ -87,6 +81,7 @@ void
 STV_free(struct storage *st)
 {
 
+       CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
        AN(st->stevedore);
        AN(st->stevedore->free);
        st->stevedore->free(st);
@@ -106,7 +101,7 @@ void
 STV_add(const char *spec)
 {
        const char *p, *q;
-       struct stevedore *stp;
+       struct stevedore *stv;
 
        p = strchr(spec, ',');
        if (p == NULL)
@@ -116,29 +111,42 @@ STV_add(const char *spec)
        xxxassert(p != NULL);
        xxxassert(q != NULL);
 
-       stp = malloc(sizeof *stp);
+       stv = malloc(sizeof *stv);
 
        if (!cmp_storage(&sma_stevedore, spec, p)) {
-               *stp = sma_stevedore;
+               *stv = sma_stevedore;
        } else if (!cmp_storage(&smf_stevedore, spec, p)) {
-               *stp = smf_stevedore;
+               *stv = smf_stevedore;
        } else {
                fprintf(stderr, "Unknown storage method \"%.*s\"\n",
                    (int)(p - spec), spec);
                exit (2);
        }
-       TAILQ_INSERT_HEAD(&stevedores, stp, stevedore_list);
-       if (stp->init != NULL)
-               stp->init(stp, q);
+       if (stv->init != NULL)
+               stv->init(stv, q);
+
+       if (!stevedores) {
+               fprintf(stderr, "first stevedore\n");
+               stevedores = stv->next = stv->prev = stv;
+       } else {
+               fprintf(stderr, "additional stevedore\n");
+               stv->next = stevedores;
+               stv->prev = stevedores->prev;
+               stv->next->prev = stv;
+               stv->prev->next = stv;
+               stevedores = stv;
+       }
 }
 
 void
 STV_open(void)
 {
-       struct stevedore *st;
+       struct stevedore *stv;
 
-       TAILQ_FOREACH(st, &stevedores, stevedore_list) {
-               if (st->open != NULL)
-                       st->open(st);
-       }
+       stv = stevedores;
+       do {
+               if (stv->open != NULL)
+                       stv->open(stv);
+               stv = stv->next;
+       } while (stv != stevedores);
 }
index 119036a4b3be4e8aa91293449101b9f2bcb7de84..364bcf433f8d909b679baa8d1108fc889336efe6 100644 (file)
@@ -28,7 +28,6 @@
  *
  * $Id$
  */
 
 #include "queue.h"
 
@@ -52,7 +51,8 @@ struct stevedore {
 
        /* private fields */
        void                    *priv;
-       TAILQ_ENTRY(stevedore)  stevedore_list;
+
+       struct stevedore        *next, *prev;
 };
 
 struct storage *STV_alloc(size_t size);