[SSI] openssi/kernel/cluster/ssi/token clitok.c, 1.8, 1.9 mhsvrtok.c, 1.7, 1.8 msgsup.c, 1.8, 1.9 rsvrtok.c, 1.7, 1.8 svrtok.c, 1.7, 1.8 tokseq.c, 1.8, 1.9

Roger Tsang <[email protected]>
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token
In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv16224/kernel/cluster/ssi/token

Modified Files:
      Tag: OPENSSI-FC
	clitok.c mhsvrtok.c msgsup.c rsvrtok.c svrtok.c tokseq.c 
Log Message:
Bug fixes and enhancements. See ChangeLog.


Index: rsvrtok.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/rsvrtok.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- rsvrtok.c	3 Feb 2009 06:18:12 -0000	1.7
+++ rsvrtok.c	27 Oct 2009 03:18:29 -0000	1.8
@@ -293,13 +293,10 @@
 		contextp = svrglue_alloc_ctx();
 
 	gluectxp = (tokctx_mod_t *)contextp;
-	mb();
 	contextp += svr_top_glue_ctx_size;
 	rctxp = (tokctx_mod_t *)contextp;
-	mb();
 	contextp += tnc_rtok_ctx_size;
 	nrctxp = (tokctx_mod_t *)contextp;
-	mb();
 	contextp += tns_nrtok_ctx_size;
 
 	svrglue_init_ctx(gluectxp,
@@ -589,7 +586,6 @@
 	/* If start earlier than requested start adjust start,len */
 	if (qret->start < start) {
 		qret->len -= (start - qret->start);
-		mb();
 		qret->start = start;
 	}
 	/* If end later than requested adjust length */
@@ -1079,7 +1075,6 @@
 		 * has no bearing on split ranges from server to client.
 		 */
 		save_op_range = rng_ctx->tc_op_range;
-		mb();
 		rng_ctx->tc_op_range = rng_ctx->tc_curchunk->rc_range;
 
 		nr_ret = svrtok_clear(

Index: tokseq.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/tokseq.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- tokseq.c	24 Mar 2009 04:26:28 -0000	1.8
+++ tokseq.c	27 Oct 2009 03:18:29 -0000	1.9
@@ -112,7 +112,7 @@
 	    ((tokseqnum_t)(newtqp->tsq_seq - base_seq) > (tokseqnum_t)((*tqpp)->tsq_seq - base_seq)))
 		tqpp = &((*tqpp)->tsq_next);
 #ifdef TOKEN_TOKSEQ_RACE_FIX
-	mb();
+	rmb();
 #endif
 	newtqp->tsq_next = *tqpp;
 	*tqpp = newtqp;
@@ -156,6 +156,7 @@
 /* Called w. tcb locked (via whatever means).
  * Could be a macro for speed.
  */
+/* 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,
@@ -372,9 +373,6 @@
 	list = tsp->ts_conns[agent].tsp_queue;
 	qlen = tsp->ts_conns[agent].tsp_qlen;
 
-#ifdef TOKEN_TOKSEQ_RACE_FIX
-	mb();
-#endif
 	tsp->ts_conns[agent].tsp_qlen = 0;
 	tsp->ts_conns[agent].tsp_queue = NULL;
 

Index: clitok.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/clitok.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- clitok.c	24 Mar 2009 04:26:28 -0000	1.8
+++ clitok.c	27 Oct 2009 03:18:29 -0000	1.9
@@ -257,19 +257,19 @@
 /* Initialize a fifo (make it empty) */
 #ifdef TOKEN_FIFO_LINUX_LIST
 static inline void
-#else
-STATIC void
-#endif
 initfifo(fifo_t *fifop)
 {
-#ifdef TOKEN_FIFO_LINUX_LIST
 	INIT_LIST_HEAD(fifop);
+}
 #else
+STATIC void
+initfifo(fifo_t *fifop)
+{
 	fifop->fifo_req_begin = NULL;
 	/* For consistency just set end pointer to NULL also */
 	fifop->fifo_req_end = NULL;
-#endif
 }
+#endif
 
 /* Place new entry onto end of a fifo */
 #ifdef TOKEN_FIFO_LINUX_LIST
@@ -289,7 +289,7 @@
 		fifop->fifo_req_end = item;
 	} else {
 		fifop->fifo_req_end->req_next = item;
-		mb();
+		wmb();
 		fifop->fifo_req_end = item;
 	}
 	item->req_next = NULL;
