[SSI] openssi/kernel/cluster/ssi/mosixll balance.c, 1.17, 1.18 freemem.c, 1.12, 1.13 info.c, 1.12, 1.13 kernel.c, 1.11, 1.12 load.c, 1.11, 1.12

Roger Tsang <[email protected]> Mon, 25 Oct 2010 05:50:43 +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-serv11623/cluster/ssi/mosixll

Modified Files:
      Tag: OPENSSI-FC
	balance.c freemem.c info.c kernel.c load.c 
Log Message:
- Reduce amount of work in interrupt context.
  - Offload mosix_snap_load() to bottom half. Actual work is moved to do_mosix_snap_load().
  - Invoke do_mosix_snap_load() every MF user ticks instead of every system tick.
  - Move mosix_calc_process_loads() back to mosix_calc_load() which runs in process context in OpenSSI.
- Fix compute_freemem() might reset value of exported freemem if below UTIL_TOLERANCE.
- In choose() re-adjust bestpri and mintime values since MF appears to be based on USER_HZ. 2.6.11 kernel HZ is 1000.
- No longer need acpuse_lock since acpuse value is "constant".
- Remove mosix_task->page_allocs. Not used.
- Fix invalid mosix_task->load value due to invalid mosix_task->ran that is calculated from load_ticks which is not reset prior the next mosix_task->ran calculation. In OpenSSI mosix_calc_load() resets load_ticks, but mosix_task->ran is calculated many times in another thread before load_ticks is reset. In this fix we use Linux ctime/stime from task_struct instead of load_ticks.
- Optimize away runqueue lock if possible in mosix_calc_process_loads().
- Change load_left_lock semaphore to spinlock. This lock used to protect other global variables from multiple mosix_calc_load() threads, but we reduced the number of mosix_calc_load() threads to one.
- Fix choose() and consider() skipped system CPU time.
- Fix update_load_array() filling master_load_array after incrementing load_cnt could race with nm_master_send(). When nm_master_send() lost the race CLMS clients would see incorrect ncpus and speed in loadinfo structure.
- Defer Mosix choose() and mchoose() to Linux work queue instead of nsc_async_queue.
- Fix mosix_do_add_to_whereto() race with age_balancing(). If age_balancing() won the race wake_up_mosix() could be using stale task struct which might cause memory corruption.

 cluster/ssi/mosixll/balance.c           |  316 +++++++++++-------------
 cluster/ssi/mosixll/freemem.c           |   15 -
 cluster/ssi/mosixll/info.c              |   17 -
 cluster/ssi/mosixll/kernel.c            |   15 -
 cluster/ssi/mosixll/load.c              |  246 +++++++++---------
 cluster/ssi/util/load_level.c           |   87 ++++--
 include/cluster/ssi/mosixll/balance.h   |    3 
 include/cluster/ssi/mosixll/defs.h      |    4 
 include/cluster/ssi/mosixll/mosixtask.h |    5 
 include/cluster/ssi/mosixll/routines.h  |    1 
 10 files changed, 368 insertions(+), 341 deletions(-)


Index: kernel.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/kernel.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- kernel.c	25 Oct 2010 05:01:37 -0000	1.11
+++ kernel.c	25 Oct 2010 05:50:41 -0000	1.12
@@ -146,9 +146,13 @@
 		spin_unlock(&whereto_lock);
 		return;
 	}
+	/* Get task. Avoid nasty race with age_balancing() */
+	get_task_struct(p);
 	/* Release whereto_lock for VProc context */
 	spin_unlock(&whereto_lock);
+
 	wake_up_mosix(p);
+	put_task_struct(p);
 #else
 	if(balpriority(p->mosix.whereto) >= balpriority(w))
 		return;
@@ -710,7 +714,9 @@
 	m->nforced_sigs = 0;
 #endif /* !CONFIG_SSI */
 	m->pages_i_bring = 0;
+#ifndef CONFIG_SSI
 	m->page_allocs = 0;
+#endif
 	m->ran = 0;
 	m->runstart = 0;
 	m->load = 0;
@@ -1193,8 +1199,10 @@
 	{
 #ifndef CONFIG_SSI
 		mosix_running++;
-#endif
 		p->mosix.runstart = load_ticks + 1;
+#else
+		p->mosix.runstart = cputime_add(p->utime, p->stime);
+#endif
 	}
 }
 
@@ -1206,9 +1214,12 @@
 #ifndef CONFIG_SSI
 		if (mosix_running > 0)
 			mosix_running--;
-#endif
 		p->mosix.ran += load_ticks + 1 - p->mosix.runstart;
 		p->mosix.runstart = 0;
+#else
+		p->mosix.ran += cputime_sub(
+			cputime_add(p->utime, p->stime), p->mosix.runstart);
+#endif
 	}
 }
 

Index: load.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/load.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- load.c	25 Oct 2010 05:01:37 -0000	1.11
+++ load.c	25 Oct 2010 05:50:41 -0000	1.12
@@ -48,13 +48,12 @@
 unsigned long load_ticks;    /* # of ticks included in load_adder */
 unsigned long cpuse;         /* # of ticks when CPU was not thrashing */
 
