Mailing List Archive

r873 - trunk/varnish-cache/bin/varnishd
Author: phk
Date: 2006-08-21 19:32:41 +0200 (Mon, 21 Aug 2006)
New Revision: 873

Modified:
trunk/varnish-cache/bin/varnishd/cache_session.c
Log:
Retire sessions if the workspace size changes, properly cache the
workspace size so we do not get caught unaware when it changes.

Implement flip-flop free queue where SES_New() can read from
one of them without a lock, which frees happen to the other one
under lock. If the lock-less queue is empty, SES_New() flips
the two queues under lock and tries again. If that queue is
also empty call malloc(3).



Modified: trunk/varnish-cache/bin/varnishd/cache_session.c
===================================================================
--- trunk/varnish-cache/bin/varnishd/cache_session.c 2006-08-21 17:26:11 UTC (rev 872)
+++ trunk/varnish-cache/bin/varnishd/cache_session.c 2006-08-21 17:32:41 UTC (rev 873)
@@ -33,14 +33,19 @@
struct sess sess;
struct http http;
struct sockaddr sockaddr[2]; /* INET6 hack */
+ unsigned workspace;
TAILQ_ENTRY(sessmem) list;
};

/*--------------------------------------------------------------------*/

-static TAILQ_HEAD(,sessmem) ses_free_mem =
- TAILQ_HEAD_INITIALIZER(ses_free_mem);
+static TAILQ_HEAD(,sessmem) ses_free_mem[2] = {
+ TAILQ_HEAD_INITIALIZER(ses_free_mem[0]),
+ TAILQ_HEAD_INITIALIZER(ses_free_mem[1]),
+};

+static unsigned ses_qp;
+
TAILQ_HEAD(srcaddrhead ,srcaddr);
static struct srcaddrhead srcaddr_hash[CLIENT_HASH];
static pthread_mutex_t ses_mtx;
@@ -188,15 +193,37 @@
SES_New(struct sockaddr *addr, unsigned len)
{
struct sessmem *sm;
+ unsigned u;

- AZ(pthread_mutex_lock(&ses_mem_mtx));
- sm = TAILQ_FIRST(&ses_free_mem);
- if (sm != NULL)
- TAILQ_REMOVE(&ses_free_mem, sm, list);
- AZ(pthread_mutex_unlock(&ses_mem_mtx));
+
+ /*
+ * One of the two queues is unlocked because only one
+ * thread ever gets here to empty it.
+ */
+ assert(ses_qp <= 1);
+ sm = TAILQ_FIRST(&ses_free_mem[ses_qp]);
if (sm == NULL) {
- sm = calloc(sizeof *sm + params->mem_workspace, 1);
+ /*
+ * If that queue is empty, flip queues holding the lock
+ * and try the new unlocked queue.
+ */
+ AZ(pthread_mutex_lock(&ses_mem_mtx));
+ ses_qp = 1 - ses_qp;
+ AZ(pthread_mutex_unlock(&ses_mem_mtx));
+ sm = TAILQ_FIRST(&ses_free_mem[ses_qp]);
+ }
+ if (sm != NULL) {
+ TAILQ_REMOVE(&ses_free_mem[ses_qp], sm, list);
+ } else {
+ /*
+ * If that fails, alloc new one.
+ */
+ u = params->mem_workspace;
+ sm = malloc(sizeof *sm + u);
+ if (sm == NULL)
+ return (NULL);
sm->magic = SESSMEM_MAGIC;
+ sm->workspace = u;
VSL_stats->n_sess_mem++;
}
if (sm == NULL)
@@ -215,7 +242,7 @@
sm->sess.sockaddrlen = len;
}

- http_Setup(&sm->http, (void *)(sm + 1), params->mem_workspace);
+ http_Setup(&sm->http, (void *)(sm + 1), sm->workspace);

sm->sess.acct.first = time(NULL);

@@ -226,8 +253,12 @@
SES_Delete(struct sess *sp)
{
struct acct *b = &sp->acct;
+ struct sessmem *sm;

CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
+ sm = sp->mem;
+ CHECK_OBJ_NOTNULL(sm, SESSMEM_MAGIC);
+
assert(sp->obj == NULL);
assert(sp->vcl == NULL);
VSL_stats->n_sess--;
@@ -236,10 +267,14 @@
sp->addr, sp->port, time(NULL) - b->first,
b->sess, b->req, b->pipe, b->pass,
b->fetch, b->hdrbytes, b->bodybytes);
- CHECK_OBJ_NOTNULL(sp->mem, SESSMEM_MAGIC);
- AZ(pthread_mutex_lock(&ses_mem_mtx));
- TAILQ_INSERT_HEAD(&ses_free_mem, sp->mem, list);
- AZ(pthread_mutex_unlock(&ses_mem_mtx));
+ if (sm->workspace != params->mem_workspace) {
+ VSL_stats->n_sess_mem--;
+ free(sm);
+ } else {
+ AZ(pthread_mutex_lock(&ses_mem_mtx));
+ TAILQ_INSERT_HEAD(&ses_free_mem[1 - ses_qp], sm, list);
+ AZ(pthread_mutex_unlock(&ses_mem_mtx));
+ }
}

/*--------------------------------------------------------------------*/