r873 - trunk/varnish-cache/bin/varnishd

phk at projects.linpro.no phk at projects.linpro.no
Mon Aug 21 19:32:41 CEST 2006


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));
+	}
 }
 
 /*--------------------------------------------------------------------*/




More information about the varnish-commit mailing list