-__cacheline_aligned_in_smp DEFINE_RWLOCK(acpuse_lock); /* protect acpuse */
-unsigned long acpuse = MF;   /* long term non-trashing (start value = non-0) */
+unsigned long acpuse = MF;   /* long term non-thrashing (non-zero) */
 
-DECLARE_MUTEX(load_left_lock); /* protect load_left */
+/* protect load_left */
+__cacheline_aligned_in_smp DEFINE_SPINLOCK(load_left_lock);
 unsigned long load_left;     /* load of processes that just left */
 
-unsigned proc_ticks;    /* # of ticks included in for load leveler to run */
 unsigned long export_load;	/* load reported to other processors */
 #else
 unsigned load_adder;    /* accumulator of `running' every clock tick */
@@ -86,8 +85,56 @@
 #endif /* CONFIG_MOSIX_RESEARCH */
 
 #ifdef CONFIG_SSI
+/* Caller might be in interrupt context */
+static void
+mosix_calc_process_loads(unsigned long ticks)
+{
+	struct task_struct *p;
+	struct mosix_task *m;
+	struct runqueue *rq = NULL;
+	unsigned long flags;
+	int need_lock = !in_softirq();
+
+	/* Based on original mosix_calc_load().
+	 * Added locking where appropriate since in OpenSSI
+	 * mosix_calc_load() is no longer in top half.
+	 */
+	read_lock(&tasklist_lock);
+	for_each_process(p)
+	{
+		m = &p->mosix;
+
+		if (!m->ran)
+			continue;
+		if (need_lock)
+			rq = task_rq_lock(p, &flags);
+
+		if (m->ran) {
+			m->load = m->load * DECAY +
+				cputime_to_clock_t(m->ran) *
+				MF * 4*NEWDATA / ticks;
+			m->ran = cputime_zero;
+		}
+		if (need_lock)
+			task_rq_unlock(rq, &flags);
+	}
+	read_unlock(&tasklist_lock);
+
+#ifdef SSI_SKIP
+#ifdef REXEC_LOADTABLE_RACE_FIX
+	if (atomic_read(&load_cnt) > 1 && atomic_read(&loadlevel_on)) {
+#else
+	if (load_cnt > 1 && atomic_read(&loadlevel_on)) {
+#endif
+		if (nsc_async_queue(nsc_generic_async_queue,
+					(void *)load_balance, NULL, 0, 0))
+			printk(KERN_WARNING "Failed to queue load balance \n");
+	}
+#endif
+}
+
 /* Locking:
- * spin_lock_irqsave(&snap_load_lock)
+ * spin_lock_bh(&snap_load_lock)
  * down(&load_left_lock)
  * -> write_lock(&acpuse_lock)
  * spin_lock(&loadinfo_lock)
@@ -95,36 +142,36 @@
 void
 mosix_calc_load(unsigned long unused)
 {
-	unsigned long ladd, cpu, ticks;
-	unsigned long new_expload, new_cpuse;
-	unsigned long flags;
 static unsigned long upper_load = 0;	/* over estimated load */
 static unsigned long accload = 0;	/* accumulated load (*128) */
+static DECLARE_MUTEX(mosix_calc_load_sem);
+	unsigned long ladd, ticks;
 	unsigned long newload;
 #ifdef DEBUG
 	static int display_counter = 0;
 #endif
 #ifdef REXEC_LOADTABLE_FAST
-extern int altload(int, int, int);
+	unsigned long __altload;
 #endif
 
-	/* Disable interrupt to prevent mosix_snap_load() */
-	spin_lock_irqsave(&snap_load_lock, flags);
+	if (down_trylock(&mosix_calc_load_sem))
+		return;
+
+	/* Disable interrupt to prevent do_mosix_snap_load() */
+	spin_lock_bh(&snap_load_lock);
 
 	ticks = load_ticks;
-	cpu = cpuse;
 	ladd = load_adder;
-	cpuse = load_adder = load_ticks = 0;
-	spin_unlock_irqrestore(&snap_load_lock, flags);
+	load_adder = load_ticks = 0;
+	spin_unlock_bh(&snap_load_lock);
 
-	if (ticks == 0)
+	if (ticks == 0) {
+		up(&mosix_calc_load_sem);
 		return;
+	}
 
-	/* Protect load_left, upper_load, accload */
-	down(&load_left_lock);
+	ladd *= stable_export;
 
-	ladd = ladd * ((long long)(MF * STD_SPD)) /
-		(ticks * cpuspeed * num_online_cpus());
 	if(ladd * 128 > accload)	/* slowly up */
 		accload = accload * DECAY + ladd * 128 * NEWDATA;
 	else				/* quickly down */
@@ -134,27 +181,23 @@
 	else				/* very slowly down */
 		upper_load = (upper_load * 7 + ladd) / 8;
 
-	write_lock(&acpuse_lock);
-
-	new_cpuse = (acpuse * 3 + cpu * MF / ticks + 3) / 4;
-	acpuse = new_cpuse;
-	write_unlock(&acpuse_lock);
-
-	new_expload = (upper_load + stable_export) *
-			MF * num_online_cpus() / new_cpuse;
+	export_load = upper_load + stable_export;
 
 	newload = (accload+64) / 128;
+
+	spin_lock(&load_left_lock);
 	if(newload < load_left)
 		newload = 0;
 	else
 		newload -= load_left;
-	newload = newload * MF * num_online_cpus() / new_cpuse;
+	load_left = 0;
+	spin_unlock(&load_left_lock);
 
 #ifdef DEBUG
 	if(Tvis)
 		printk("\0337\033[22;55HL=%d,E=%d,R=%lu,U=%d  \0338",
-			(int)newload, (int)new_expload, nr_running(),
-			(int)new_cpuse);
+			(int)newload, (int)export_load, nr_running(),
+			(int)acpuse);
 	if(Tload) {
 		if (!(display_counter = (display_counter + 1) & 0xf))
 			printk("\naccload upper_load\tload_adder\tload_ticks\n");
@@ -162,13 +205,16 @@
 			(int)accload, (int)upper_load, (int)ladd, (int)ticks);
 	}
 #endif /* DEBUG */
