[SSI] openssi/kernel/cluster/ssi/mosixll balance.c,1.21,1.22

Roger Tsang <[email protected]> Wed, 15 Dec 2010 07:03:12 +0000
Newsgroups gmane.linux.cluster.ssic.cvs
Message-ID <[email protected]>
Update of /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv13700/kernel/cluster/ssi/mosixll

Modified Files:
      Tag: OPENSSI-FC
	balance.c 
Log Message:
- choose: fix race over last_consider field in memory descriptor due to updating this field outside choose_sem semaphore.
- mchoose: fix race over mlast_consider field in memory descriptor. use mchoose_sem semaphore.
- mchoose: move get_jiffies_64() call outside for-loop and tasklist_lock. reduce lock contention.
- altload: return ULONG_MAX instead of hard-coded maximum value of 32-bit long because type long can be 64-bit. altruistic load values probably never go that high or beyond 32-bit range, but is a bug when this happens on 64-bit kernels.


Index: balance.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/balance.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- balance.c	9 Nov 2010 02:46:03 -0000	1.21
+++ balance.c	15 Dec 2010 07:03:10 -0000	1.22
@@ -424,7 +424,7 @@
 	unsigned long threshold;
 
 	if (!speed || !ncpus)
-		return 0xffffffff;
+		return ULONG_MAX;
 
 	threshold = ((unsigned long)(MF * STD_SPD)) / speed;
 
@@ -477,17 +477,19 @@
 {
 	struct task_struct *p, *sel = NULL;
         unsigned long minload, load, bestload = -1;
-        unsigned int priority, lastpri = 0; /* ms */
+        unsigned int consider, last_consider = 0; /* ms */
 	unsigned int pri, bestpri; /* ms */
 	cputime_t time;
 	const unsigned int mintime = 1000; /* 1000ms */
 	const unsigned int very_mintime = mintime / 3;
 static DECLARE_MUTEX(choose_sem);
 
-	if (chosen_for_balance)
-		return;
 	if (down_trylock(&choose_sem))
 		return;
+	if (chosen_for_balance) {
+		up(&choose_sem);
+		return;
+	}
 
 	/* Unlike OpenSSI, Mosix acpuse is always <= (MF * num_online_cpus()) */
 	bestpri = mintime; /* SSI: skip acpuse */
@@ -524,10 +526,11 @@
 			time = cputime_add(time, p->signal->cutime);
 			time = cputime_add(time, p->signal->cstime);
 		}
-		priority = cputime_to_msecs(time);
+		consider = cputime_to_msecs(time);
 
-		priority -= p->mm->last_consider;
-		pri = priority < 4000 ? priority : 4000; /* 4000ms */
+		pri = consider - p->mm->last_consider;
+		if (pri > 4000)
+			pri = 4000; /* 4000ms */
 
 		task_lock(p);
                 load = p->mm->load;
@@ -560,33 +563,31 @@
                         sel = p;
                         bestload = load;
                         bestpri = pri;
-			lastpri = priority;
+			last_consider = consider;
                 } else
 			mmput(p->mm);
         }
 	read_unlock(&tasklist_lock);
 
-        if(!sel) {
+	if (!sel) {
 		up(&choose_sem);
 		return;
 	}
 
 	spin_lock(&whereto_lock);
-
-	/* Release choose_sem early since
-	 * mosix_do_add_to_whereto() path might be re-entrant
-	 */
-	up(&choose_sem);
-
-	if(chosen_for_balance)
-	{
+	if (chosen_for_balance) {
 		spin_unlock(&whereto_lock);
+		up(&choose_sem);
 		mmput(sel->mm);
 		put_task_struct(sel);
 		return;
 	}
 	chosen_for_balance = sel;
-        sel->mm->last_consider += lastpri;
+	sel->mm->last_consider = last_consider;
+
+	/* Release choose_sem now that mm->last_consider is updated */
+	up(&choose_sem);
+
 	mmput(sel->mm);
 
 	load_balancing_counter = BALANCING_TIMEOUT;
@@ -596,7 +597,7 @@
 #ifdef	CONFIG_MOSIX_DEBUG
 	if(ds_debug & (DSDEB_LOAD|DSDEB_CONSIDER))
 		printk("selected %s for load-balancing, pri=%d, load=%lu, priority=%d\n",
-			desc_mostask(&sel->mosix), (int)bestpri, bestload, (int)lastpri);
+			desc_mostask(&sel->mosix), (int)bestpri, bestload, (int)last_consider);
 #endif /* CONFIG_MOSIX_DEBUG */
 }
 
@@ -756,16 +757,22 @@
 	unsigned long need = (unsigned long)arg;
 #ifdef SSI_BALANCE_MEMORY
 	unsigned long quality, bestquality = 0;
-	u64 df, diff = MIN_MCHOOSE_AGAIN / 1000;
+	u64 df, timestamp, diff = MIN_MCHOOSE_AGAIN / 1000;
 #else
 	int quality, bestquality = 0;
 	int df, diff = MIN_MCHOOSE_AGAIN;
 #endif
 	now_t dff;
 	struct task_struct *p, *sel = NULL;
+static DECLARE_MUTEX(mchoose_sem);
 
-	if (chosen_for_mdp)
+	if (down_trylock(&mchoose_sem))
 		return;
+	if (chosen_for_mdp) {
+		up(&mchoose_sem);
+		return;
+	}
+	timestamp = get_jiffies_64();
 
 	read_lock(&tasklist_lock);
 	for_each_process(p) {
@@ -780,7 +787,7 @@
 
 		if (!get_task_mm(p))
 			continue;
-		dff = get_jiffies_64() - p->mm->last_mconsider;
+		dff = timestamp - p->mm->last_mconsider;
 		if (dff)
 			dff /= HZ;
 
@@ -804,18 +811,26 @@
 			mmput(p->mm);
         }
 	read_unlock(&tasklist_lock);
-        if(!sel)
+
+	if (!sel) {
+		up(&mchoose_sem);
 		return;
+	}
 
 	spin_lock(&whereto_lock);
 	if (chosen_for_mdp) {
 		spin_unlock(&whereto_lock);
+		up(&mchoose_sem);
 		mmput(sel->mm);
 		put_task_struct(sel);
 		return;
 	}
 	chosen_for_mdp = sel;
-	sel->mm->last_mconsider = get_jiffies_64();
+	sel->mm->last_mconsider = timestamp;
+
+	/* Release mchoose_sem now that last_mconsider is updated */
+	up(&mchoose_sem);
+
 	mmput(sel->mm);
 
 	memory_balancing_counter = BALANCING_TIMEOUT;


------------------------------------------------------------------------------
Lotusphere 2011
Register now for Lotusphere 2011 and learn how
to connect the dots, take your collaborative environment
to the next level, and enter the era of Social Business.
http://p.sf.net/sfu/lotusphere-d2d