[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