-	load_left = 0;
-	up(&load_left_lock);
 
+	if (atomic_read(&loadlevel_on))
+		mosix_calc_process_loads(ticks);
+
+#ifdef REXEC_LOADTABLE_FAST
+	__altload = altload(export_load, loadinfo[0].speed, loadinfo[0].ncpus);
+#endif
 	spin_lock(&loadinfo_lock);
 #ifdef REXEC_LOADTABLE_FAST
-	loadinfo[0].altload =
-		altload(new_expload, loadinfo[0].speed, loadinfo[0].ncpus);
+	loadinfo[0].altload = __altload;
 #endif
 #ifdef CONFIG_SSI_LOADINFO_RLOAD
 	/* SSI_XXX: newload already factored in load_left - aka. rload */
@@ -179,55 +225,21 @@
 	loadinfo[0].mem = latest_free_mem;
 	spin_unlock(&loadinfo_lock);
 
-	set_mb(export_load, new_expload);
+	up(&mosix_calc_load_sem);
 
 	/* SSI_XXX: Need inc_decays() ? */
 	age_balancing();
-}
-
-/* Following path in interrupt context:
- * do_timer, mosix_snap_load, mosix_calc_process_loads
- */
-void
-mosix_calc_process_loads(int ticks)
-{
-	struct task_struct *p;
-	register struct mosix_task *m;
-	proc_ticks = 0;
 
-	read_lock(&tasklist_lock);
-	for_each_process(p)
-	{
-		m = &p->mosix;
-		if (!spin_trylock(&p->alloc_lock))
-			continue;
-		/* Got task_lock(p) */
-		if(m->runstart)
-		{
-			m->ran += ticks + 1 - m->runstart;
-			m->runstart = 1;
-		}
-		m->load = m->load * DECAY + m->ran * MF * 4*NEWDATA/ticks;
-		m->ran = 0;
-		m->page_allocs >>= 1;	/* decay in time */
-		task_unlock(p);
-	}
-	read_unlock(&tasklist_lock);
-
-#ifdef SSI_SKIP
 #ifdef REXEC_LOADTABLE_RACE_FIX
-	if (atomic_read(&load_cnt) > 1 && atomic_read(&loadlevel_on)) {
+	if (atomic_read(&load_cnt) > 1 && atomic_read(&loadlevel_on))
+		exec_balance();
 #else
 	if (load_cnt > 1 && atomic_read(&loadlevel_on)) {
-#endif
-		if (nsc_async_queue(nsc_generic_async_queue,
-					(void *)load_balance, NULL, 0, 0))
-			printk(KERN_WARNING "Failed to queue load balance \n");
+		exec_balance();
 	}
 #endif
 }
-
-#else /* !CONFIG_SSI */
+#else /* CONFIG_SSI */
 void
 mosix_calc_load(unsigned long unused)
 {
@@ -277,8 +289,6 @@
 	newload = newload * MF * num_online_cpus() / new_cpuse;
 	new_came = came_lately4 * DECAY + coming_in * 4 * NEWDATA;
 
-#ifndef CONFIG_SSI
-	/* For SSI we moved this into mosix_calc_process_loads(); */
 	read_lock(&tasklist_lock);
 	for_each_process(p)
 	{
@@ -293,7 +303,6 @@
 		m->page_allocs >>= 1;	/* decay in time */
 	}
 	read_unlock(&tasklist_lock);
-#endif
 
 #ifdef DEBUG
 	if(Tvis)
@@ -308,12 +317,7 @@
 	}
 #endif /* DEBUG */
 	write_lock_bh(&loadinfo_lock);
-#ifdef CONFIG_SSI_LOADINFO_RLOAD
-	/* SSI_XXX: newload already factored in load_left - aka. rload */
-	loadinfo[0].load = newload - loadinfo[0].rload;
-#else
 	loadinfo[0].load = newload;
-#endif
 	export_load = new_expload;
 	acpuse = new_cpuse;
 	came_lately4 = new_came;
@@ -381,50 +385,60 @@
 #endif /* CONFIG_MOSIX_RESEARCH */
 }
 
-/* Called by timer interrupt */
 #ifdef CONFIG_SSI