@@ -308,7 +308,6 @@
 	if (fifop->fifo_req_begin == NULL)
 		return NULL;
 	save_req = fifop->fifo_req_begin;
-	mb();
 	fifop->fifo_req_begin = fifop->fifo_req_begin->req_next;
 	/* If the last one removed, set end pointer for consistency */
 	if (fifop->fifo_req_begin == NULL)
@@ -344,7 +343,7 @@
 void
 nrreq_init(void)
 {
-	nrreq_cachep = kmem_cache_create("clitok_req_cache",
+	nrreq_cachep = kmem_cache_create("ssi_clitok_req",
 				sizeof(struct nrreq), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -422,7 +421,6 @@
 #endif
 	LOCK_SPIN_LOCK(&nrreq_free_lock);
 	reqp->req_next = nrreq_free;
-	mb();
 	nrreq_free = reqp;
 	nrreq_free_count++;
 	UNLOCK_SPIN_LOCK(&nrreq_free_lock);
@@ -435,7 +433,7 @@
 void
 nrrevoke_init(void)
 {
-	nrrevoke_cachep = kmem_cache_create("clitok_rev_cache",
+	nrrevoke_cachep = kmem_cache_create("ssi_clitok_rev",
 				sizeof(struct nrrevoke), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -457,9 +455,6 @@
 
 #ifdef CLITOK_KMEM_CACHE
 	revp = kmem_cache_alloc(nrrevoke_cachep, GFP_KERNEL|__GFP_NOFAIL);
-#ifdef TOKEN_FIFO_LINUX_LIST
-	INIT_LIST_HEAD(&revp->rev_reqfifo);
-#endif
 #else
 	LOCK_SPIN_LOCK(&nrrev_free_lock);
 	if ((revp = nrrev_free)) {
@@ -487,7 +482,6 @@
 #else
 	LOCK_SPIN_LOCK(&nrrev_free_lock);
 	revp->rev_tcbp = (nrtcb_t *)nrrev_free;
-	mb();
 	nrrev_free = revp;
 	nrrev_free_count++;
 	UNLOCK_SPIN_LOCK(&nrrev_free_lock);
@@ -535,13 +529,12 @@
 DBG(DBGCLI,("wakeup(0x%x) performed on requestor process\n", reqp));
 #ifdef __KERNEL__
 #ifdef CFSTOK_INTR
-	SIGNAL_INTR_EVENT(&reqp->req_done);
-	/* SSI_XXX: what if called more than once? */
-	if (tas(&reqp->req_release)) {
-		reqp->req_release = 0;
-		/* Caller should have TCB lock */
+	if (xchg(&reqp->req_release, TOK_COMPLETED) == TOK_INTERRUPTED) {
+		/* Called with CFSTOK_XLOCK on cnode */
 		(void) tok_release(objp, reqp->req_tcbp, reqp->req_mode, 0);
-	}
+		tok_freereq(reqp);
+	} else
+		SIGNAL_INTR_EVENT(&reqp->req_done);
 #else
 	SIGNAL_EVENT(&(reqp->req_done));
 #ifdef NOTYET
@@ -781,10 +774,10 @@
 	ssi_mask_signals(current, &old_blocked, 1);
 	WAIT_INTR_EVENT(&request->req_done, 1, &intr);
 	ssi_unmask_signals(current, &old_blocked, 1);
-	if (intr && tas(&request->req_release))
-		/* Got interrupted but also got woken */
-		intr = request->req_release = 0;
-	tok_freereq(request);
+	if (intr && xchg(&request->req_release, TOK_INTERRUPTED) == TOK_COMPLETED)
+		intr = 0; /* Lost the race */
+	if (!intr)
+		tok_freereq(request);
 	DBG(DBGCLI,("tok_hold: request(0x%x) complete returning\n", request));
 	return intr;
 #else /* !CFSTOK_INTR */
@@ -921,6 +914,9 @@
 			MSGSEND(objp, REQUEST, (range_off_t)0, (range_off_t)0, request->req_agent,
 				tcbp->tok_mode, request->req_mode);
 		}
+#ifdef TOKEN_FIFO_LINUX_LIST
+		rmb();
+#endif
 		insertfifo(&((tcbp)->tok_reqfifo), request);
 		return FALSE;
 	}
@@ -1114,6 +1110,8 @@
 
 	tcbp->tok_mode = newmode;
 
+	barrier();
+
 	__token_wait_and_hold(objp, tcbp, newmode);
 }
 
@@ -1154,11 +1152,11 @@
 		return;
 	}
 	revp = allocnrrev();
+	initfifo(&revp->rev_reqfifo);
 	revp->rev_oldmode = oldmode;
 	revp->rev_newmode = newmode;
 	revp->rev_agent = agent;
 	revp->rev_tcbp = tcbp;
-	initfifo(&(revp->rev_reqfifo));
 
 	if (revoke_internal(objp, revp, direct)) {
 		/* Process requests waiting behind revoke */
@@ -1744,17 +1742,15 @@
 		 * have to re-send to us, anyway.
 		 */
 		if ((revp = tcbp->tok_revptr)) {
+			tcbp->tok_revptr = NULL;
 #ifdef TOKEN_FIFO_LINUX_LIST
 			/* Merge revoke reqfifo with tok_reqfifo */
 			list_splice_init(&revp->rev_reqfifo, &tcbp->tok_reqfifo);
+			freerev(revp);
 #else
 			fifo = revp->rev_reqfifo;
 			initfifo(&(revp->rev_reqfifo));
-#endif
 			freerev(revp);
-			tcbp->tok_revptr = NULL;
-
-#ifndef TOKEN_FIFO_LINUX_LIST
 			/* Merge revoke reqfifo with tok_reqfifo */
 			while((request = deletefifo(&fifo)))
 				insertfifo(&tcbp->tok_reqfifo, request);

Index: svrtok.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/svrtok.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- svrtok.c	24 Mar 2009 04:26:28 -0000	1.7
+++ svrtok.c	27 Oct 2009 03:18:29 -0000	1.8
@@ -143,10 +143,9 @@
 		fifop->fifo_req_end = item;
 	} else {
 		fifop->fifo_req_end->wan_next = item;
-		mb();
+		wmb();
 		fifop->fifo_req_end = item;
 	}
-	mb();
 	item->wan_next = NULL;
 	return;
 #endif
@@ -170,12 +169,10 @@
 	if (fifop->fifo_req_begin == NULL)
 		return NULL;
 	save_req = fifop->fifo_req_begin;
-	mb();
 	fifop->fifo_req_begin = fifop->fifo_req_begin->wan_next;
 	/* If the last one removed, set end pointer for consistency */
 	if (fifop->fifo_req_begin == NULL)
 		fifop->fifo_req_end = NULL;
-	mb();
 	save_req->wan_next = NULL;
 #endif
 	return(save_req);
@@ -221,7 +218,7 @@
 void
 node_ent_init(void)
 {
-	node_ent_cachep = kmem_cache_create("svrtok_nd_cache",
+	node_ent_cachep = kmem_cache_create("ssi_svrtok_nd",
 				sizeof(struct node_ent), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -260,8 +257,8 @@
 	newnode->nd_agent = agent;
 	newnode->nd_mode = mode;
 	newnode->nd_flags = flags;
-	svrinitfifo(&(newnode->nd_givefifo));
 	newnode->nd_next = NULL;
+	svrinitfifo(&(newnode->nd_givefifo));
 	return(newnode);
 }
 
@@ -303,7 +300,6 @@
 	/* Put node entry only free list */
 	LOCK_SPIN_LOCK(&node_free_lock);
 	savep->nd_next = node_free;
-	mb();
 	node_free = savep;
 	node_free_count++;
 	UNLOCK_SPIN_LOCK(&node_free_lock);
@@ -326,9 +322,9 @@
 	int newmode,
 	int getinstall)
 {
+	int oldmode;
 	struct node_ent **savepp;
 	struct node_ent *next;
-	int oldmode;
 
 	for (savepp = &(tcbp->tok_ndlist); *savepp;
 	    savepp = &((*savepp)->nd_next)) {
@@ -358,14 +354,14 @@
 #endif
 
 			oldmode = (*savepp)->nd_mode;
-			mb();
+			rmb();
 			(*savepp)->nd_mode = newmode;
 			return oldmode;
 		}
 	}
 	/* Insert newly allocated in agent order */
 	next = *savepp;
-	mb();
+	rmb();
 	*savepp = svrallocnode(agent, newmode, (short)0);
 	(*savepp)->nd_next = next;
 
@@ -579,8 +575,6 @@
 
 	for (savepp = &(tcbp->tok_ndlist); *savepp;
 	    savepp = &((*savepp)->nd_next)) {
-		if (GT_AGENT((*savepp)->nd_agent, agent))
-			break;
 		if (EQ_AGENT((*savepp)->nd_agent, agent)) {
 #ifdef NRSVRFIFO_LINUX_LIST
 			struct nrwant *tmp;
@@ -601,6 +595,8 @@
 			/* Only one node_ent per agent */
 			return;
 		}
+		if (GT_AGENT((*savepp)->nd_agent, agent))
+			break;
 	}
 }
 
@@ -645,8 +641,8 @@
 	 * Since reqfifo isn't being duplicated, we
 	 * should attempt to process the givebacks.
 	 */
-	for (nodepp = &(newtcbp->tok_ndlist); *nodepp ;
-	    nodepp = &(*nodepp)->nd_next) {
+	for (nodepp = &(newtcbp->tok_ndlist); *nodepp;
+	    nodepp = &((*nodepp)->nd_next)) {
 		process_give(objp, newtcbp, nodepp);
 		if ((*nodepp) == NULL)
 			break;
@@ -661,7 +657,7 @@
 void
 nrwant_init(void)
 {
-	nrwant_cachep = kmem_cache_create("svrtok_wt_cache",
+	nrwant_cachep = kmem_cache_create("ssi_svrtok_wt",
 				sizeof(struct nrwant), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -1471,7 +1467,9 @@
 		svrinsertfifo(&tcbp->tok_reqfifo, wantp);
 		return FALSE;
 	}
-
+#ifdef NRSVRFIFO_LINUX_LIST
+	rmb();
+#endif
 	svrinsertfifo(&tcbp->tok_reqfifo, wantp);
 
 	if (wantp->wan_flags & SVRTOK_QUERY) {
@@ -1941,7 +1939,6 @@
 	nrsvrtcb_t *tcbp,
 	agent_t agent)
 {
-	int ret;
 #if	defined(DEBUG) || defined(SIMUL)
 	char str[DBGSTRLEN];
 #endif
@@ -2006,7 +2003,7 @@
 			if (!(wantp->wan_flags & SVRTOK_QUERY) &&
 			    EQ_AGENT(wantp->wan_agent, agent)) {
 #ifdef NRSVRFIFO_LINUX_LIST
-				list_del_init(&wantp->wan_list);
+				list_del(&wantp->wan_list);
 #endif
 				freenrwant(wantp);
 			} else
@@ -2028,9 +2025,7 @@
 	}
 
 	/* We will return TRUE to caller if all tokens back at server */
-	ret = svrtok_notokens(tcbp);
-
-	return ret;
+	return svrtok_notokens(tcbp);
 }
 
 /*
@@ -2628,7 +2623,6 @@
 			nrwant_free_count -= chunk;
 			nrwant_free = nrwantp;
 			UNLOCK_SPIN_LOCK(&nrwant_free_lock);
-			mb();
 			nrwantp = startp;
 			for (; chunk > 0; chunk--) {
 				nextp = nrwantp->wan_next;

Index: msgsup.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/msgsup.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- msgsup.c	19 Feb 2009 08:01:02 -0000	1.8
+++ msgsup.c	27 Oct 2009 03:18:29 -0000	1.9
@@ -60,6 +60,12 @@
 
 #ifdef __KERNEL__
 #include <linux/sched.h>
+#ifdef RCU_MSGSUP_HASH
+#include <linux/bootmem.h>
+#include <linux/hash.h>
+#include <cluster/config.h>
+#endif
+#ifdef SSI_SKIP
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
@@ -77,9 +83,10 @@
 #include <asm/system.h>
 #include <cluster/nsc.h>
 #include <cluster/synch.h>
+#include <cluster/assert.h>
+#endif /* SSI_SKIP */
 #include <cluster/ssi/token/tokseq.h>
 #include <cluster/ssi/token/msgsup.h>
-#include <cluster/assert.h>
 #else /* ~__KERNEL__ */
 #include <stdio.h>
 #include <string.h>
@@ -105,7 +112,7 @@
 #define	MSG_LOCK(lock)			LOCK_SPIN_LOCK(&(lock))
 #define	MSG_UNLOCK(lock)		UNLOCK_SPIN_LOCK(&(lock))
 #define	MSG_INITLOCK(lock)		INIT_SPIN_LOCK(&(lock))
-#define	MSG_LOCK_T(lock)		SPIN_LOCK_T lock
+#define	MSG_LOCK_T(lock)		SPIN_LOCK_T lock __cacheline_aligned_in_smp
 #else /* ~ __KERNEL__ */
 #define	MSG_LOCK(lock)
 #define	MSG_UNLOCK(lock)
@@ -117,7 +124,10 @@
 struct msg {
 #ifdef RCU_MSGSUP
 	struct list_head msg_list;
-	struct rcu_head msg_rcu;
+	long id;
+#endif
+#ifdef RCU_MSGSUP_HASH
+	int in_process_msgs; /* non-zero: being processed by process_msgs() */
 #endif
 	object_t obj;
 	int op;
@@ -126,17 +136,22 @@
 	agent_t agent;
 	int oldmode;
 	int newmode;
+#ifndef RCU_MSGSUP
 	long id;
+#endif
 	int seq;
+#ifdef RCU_MSGSUP
+	struct rcu_head msg_rcu;
+#else
 #ifdef DEBUG
 	pid_t	pid;
 #endif /* DEBUG */
-#ifndef RCU_MSGSUP
 	struct msg *next;
 	struct msg *back;
-#endif
+#endif /* !RCU_MSGSUP */
 };
 
+#ifndef RCU_MSGSUP_HASH
 struct id {
 #ifdef RCU_MSGSUP
 	struct list_head id_list;
@@ -150,16 +165,23 @@
 	pid_t	pid;
 #endif
 };
+#endif /* !RCU_MSGSUP_HASH */
 
 #ifdef RCU_MSGSUP
 STATIC kmem_cache_t *msgsup_cachep;
+#ifdef RCU_MSGSUP_HASH
+STATIC struct list_head *msgsup_hashtable;
+STATIC unsigned int m_hash_shift;
+#define MSG_HASH hash_long(NSC_UNIQUE_ID, m_hash_shift)
+#else
 STATIC kmem_cache_t *msgsup_id_cachep;
 STATIC LIST_HEAD(msgsup_head);
 STATIC LIST_HEAD(msgsup_idlist);
+MSG_LOCK_T(msgsup_idlist_lock);
 #ifdef DEBUG
 STATIC int msgsup_head_count = 0;
 #endif
-MSG_LOCK_T(msgsup_idlist_lock);
+#endif /* !RCU_MSGSUP_HASH */
 #else /* !RCU_MSGSUP */
 STATIC struct msg *msgsup_head = NULL;
 STATIC struct msg *msg_free = NULL;
@@ -177,6 +199,7 @@
 #endif
 
 #ifdef __KERNEL__
+#ifndef RCU_MSGSUP_HASH
 /*
  * See if id is already on list.
  * Called/Returns with MSG_LOCK() held.
@@ -254,9 +277,8 @@
 void
 msgsup_id_free(struct rcu_head *id_rcu)
 {
-	struct id *ident = container_of(id_rcu, struct id, id_rcu);
-
-	kmem_cache_free(msgsup_id_cachep, ident);
+	kmem_cache_free(msgsup_id_cachep,
+			container_of(id_rcu, struct id, id_rcu));
 }
 #endif /* RCU_MSGSUP */
 
@@ -275,6 +297,7 @@
 		if (ident->id != id)
 			continue;
 		MSG_LOCK(msgsup_idlist_lock);
+		/* Linux: No race. id == NSC_UNIQUE_ID == current */
 		list_del_rcu(&ident->id_list);
 		MSG_UNLOCK(msgsup_idlist_lock);
 		rcu_read_unlock();
@@ -302,22 +325,45 @@
 
 	panic("msgsup_delid: entry not found");
 }
+#endif /* !RCU_MSGSUP_HASH */
 
 void
 msgsup_init()
 {
+#ifdef RCU_MSGSUP_HASH
+	int loop;
+
+	msgsup_hashtable =
+		alloc_large_system_hash("SSI Token Message",
+					sizeof(struct list_head),
+					0,
+					(num_physpages >= 128 * 1024) ?
+						(25 - PAGE_SHIFT) :
+						(27 - PAGE_SHIFT),
+					HASH_HIGHMEM,
+					&m_hash_shift,
+					NULL,
+					(MAXLOCPID + 1) >> 4);
+
+	for (loop = 0; loop < (1 << m_hash_shift); loop++)
+		INIT_LIST_HEAD(&msgsup_hashtable[loop]);
+#endif /* RCU_MSGSUP_HASH */
+
 	MSG_INITLOCK(msg_lock);
 #ifdef RCU_MSGSUP
-	MSG_INITLOCK(msgsup_idlist_lock);
-	msgsup_cachep = kmem_cache_create("msgsup_msg_cache",
+	msgsup_cachep = kmem_cache_create("ssi_msgsup_msg",
 				sizeof(struct msg), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
-	msgsup_id_cachep = kmem_cache_create("msgsup_id_cache",
+#ifndef RCU_MSGSUP_HASH
+	MSG_INITLOCK(msgsup_idlist_lock);
+
+	msgsup_id_cachep = kmem_cache_create("ssi_msgsup_id",
 				sizeof(struct id), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
-#endif
+#endif /* !RCU_MSGSUP_HASH */
+#endif /* RCU_MSGSUP */
 }
 #endif /* __KERNEL__ */
 
@@ -339,6 +385,9 @@
 #ifdef RCU_MSGSUP
 	msgp = kmem_cache_alloc(msgsup_cachep, GFP_KERNEL|__GFP_NOFAIL);
 	INIT_LIST_HEAD(&msgp->msg_list);
+#ifdef RCU_MSGSUP_HASH
+	msgp->in_process_msgs = 0;
+#endif
 	INIT_RCU_HEAD(&msgp->msg_rcu);
 #else /* !RCU_MSGSUP */
 	MSG_LOCK(msg_lock);
@@ -390,12 +439,15 @@
 	/* Add new messages to back of list */
 #ifdef RCU_MSGSUP
 	MSG_LOCK(msg_lock);
+#ifdef RCU_MSGSUP_HASH
+	list_add_tail_rcu(&msgp->msg_list, &msgsup_hashtable[MSG_HASH]);
+#else
 	list_add_tail_rcu(&msgp->msg_list, &msgsup_head);
 #ifdef DEBUG
 	msgsup_head_count++;
 	SSI_ASSERT(msgsup_head_count < 10000);
 #endif
-	MSG_UNLOCK(msg_lock);
+#endif /* !RCU_MSGSUP_HASH */
 #else /* !RCU_MSGSUP */
 	if (msgsup_head) {
 		msgp->next = msgsup_head;
@@ -409,9 +461,9 @@
 	}
 	msgsup_head_count++;
 	SSI_ASSERT(msgsup_head_count < 10000);
+#endif /* !RCU_MSGSUP */
 
 	MSG_UNLOCK(msg_lock);
-#endif /* !RCU_MSGSUP */
 #endif /* __KERNEL__ */
 #if	defined(SIMUL)
 	if (op & CFSCLI) {
@@ -430,9 +482,8 @@
 void
 msgsup_free(struct rcu_head *msg_rcu)
 {
-	struct msg *msgp = container_of(msg_rcu, struct msg, msg_rcu);
-
-	kmem_cache_free(msgsup_cachep, msgp);
+	kmem_cache_free(msgsup_cachep,
+			container_of(msg_rcu, struct msg, msg_rcu));
 }
 #endif /* RCU_MSGSUP */
 
@@ -440,11 +491,21 @@
 process_msgs(int force)
 {
 	struct msg *save;
+#ifdef RCU_MSGSUP_HASH
+	unsigned long hashval = MSG_HASH;
+	int recurse = FALSE;
+#else
 	int recurse;
 
 	/* PERF: Optimize NOOP case */
 #ifdef RCU_MSGSUP
-	if (list_empty(&msgsup_head))
+	rcu_read_lock();
+	list_for_each_entry_rcu(save, &msgsup_head, msg_list) {
+		if (save->id == NSC_UNIQUE_ID)
+			break;
+	}
+	rcu_read_unlock();
+	if (&save->msg_list == &msgsup_head) /* NOOP */
 		return;
 
 	recurse = msgsup_findid(NSC_UNIQUE_ID);
@@ -472,16 +533,56 @@
 #endif
 	} else
 		msgsup_addid(NSC_UNIQUE_ID);
+#endif /* !RCU_MSGSUP_HASH */
 
 restart:
 #ifdef RCU_MSGSUP
+#ifdef RCU_MSGSUP_HASH
+	rcu_read_lock();
+	list_for_each_entry_rcu(save, &msgsup_hashtable[hashval], msg_list) {
+		if (save->id != NSC_UNIQUE_ID)
+			continue;
+		/* SSI: No race. NSC_UNIQUE_ID == current */
+		if (save->in_process_msgs) {
+			if (!recurse) {
+				if (!force)
+					break;
+				WARN_ON(save->in_process_msgs++ > 16);
+				recurse = TRUE;
+			}
+			/* already being processed */
+			continue;
+		}
+		save->in_process_msgs = 1;
+		rcu_read_unlock();
+
+#ifdef DEBUG
+		if (recurse)
+			printk(KERN_WARNING
+			    "%s: forced recursive processing\n", __FUNCTION__);
+#endif
+
+		TRANSPORT((&(save->obj)))(&(save->obj), save->seq,
+			save->op, save->oldmode, save->newmode, save->agent,
+			save->start, save->len);
+
+		/* Only remove from list after recursive processing. */
+		MSG_LOCK(msg_lock);
+		list_del_rcu(&save->msg_list);
+		MSG_UNLOCK(msg_lock);
+
+		call_rcu(&save->msg_rcu, msgsup_free);
+		goto restart;
+	}
+	rcu_read_unlock();
+#else /* !RCU_MSGSUP_HASH */
 	rcu_read_lock();
 	list_for_each_entry_rcu(save, &msgsup_head, msg_list) {
 		if (save->id != NSC_UNIQUE_ID)
 			continue;
 		MSG_LOCK(msg_lock);
 #ifdef SSI_SKIP
-		/* Linux: No need to check. See NSC_UNIQUE_ID */
+		/* SSI: No race. NSC_UNIQUE_ID == current */
 		if (save->id == 0) {
 			MSG_UNLOCK(msg_lock);
 			goto restart;
@@ -504,6 +605,7 @@
 		goto restart;
 	}
 	rcu_read_unlock();
+#endif /* !RCU_MSGSUP_HASH */
 #else /* !RCU_MSGSUP */
 	for (save = msgsup_head ; save ; save = save->next) {
 
@@ -548,8 +650,10 @@
 	}
 #endif /* !RCU_MSGSUP */
 
+#ifndef RCU_MSGSUP_HASH
 	if (!recurse)
 		msgsup_delid(NSC_UNIQUE_ID);
+#endif
 
 #ifndef RCU_MSGSUP
 	MSG_UNLOCK(msg_lock);

Index: mhsvrtok.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/token/mhsvrtok.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mhsvrtok.c	3 Feb 2009 06:18:12 -0000	1.7
+++ mhsvrtok.c	27 Oct 2009 03:18:29 -0000	1.8
@@ -76,7 +76,7 @@
 void
 mhnode_init(void)
 {
-	mhnode_cachep = kmem_cache_create("mhsvrtok_cache",
+	mhnode_cachep = kmem_cache_create("ssi_mhsvrtok",
 				sizeof(struct mhnode_ent), 0,
 				SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT|SLAB_PANIC,
 				NULL, NULL);
@@ -142,9 +142,6 @@
 	/* Put node entry only free list */
 	LOCK_SPIN_LOCK(&mhnode_free_lock);
 	savep->nd_next = mhnode_free;
-#ifdef MHSVRTOK_RACE_FIX
-	mb();
-#endif
 	mhnode_free = savep;
 	mhnode_free_count++;
 	UNLOCK_SPIN_LOCK(&mhnode_free_lock);
@@ -176,7 +173,7 @@
 	/* Insert newly allocated in agent order */
 	next = *savepp;
 #ifdef MHSVRTOK_RACE_FIX
-	mb();
+	rmb();
 #endif
 	*savepp = mhsvrallocnode(agent);
 	(*savepp)->nd_next = next;
@@ -185,7 +182,6 @@
 
 found:
 	(*savepp)->nd_numtoks++;
-	return;
 }
 
 STATIC void
@@ -193,7 +189,7 @@
 	object_t *objp,
 	mhsvrtcb_t *tcbp,
 	agent_t agent,
-	int count)
+	unsigned int count)
 {
 	struct mhnode_ent **savepp;
 
@@ -209,8 +205,11 @@
 				mhsvrfreenode(tcbp, savepp);
 			}
 
+			/* Only one mhnode_ent per agent */
 			return;
 		}
+		if (GT_AGENT((*savepp)->nd_agent, agent))
+			break;
 	}
 
 #if	defined(DEBUG) || defined(SIMUL)
@@ -234,8 +233,6 @@
 
 	for (savepp = &(tcbp->tok_ndlist); *savepp;
 	    savepp = &((*savepp)->nd_next)) {
-		if (GT_AGENT((*savepp)->nd_agent, agent))
-			break;
 		if (EQ_AGENT((*savepp)->nd_agent, agent)) {
 			(*savepp)->nd_numtoks = 0;
 			mhsvrfreenode(tcbp, savepp);
@@ -243,6 +240,8 @@
 			/* Only one mhnode_ent per agent */
 			return;
 		}
+		if (GT_AGENT((*savepp)->nd_agent, agent))
+			break;
 	}
 }
 
@@ -403,7 +402,6 @@
 	mhsvrtcb_t *tcbp,
 	agent_t agent)
 {
-	int ret;
 #if	defined(DEBUG) || defined(SIMUL)
 	char str[DBGSTRLEN];
 #endif
@@ -414,9 +412,7 @@
 	mhsvrclearnode(tcbp, agent);
 
 	/* We will return TRUE to caller if all tokens back at server */
-	ret = mhsvrtok_notokens(tcbp);
-
-	return ret;
+	return mhsvrtok_notokens(tcbp);
 }
 
 #if	!defined(__KERNEL__) || defined(DEBUG) || defined(DEBUG_TOOLS)


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.