[SSI] openssi/kernel/cluster/ssi/token tokseq.c,1.11,1.12

Roger Tsang <[email protected]> Tue, 25 Jan 2011 06:04:21 +0000
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv24579/cluster/ssi/token

Modified Files:
      Tag: OPENSSI-FC
	tokseq.c 
Log Message:
- insert_queue: always inline.
- tokseq_accept: indicate to compiler unlikely branch direction.
- tokseq_accept: access tqentry structure outside critical section. reduce contention over ts_lock in tokseq structure.
- tokseq_accept: reduce stack usage in local scope.
- tokseq_accept: immediately process items with seqnum 0 which could be items created while TSF_DOWN flag was set. we would see these items if we lost the race with tokseq_cleanup(). fix items stuck in queue.


Index: tokseq.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/tokseq.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- tokseq.c	25 Jan 2011 05:51:26 -0000	1.11
+++ tokseq.c	25 Jan 2011 06:04:19 -0000	1.12
@@ -104,7 +104,7 @@
 int tokseq_qlen_found = FALSE;
 #endif
 
-STATIC void
+static inline void
 insert_queue(tqentry_t **tqpp, tqentry_t *newtqp, tokseqnum_t base_seq)
 {
 	/* Find insertion point */
@@ -154,16 +154,18 @@
 	UNLOCK_COND_LOCK(&tsp->ts_lock);
 }
 
-/* Called w. tcb locked (via whatever means).
- * Could be a macro for speed.
+/**
+ * tokseq_accept - process or queue sequenced item
+ *
+ * Process item now if the item is in sequence. Otherwise queue the item.
+ *
+ * Not called with tcb locked. serverfunc() may acquire tcb lock.
  */