-/* Acquires
- * spin_lock(&snap_load_lock)
- * read_lock(&tasklist_lock)
- */
+static unsigned long mosix_running, mosix_ticks;
+
+/* Caller holds mosix_tasklet tasklet_lock */
+static void
+do_mosix_snap_load(unsigned long dummy)
+{
+	spin_lock(&snap_load_lock);
+	load_adder += mosix_running;
+	load_ticks += mosix_ticks;
+	spin_unlock(&snap_load_lock);
+	/* preempt-safe */
+	mosix_running = mosix_ticks = 0;
+}
+
+/* Called from hard timer interrupt */
 void
 mosix_snap_load(unsigned long ticks)
-#else
-void
-mosix_snap_load(int ticks)
-#endif
 {
-#ifdef CONFIG_SSI
-	int n, active_cpus = 0;
+static DECLARE_TASKLET(mosix_tasklet, do_mosix_snap_load, 0);
+static unsigned long __mosix_running, __mosix_ticks;
+static int count = MOSIX_SNAP_FREQ;
 
-#ifdef SSI_SKIP
-	/* SSI_XXX: Could race with mosix_calc_load() */
-	load_adder += nr_running() + nr_uninterruptible();
-	for (n=0; n < num_online_cpus(); n++)
-		active_cpus += active_cpu_list[n];
+	count -= ticks;
+	if (count < 0) {
+		count += MOSIX_SNAP_FREQ;
+		__mosix_running += nr_running();
+		__mosix_ticks += MF;
 
-	if(nr_running() <= active_cpus)
-#endif
-	for_each_online_cpu(n) {
-		if (!idle_cpu(n))
-			active_cpus++;
-	}
+		if (!tasklet_trylock(&mosix_tasklet))
+			return;
+		mosix_running += __mosix_running;
+		mosix_ticks += __mosix_ticks;
+		tasklet_unlock(&mosix_tasklet);
 
-	if(nr_running() <= active_cpus) {
-		spin_lock(&snap_load_lock);
-#else
+		tasklet_schedule(&mosix_tasklet);
+		__mosix_running = __mosix_ticks = 0;
+	}
+}
+#else /* CONFIG_SSI */
+void
+mosix_snap_load(int ticks)
+{
 	load_adder += mosix_running;
+	for (n=0; n < num_online_cpus(); n++)
+		active_cpus += active_cpu_list[n];
 	if(mosix_running <= active_cpus) {
-#endif
 		cpuse += ticks * num_online_cpus();
 	} else {
 		/* a possible race between the time of making a process runable
 		 * and actual picking up by a processor: so count runable
 		 * processes as if already occupying a processor:
 		 */
-#ifndef CONFIG_SSI
 		int n;
-#endif
 		register struct task_struct *p;
 
 		read_lock(&tasklist_lock);
@@ -437,22 +451,10 @@
 			}
 		}
 		read_unlock(&tasklist_lock);
-#ifdef CONFIG_SSI
-		spin_lock(&snap_load_lock);
-#endif
 		cpuse += ticks * n;
 	}
-#ifdef CONFIG_SSI
-	load_adder += nr_running() + nr_uninterruptible();
-	load_ticks += ticks;
-	spin_unlock(&snap_load_lock);
-
-	proc_ticks += ticks;
-	if(proc_ticks >= MF && atomic_read(&loadlevel_on))
-		mosix_calc_process_loads(proc_ticks);
-#else
 	load_ticks += ticks;
 	if(load_ticks >= MF)
 		mosix_calc_load(0);
-#endif
 }
+#endif /* !CONFIG_SSI */

Index: balance.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/balance.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- balance.c	25 Oct 2010 05:01:37 -0000	1.17
+++ balance.c	25 Oct 2010 05:50:41 -0000	1.18
@@ -418,7 +418,7 @@
  * the loss is therefore (N*L-1)*(L-(N*L-1)/N) = (N*L-1)*(L-L+1/N) = L - 1/N.
  */
 #ifdef CONFIG_SSI
-inline unsigned long
+unsigned long
 altload(unsigned long load, unsigned long speed, int ncpus)
 {
 	unsigned long threshold;
@@ -469,99 +469,80 @@
 
 #ifdef CONFIG_SSI
 /* Locking: this function may acquire ...
- * read_lock(&acpuse_lock)
  * read_lock(&tasklist_lock)
  * -> sighand->siglock
  * task_lock()
  * spin_lock(&whereto_lock)
  */
 void
-choose(void)
+choose(void *dummy)
 {
-	struct task_struct *t, *p, *sel = NULL;
-	register struct mosix_task *m;
-        unsigned long minload, load, bestload = 0;
-        unsigned int priority, lastpri = 0;
-	unsigned int pri, bestpri, mintime, very_mintime;
-	cputime_t utime, cutime;
+	struct mosix_task *m;
+	struct task_struct *p, *sel = NULL;
+        unsigned long minload, load, bestload = -1;
+        unsigned int priority, lastpri = 0; /* ms */
+	unsigned int pri, bestpri; /* ms */
+	const unsigned int mintime = 1000; /* 1000ms */
+	const unsigned int very_mintime = mintime / 3;
+	cputime_t time;
 
-	read_lock(&acpuse_lock);
-	bestpri = mintime = jiffies_to_msecs(acpuse) / (num_online_cpus() * MF) ;
-	minload = 2 * acpuse / num_online_cpus();	/* normally 4*MF */
-	read_unlock(&acpuse_lock);
+	if (chosen_for_balance)
+		return;
 
-	very_mintime = mintime / 3;
+	/* Unlike OpenSSI, Mosix acpuse is always <= (MF * num_online_cpus()) */
+	bestpri = mintime; /* SSI: skip acpuse */
+	minload = 2 * MF / num_online_cpus();	/* normally 4*MF */
 
 	read_lock(&tasklist_lock);
-
-	if(!chosen_for_balance)
-	for_each_process(p)
-	if (!((m = &p->mosix)->stay) && p != chosen_for_mdp && !p->execnode &&
-					is_loadlevelable(p, NULL))
-        {
-#ifdef SSI_SKIP
-		/* With VPROCS we already do all the user & child time
-		 * accounting
-		 */
-		priority = ticks_to_ms(p->utime + p->signal->utime + p->signal->cutime);
-#else
-		/* Following two blocks borrowed from Linux do_task_stat() */
-		utime = cutime = cputime_zero;
-		if (p->sighand) {
-			spin_lock_irq(&p->sighand->siglock);
-			/* add up live thread stats at the group level */
-			t = p;
-			do {
-				utime = cputime_add(utime, t->utime);
-				t = next_thread(t);
-			} while (t != p);
-			spin_unlock_irq(&p->sighand->siglock);
-		}
+	for_each_process(p) {
+		if (p->mosix.stay || p == chosen_for_mdp ||
+		    p->execnode || !is_loadlevelable(p, NULL))
+			continue;
+		time = cputime_add(p->utime, p->stime);
 		if (p->signal) {
-			cutime = p->signal->cutime;
-			utime = cputime_add(utime, p->signal->utime);
+			time = cputime_add(time, p->signal->utime);
+			time = cputime_add(time, p->signal->stime);
+			time = cputime_add(time, p->signal->cutime);
+			time = cputime_add(time, p->signal->cstime);
 		}
-		priority = cputime_to_msecs(cputime_add(cutime, utime));
-#endif
+		priority = cputime_to_msecs(time);
 
-		task_lock(p);
+		m = &p->mosix;
 
+		task_lock(p);
+		ssi_do_decay(m);
 		priority -= m->last_consider;
-		pri = (priority > 4*MILLION) ? 4*MILLION : priority; /*4 secs*/
+		task_unlock(p);
+
+		pri = priority < 4000 ? priority : 4000; /* 4000ms */
 
+                load = m->load;
 #ifdef DEBUG
 if(Tload)
 	printk("process=%d, load=%lu pri=%u bestpri=%u mload=%lu, bload=%lu \n",
-					p->pid, m->load, pri, bestpri, minload,
+					p->pid, load, pri, bestpri, minload,
 					bestload);
 #endif /* DEBUG */
 
-		ssi_do_decay(m);
-
                 if(pri < bestpri)
                 {
                         if(bestpri == mintime &&
 				/* (thrashing, or (m->load <= minload)) */
-				m->load > minload && pri >= very_mintime)
+			   load > minload && pri >= very_mintime)
                                 pri = mintime;
                         else
-			{
-				task_unlock(p);
                                 continue;
-			}
                 }
-                load = m->load;
-		task_unlock(p);
 
                 if(pri > bestpri || load > bestload)
                 {
                         bestload = load;
+                        bestpri = pri;
+			lastpri = priority;
+			get_task_struct(p);
 			if(sel)
 				put_task_struct(sel);
-			get_task_struct(p);
                         sel = p;
-                        bestpri = pri;
-			lastpri = priority;
                 }
         }
 	read_unlock(&tasklist_lock);
@@ -699,9 +680,6 @@
 }
 #endif /* !CONFIG_SSI */
 
-#ifndef CONFIG_SSI
-/* Acquires read_lock_bh(&loadinfo_lock) */
-#endif
 void
 load_balance(void)
 {
@@ -709,59 +687,52 @@
 #ifndef REXEC_LOADTABLE_FAST
 	unsigned long load;
 #endif
-#else
-	register int load;
-#endif
-	register struct loadinfo *l;
-	int doit = 0;
-
-#ifndef CONFIG_SSI
-	if(mosadmin_mode_stay)
-		return;
+	struct loadinfo *l;
+static DECLARE_WORK(work, choose, NULL);
 
-	read_lock_bh(&loadinfo_lock);
-#endif
 #ifndef REXEC_LOADTABLE_FAST
 	load = altload(loadinfo[0].load, loadinfo[0].speed, loadinfo[0].ncpus);
 #endif
 	for(l = &loadinfo[1]; l < &loadinfo[INFO_WIN] ; l++)
-#ifdef CONFIG_SSI
 #ifdef REXEC_LOADTABLE_FAST
 	if (l->node && l->mem && l->altload <= loadinfo[0].altload)
 #else
 	if(l->node && l->mem && altload(l->load, l->speed, l->ncpus) <= load)
 #endif
-#else
+	{
+		/* Avoid stack overflow due to unchoose_me() recursion */
+		schedule_work(&work);
+		break;
+
+	}
+#else /* CONFIG_SSI */
+	register int load;
+	register struct loadinfo *l;
+	int doit = 0;
+
+	if(mosadmin_mode_stay)
+		return;
+
+	read_lock_bh(&loadinfo_lock);
+	for(l = &loadinfo[1]; l < &loadinfo[INFO_WIN] ; l++)
 	if(l->pe && l->mem > 0 && altload(l->load, l->speed, l->ncpus) <= load)
-#endif
 	{
 		doit = 1;
 		break;
 
 	}
-#ifndef CONFIG_SSI
 	read_unlock_bh(&loadinfo_lock);
-#endif
 	if(doit)
-#ifdef CONFIG_SSI
-		/* Avoid stack overflow due to unchoose_me() recursion */
-		if (nsc_async_queue(nsc_generic_async_queue,
-					(void *)choose, NULL, 0, 0))
-			printk(KERN_WARNING "Failed to queue choose\n");
-#else
 		choose();
-#endif
+#endif /* !CONFIG_SSI */
 }
 
+#ifdef CONFIG_SSI
 void
-#ifdef SSI_BALANCE_MEMORY
 mchoose(void *arg)
-#else
-mchoose(int need)
-#endif
 {
+	unsigned long need = (unsigned long)arg;
 #ifdef SSI_BALANCE_MEMORY
-	unsigned long *need = (unsigned long *)arg;
 	unsigned long quality, bestquality = 0;
 	now_t df, diff = MIN_MCHOOSE_AGAIN;
 #else
@@ -772,17 +743,68 @@
 	struct task_struct *p, *sel = NULL;
 	register struct mosix_task *m;
 
+	if (chosen_for_mdp)
+		return;
+
 	read_lock(&tasklist_lock);
-	if(!chosen_for_mdp)
 	for_each_process(p)
-#ifdef CONFIG_SSI
 	if (!((m=&p->mosix)->stay) && p != chosen_for_balance &&
 					is_loadlevelable(p, NULL))
-#else
+	{
+		task_lock(p);
+		dff = time_since(m->last_mconsider);
+		task_unlock(p);
+		if(dff > MAX_MCHOOSE_AGAIN)
+			df = MAX_MCHOOSE_AGAIN;
+		else
+			df = dff;
+		if(df < diff)
+			continue;
+		quality = memory_relief_quality(p, need);
+		if(quality > bestquality || (quality > 0 && df > diff))
+                {
+			if(sel)
+				put_task_struct(sel);
+			get_task_struct(p);
+                        sel = p;
+                        bestquality = quality;
+			diff = df;
+                }
+        }
+	read_unlock(&tasklist_lock);
+        if(!sel)
+		return;
+	spin_lock(&whereto_lock);
+	if(chosen_for_mdp)
+	{
+		put_task_struct(sel);
+		spin_unlock(&whereto_lock);
+		return;
+	}
+	task_lock(sel);
+	sel->mosix.last_mconsider = time_now();
+	task_unlock(sel);
+	chosen_for_mdp = sel;
+	memory_balancing_counter = BALANCING_TIMEOUT;
+	mosix_do_add_to_whereto(sel, MEMBALANCE);
+	/* whereto_lock unlocked */
+}
+#else /* CONFIG_SSI */
+void
+mchoose(int need)
+{
+	int quality, bestquality = 0;
+	int df, diff = MIN_MCHOOSE_AGAIN;
+	now_t dff;
+	struct task_struct *p, *sel = NULL;
+	register struct mosix_task *m;
+
+	read_lock(&tasklist_lock);
+	if(!chosen_for_mdp)
+	for_each_process(p)
         if(!((m = &p->mosix)->dflags & (DDEPUTY|DFINISHED|DPASSING)) &&
 		!m->stay && !m->whereto && p != chosen_for_balance &&
 		(!mosadmin_mode_lstay || (m->dflags & DREMOTE)))
-#endif /* !CONFIG_SSI */
 	{
 #ifdef CONFIG_MOSIX_DIAG
 		if(LOGICAL_STATE(p) == TASK_ZOMBIE)
@@ -791,24 +813,14 @@
 			continue;
 		}
 #endif /* CONFIG_MOSIX_DIAG */
-#ifdef CONFIG_SSI
-		task_lock(p);
-#endif
 		dff = time_since(m->last_mconsider);
-#ifdef CONFIG_SSI
-		task_unlock(p);
-#endif
 		if(dff > MAX_MCHOOSE_AGAIN)
 			df = MAX_MCHOOSE_AGAIN;
 		else
 			df = dff;
 		if(df < diff)
 			continue;
-#ifdef SSI_BALANCE_MEMORY
-		quality = memory_relief_quality(p, *need);
-#else
 		quality = memory_relief_quality(p, need);
-#endif
 		if(quality > bestquality || (quality > 0 && df > diff))
                 {
 			if(sel)
@@ -822,35 +834,16 @@
 	read_unlock(&tasklist_lock);
         if(!sel)
 		return;
-#ifdef CONFIG_SSI
-	spin_lock(&whereto_lock);
-#else
 	spin_lock_irq(&whereto_lock);
-#endif
 	if(chosen_for_mdp)
 	{
 		put_task_struct(sel);
-#ifdef CONFIG_SSI
-		spin_unlock(&whereto_lock);
-#else
 		spin_unlock_irq(&whereto_lock);
-#endif
 		return;
 	}
-#ifdef CONFIG_SSI
-	task_lock(sel);
-#endif
 	sel->mosix.page_allocs = 0;
 	sel->mosix.last_mconsider = time_now();
-#ifdef CONFIG_SSI
-	task_unlock(sel);
-#endif
 	chosen_for_mdp = sel;
-#ifdef CONFIG_SSI
-	memory_balancing_counter = BALANCING_TIMEOUT;
-	mosix_do_add_to_whereto(sel, MEMBALANCE);
-	/* whereto_lock unlocked */
-#else
 	mosix_do_add_to_whereto(sel, MEMBALANCE);
 	memory_balancing_counter = BALANCING_TIMEOUT;
 	if(sel->mosix.whereto != MEMBALANCE)
@@ -859,28 +852,25 @@
 		chosen_for_mdp = NULL;
 	}
 	spin_unlock_irq(&whereto_lock);
-#endif /* !CONFIG_SSI */
 #ifdef	CONFIG_MOSIX_DEBUG
 	if(ds_debug & DSDEB_CONSIDER)
 		printk("selected %s for memory-balancing, quality=%d\n",
 			desc_mostask(&sel->mosix), (int)bestquality);
 #endif
 }
+#endif /* !CONFIG_SSI */
 
-#ifndef CONFIG_SSI
-/* Acquires read_lock_bh(&loadinfo_lock) */
-#endif
-/* Code path may acquire read_lock(&tasklist_lock) */
 void
 memory_balance(void)
 {
-	register struct loadinfo *l;
+#ifdef CONFIG_SSI
+	struct loadinfo *l;
 #ifdef SSI_BALANCE_MEMORY
 	unsigned long need;
 #else
 	int need;
 #endif
-	int doit = 0;
+static DECLARE_WORK(work, mchoose, NULL);
 
 #ifdef SSI_BALANCE_MEMORY
 	if (mosadmin_mode_quiet || !memory_badly_required(&need))
@@ -890,39 +880,33 @@
 	   || (need = memory_badly_required()) <= 0)
 		return;
 #endif
-#ifndef CONFIG_SSI
+	for (l = &loadinfo[1]; l < &loadinfo[INFO_WIN] ; l++) {
+		if (!l->node || l->mem <= MIN_EXPECTED_PROC_SIZE)
+			continue;
+		/* Avoid stack overflow due to unchoose_me() recursion */
+		PREPARE_WORK(&work, mchoose, (void *)need);
+		schedule_work(&work);
+		break;
+	}
+#else /* CONFIG_SSI */
+	register struct loadinfo *l;
+	int need;
+	int doit = 0;
+
+	if(mosadmin_mode_stay || mosadmin_mode_quiet
+	   || (need = memory_badly_required()) <= 0)
+		return;
 	read_lock_bh(&loadinfo_lock);
-#endif
 	for(l = &loadinfo[1]; l < &loadinfo[INFO_WIN] ; l++)
-#ifdef CONFIG_SSI
-	if(l->node && (l->mem > MIN_EXPECTED_PROC_SIZE))
-#else
 	if(l->pe && l->mem > MIN_EXPECTED_PROC_SIZE)
-#endif /* !CONFIG_SSI */
 	{
 		doit = 1;
 		break;
 	}
-#ifdef CONFIG_SSI
-	if(doit) {
-		unsigned long *arg;
-
-		arg = kmalloc(sizeof(*arg), GFP_KERNEL);
-		if (!arg)
-			return;
-
-		*arg = need;
-		/* Avoid stack overflow due to unchoose_me() recursion */
-		if (nsc_async_queue(nsc_generic_async_queue,
-				(void *)mchoose, arg, sizeof(*arg),
-				NSC_ASYNC_ARGS_FREE))
-			printk(KERN_WARNING "Failed to queue mchoose\n");
-	}
-#else
 	read_unlock_bh(&loadinfo_lock);
 	if(doit)
 		mchoose(need);
-#endif
+#endif /* !CONFIG_SSI */
 }
 
 #ifndef CONFIG_SSI