-/* SSI_XXX: Not called with tcb locked. serverfunc() may acquire tcb lock. */
 void
 tokseq_accept(tokseq_t *tsp, int agent, tokseqnum_t recvd,
 	void (*serverfunc)(void *), void *args, int argsize,
 	void *(*dupfunc)(void *), void (*freefunc)(void *))
 {
-	void *save;
 	tqentry_t *tqp;
 
 	SSI_ASSERT(agent > 0 && agent <= tsp->ts_num_conns);
@@ -173,54 +175,58 @@
 #endif
 
 	LOCK_COND_LOCK(&tsp->ts_lock);
-	if (tsp->ts_conns[agent].tsp_flags & TSF_DOWN) {
+	if (unlikely(tsp->ts_conns[agent].tsp_flags & TSF_DOWN)) {
 		UNLOCK_COND_LOCK(&tsp->ts_lock);
 		return;
 	}
-	if (recvd != tsp->ts_conns[agent].tsp_expect) {
-
+	/* Special case: all items have seqnum 0 when TSF_DOWN flag was set
+	 * during tokseq_getseq() and we lost the race with tokseq_cleanup().
+	 * Process those with recvd = 0 immediately.
+	 */
+	if (recvd && recvd != tsp->ts_conns[agent].tsp_expect) {
 		UNLOCK_COND_LOCK(&tsp->ts_lock);
+
+		tqp = KMEM_SLEEP_ALLOC(sizeof(tqentry_t));
+		tqp->tsq_seq = recvd;
+		tqp->tsq_serverfunc = serverfunc;
+		tqp->tsq_freefunc = freefunc;
+		tqp->tsq_argsize = argsize;
 		if (dupfunc)
-			save = (*dupfunc)(args);
+			tqp->tsq_args = (*dupfunc)(args);
 		else {
 			/* Queue up this arg */
-			save = KMEM_SLEEP_ALLOC(argsize);
-			bcopy(args, save, argsize);
+			tqp->tsq_args = KMEM_SLEEP_ALLOC(argsize);
+			bcopy(args, tqp->tsq_args, argsize);
 		}
-		tqp = KMEM_SLEEP_ALLOC(sizeof(tqentry_t));
+
 		LOCK_COND_LOCK(&tsp->ts_lock);
 
 		/* Make sure that node is still up */
-		if (tsp->ts_conns[agent].tsp_flags & TSF_DOWN) {
+		if (unlikely(tsp->ts_conns[agent].tsp_flags & TSF_DOWN)) {
 			UNLOCK_COND_LOCK(&tsp->ts_lock);
-			/* free memory */
-			KMEM_SLEEP_FREE(tqp, sizeof(tqentry_t));
 			if (freefunc)
-				(*freefunc)(save);
+				(*freefunc)(tqp->tsq_args);
 			else
-				KMEM_SLEEP_FREE(save, argsize);
+				KMEM_SLEEP_FREE(tqp->tsq_args, argsize);
+			KMEM_SLEEP_FREE(tqp, sizeof(tqentry_t));
 			return;
 		}
 		/* If we are now in sequence, since memory allocation,
 		 * free memory and run the server.
 		 */
 		if (recvd == tsp->ts_conns[agent].tsp_expect) {
-			KMEM_SLEEP_FREE(tqp, sizeof(tqentry_t));
+			UNLOCK_COND_LOCK(&tsp->ts_lock);
 			if (freefunc)
-				(*freefunc)(save);
+				(*freefunc)(tqp->tsq_args);
 			else
-				KMEM_SLEEP_FREE(save, argsize);
+				KMEM_SLEEP_FREE(tqp->tsq_args, argsize);
+			KMEM_SLEEP_FREE(tqp, sizeof(tqentry_t));
 			goto no_queue;
 		}
 
-		tqp->tsq_seq = recvd;
-		tqp->tsq_args = save;
-		tqp->tsq_argsize = argsize;
-		tqp->tsq_serverfunc = serverfunc;
-		tqp->tsq_freefunc = freefunc;
-
 		/* Insert operation in sequence order */
-		insert_queue(&tsp->ts_conns[agent].tsp_queue, tqp, tsp->ts_conns[agent].tsp_expect);
+		insert_queue(&tsp->ts_conns[agent].tsp_queue, tqp,
+					tsp->ts_conns[agent].tsp_expect);
 		tsp->ts_conns[agent].tsp_qlen++;
 #ifdef DEBUG
 		tokseq_queue++;
@@ -242,9 +248,8 @@
 		UNLOCK_COND_LOCK(&tsp->ts_lock);
 		return;
 	}
-
-no_queue:
 	UNLOCK_COND_LOCK(&tsp->ts_lock);
+no_queue:
 
 	/* We are in sequence, so just run the server code */
 	(*serverfunc)(args);
@@ -267,23 +272,12 @@
 	}
 
 	/* Queue not empty and front of queue in sequence */
-	while (tsp->ts_conns[agent].tsp_queue &&
-	    (tsp->ts_conns[agent].tsp_queue->tsq_seq ==
-	    tsp->ts_conns[agent].tsp_expect)) {
-		int curseq;
-
-		tqp = tsp->ts_conns[agent].tsp_queue;
-
-		curseq = tqp->tsq_seq;
-		serverfunc = tqp->tsq_serverfunc;
-		args = tqp->tsq_args;
-		argsize = tqp->tsq_argsize;
-		freefunc = tqp->tsq_freefunc;
-
+	while ((tqp = tsp->ts_conns[agent].tsp_queue)) {
+		if (tqp->tsq_seq != tsp->ts_conns[agent].tsp_expect)
+			break;
 		/* Remove front of list */
 		tsp->ts_conns[agent].tsp_queue = tqp->tsq_next;
 		tsp->ts_conns[agent].tsp_qlen--;
-
 		UNLOCK_COND_LOCK(&tsp->ts_lock);
 
 #ifdef DEBUG
@@ -293,6 +287,11 @@
 				(int)tsp, agent);
 		}
 #endif
+		recvd = tqp->tsq_seq;
+		serverfunc = tqp->tsq_serverfunc;
+		freefunc = tqp->tsq_freefunc;
+		args = tqp->tsq_args;
+		argsize = tqp->tsq_argsize;
 
 		/* We are in sequence, so just run the server code */
 		(*serverfunc)(args);
@@ -306,12 +305,12 @@
 #ifdef DEBUG
 		if (tokseq_log)
 			nsc_log(tsp->ts_logcookie, TOKSEQ_LOG_COMPLETE,
-				(int)tsp, (int)agent, (int)curseq,
+				(int)tsp, (int)agent, (int)recvd,
 				(int)serverfunc, (int)args, (int)argsize, 0);
 #endif
 		LOCK_COND_LOCK(&tsp->ts_lock);
 		/* Bump sequence number if calling routine didn't already do it */
-		if (curseq == tsp->ts_conns[agent].tsp_expect)
+		if (recvd == tsp->ts_conns[agent].tsp_expect)
 			tsp->ts_conns[agent].tsp_expect++;
 	}
 


------------------------------------------------------------------------------
Special Offer-- Download ArcSight Logger for FREE (a $49 USD value)!
Finally, a world-class log management solution at an even better price-free!
Download using promo code Free_Logger_4_Dev2Dev. Offer expires 
February 28th, so secure your free ArcSight Logger TODAY! 
http://p.sf.net/sfu/arcsight-sfd2d