@@ -990,13 +974,14 @@
 #if MAX_CONSIDERED > 127
 #error char is not enough for map
 #endif /*MAX_CONSIDERED*/
-	struct task_struct *t, *p = current;
+	//struct task_struct *t;
+	struct task_struct *p = current;
 	struct mosix_task *m = &p->mosix;
-	cputime_t utime, cutime;
-	clusternode_t mach[MAX_CONSIDERED];
 	long long tim, costs[MAX_CONSIDERED];
-	unsigned long migpages, aload[MAX_CONSIDERED];
 	int64_t ms;
+	unsigned long migpages, aload[MAX_CONSIDERED];
+	cputime_t time;
+	clusternode_t mach[MAX_CONSIDERED];
 	int i, n = 0, j, k;
 	int remote = (m->dflags & DREMOTE) ? 1 : 0;
 
@@ -1048,29 +1033,18 @@
 	kernel_fpu_begin();
 #endif
 
-	/* Following two blocks borrowed from Linux do_task_stat() */
-	utime = cutime = cputime_zero;
-
 	read_lock(&tasklist_lock);
-	if (p->sighand) {
-		spin_lock_irq(&p->sighand->siglock);
-		/* add up live thread stats at the group level */
-		t = p;
-		do {
-			utime = cputime_add(utime, t->utime);
-			t = next_thread(t);
-		} while (t != p);
-		spin_unlock_irq(&p->sighand->siglock);
-	}
+	time = cputime_add(p->utime, p->stime);
 	if (p->signal) {
-		cutime = p->signal->cutime;
-		utime = cputime_add(utime, p->signal->utime);
+		time = cputime_add(time, p->signal->utime);
+		time = cputime_add(time, p->signal->stime);
+		time = cputime_add(time, p->signal->cutime);
+		time = cputime_add(time, p->signal->cstime);
 	}
 	read_unlock(&tasklist_lock);
 
 	task_lock(p);
-	/* ms = (ticks_to_ms(p->utime+p->stime) - m->dctime) / HZ; */
-	ms = cputime_to_msecs(cputime_add(cutime, utime)) - m->dctime;
+	ms = cputime_to_msecs(time) - m->dctime;
 	task_unlock(p);
 
 	tim = (ms ? : 2) * cpuspeed / STD_SPD;

Index: freemem.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/freemem.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- freemem.c	18 Apr 2010 20:42:24 -0000	1.12
+++ freemem.c	25 Oct 2010 05:50:41 -0000	1.13
@@ -266,8 +266,8 @@
 void
 compute_freemem(void)
 {
-	static int trouble_time;
 #ifndef SSI_BALANCE_MEMORY
+	static int trouble_time;
 	int count;
 	int buffered, kernel, inactive, cached, tasked;
 #else
@@ -278,15 +278,9 @@
 		return;
 #endif
 
-#ifdef CONFIG_SSI
-	read_lock(&acpuse_lock);
-#endif
+#ifndef SSI_BALANCE_MEMORY
 	if(acpuse < MF * num_online_cpus() * UTIL_TOLLERANCE)
 		trouble_time = 11;
-#ifdef CONFIG_SSI
-	read_unlock(&acpuse_lock);
-#endif
-#ifndef SSI_BALANCE_MEMORY
 	tasked = 0;
 	if(trouble_time && --trouble_time > 0)
 		buffered = kernel = inactive = cached = 0;
@@ -341,9 +335,8 @@
 		count = 0;
 	latest_free_mem = count;
 #else /* SSI_BALANCE_MEMORY */
-	if (trouble_time && --trouble_time > 0) {
-		count = 0;
-	} else {
+	/* In OpenSSI acpuse is always above UTIL_TOLLERANCE */
+	{
 		/* Taken from Linux-2.6.11 mm/mmap.c:__vm_enough_memory()
 		 * where sysctl_overcommit_memory == OVERCOMMIT_GUESS
 		 */

Index: info.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/info.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- info.c	25 Oct 2010 05:01:37 -0000	1.12
+++ info.c	25 Oct 2010 05:50:41 -0000	1.13
@@ -998,12 +998,12 @@
 {
 	struct task_struct *p = current;
 	register struct mosix_task *m = &p->mosix;
+	struct runqueue *rq;
+	unsigned long flags;
 #ifdef CONFIG_SSI
 	unsigned long load;
 	unsigned int i;
 #else
-	struct runqueue *rq;
-	unsigned long flags;
 	register int load, i;
 	int pages = m->migpages ? : count_migrating_pages();
 
@@ -1014,10 +1014,11 @@
 	 * to avoid over-migration.
 	 */
 #ifdef CONFIG_SSI
-	task_lock(p);
-	load = m->load * STD_SPD / 4 / cpuspeed;
-	task_unlock(p);
+	rq = task_rq_lock(p, &flags);
+	load = m->load;
+	task_rq_unlock(rq, &flags);
 
+	load = load * STD_SPD / 4 / cpuspeed;
 	load /= num_online_cpus();
 
 	spin_lock(&loadinfo_lock);
@@ -1053,7 +1054,7 @@
 #endif
 	{
 		/* add slightly more than 1 process worth of load */
-		loadinfo[i].load += MF * 102 * STD_SPD/
+		loadinfo[i].load += (unsigned long)(MF) * 102 * STD_SPD/
 			(loadinfo[i].speed * loadinfo[i].ncpus * 100);
 		loadinfo[i].mem -= pages;
 #ifdef CONFIG_SSI_LOADINFO_RLOAD
@@ -1080,9 +1081,9 @@
 #else
 	spin_unlock(&loadinfo_lock);
 
-	down(&load_left_lock);
+	spin_lock(&load_left_lock);
 	load_left += load;
-	up(&load_left_lock);
+	spin_unlock(&load_left_lock);
 #endif /* CONFIG_SSI */
 #ifdef CONFIG_MOSIX_DEBUG
 	if((ds_debug & (DSDEB_LOADS|DSDEB_CONSIDER)) && i == INFO_WIN)


------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in  U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store 
http://p.sf.net/sfu/nokia-dev2dev