[SSI] openssi/kernel/cluster/ssi/mosixll freemem.c, 1.11, 1.12 service.c, 1.9, 1.10

Roger Tsang <[email protected]> Sun, 18 Apr 2010 20:42:26 +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-serv10942/cluster/ssi/mosixll

Modified Files:
      Tag: OPENSSI-FC
	freemem.c service.c 
Log Message:
MOSIX (#ifdef SSI_BALANCE_MEMORY):
- Use cond_resched_lock() instead of run_over_maxchunk, sort_age_maxchunk. Prevent needless re-traversing of the page table.
- run_over_dirty_pages(), sort_and_age_pages() support 4-level page table.


Index: service.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/service.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- service.c	17 Dec 2009 06:43:51 -0000	1.9
+++ service.c	18 Apr 2010 20:42:24 -0000	1.10
@@ -210,38 +210,91 @@
 	return(PageDirty(page) || PageSwapCache(page));
 }
 
-#define	RUN_OVER_MAGIC	126094
+#ifdef SSI_BALANCE_MEMORY
+/* We hold mm semaphore and page_table_lock on entry */
+static unsigned long
+__run_over_dirty_pg(
+	unsigned long *addr,
+	pgd_t *pgdir,
+	unsigned long pgd_end,
+	int isfile,
+	int count_in_file)
+{
+	pud_t *pudir;
+	pmd_t *pmdir;
+	pte_t *pte, *pte_dir;
+	unsigned long pud_end, pmd_end, pte_end, count = 0;
 
-static int run_over_maxchunk;
+	pudir = pud_offset(pgdir, *addr);
+	for(; *addr < pgd_end ; *addr = pud_end , pudir++) {
+		pud_end = (*addr + PUD_SIZE) & PUD_MASK;
+		if(pud_end > pgd_end || pud_end <= *addr)
+			pud_end = pgd_end;
+		if(pud_none(*pudir) || pud_bad(*pudir))
+			continue;
+
+		pmdir = pmd_offset(pudir, *addr);
+		for(; *addr < pud_end ; *addr = pmd_end , pmdir++) {
+			pmd_end = (*addr + PMD_SIZE) & PMD_MASK;
+			if(pmd_end > pud_end || pmd_end <= *addr)
+				pmd_end = pud_end;
+			if(pmd_none(*pmdir) || pmd_bad(*pmdir))
+				continue;
+
+			pte = pte_dir = pte_offset_map(pmdir, *addr);
+			for(; *addr < pmd_end ; *addr = pte_end , pte++) {
+				pte_end = *addr + PAGE_SIZE;
+				if(pte_end > pmd_end)
+					pte_end = pmd_end;
+				if(pte_present(*pte) ?
+				   (isfile && !pte_really_dirty(*pte)) :
+				   pte_none(*pte)) {
+					if(isfile && count_in_file)
+						count++;
+					continue;
+				}
+				if(!count_in_file)
+					count++;
+			}
+			pte_unmap(pte_dir);
+		}
+	}
+	return count;
+}
 
-#ifdef SSI_BALANCE_MEMORY
 /* Locking:
  * down_read(&mm->mmap_sem)
  * -> spin_lock(&mm->page_table_lock)
  */
 unsigned long
-#else
+run_over_dirty_pages(int (*func)(unsigned long, int), int count_in_file)
+#else /* SSI_BALANCE_MEMORY */
+#define	RUN_OVER_MAGIC	126094
+
+static int run_over_maxchunk;
+
 int
-#endif
 run_over_dirty_pages(int (*func)(unsigned long, int), int count_in_file)
+#endif /* !SSI_BALANCE_MEMORY */
 {
-	struct task_struct *p = current;
-	struct mm_struct *mm = p->mm;
+	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
+	unsigned long addr, pgd_end;
+	int isfile;
+	pgd_t *pgdir;
 #ifdef SSI_BALANCE_MEMORY
 	unsigned long count = 0;
 #else
+	unsigned long pmd_end, pte_end;
+	unsigned long start;
 	int count = 0;
-#endif
-	int isfile;
-	unsigned long start, addr, pgd_end, pmd_end, pte_end;
-	pgd_t *pgdir;
 	pud_t *pudir;
 	pmd_t *pmdir;
 	pte_t *pte;
 	pte_t *pte_dir;
-	int err;
 	int let_go;
+	int err;
+#endif
 
 #ifdef CONFIG_SSI
 	if(!mm || mm == &init_mm)
@@ -250,6 +303,7 @@
 		return(0);
 	}
 #endif /* CONFIG_SSI */
+#ifndef SSI_BALANCE_MEMORY
 	if(!run_over_maxchunk)
 	{
 		/* this routine can take very long for huge processes:
@@ -260,6 +314,7 @@
 		if(!run_over_maxchunk)	/* slow processors */
 			run_over_maxchunk = 1;
 	}
+#endif /* !SSI_BALANCE_MEMORY */
 
 #ifdef CONFIG_MOSIX_DIAG
 	if(!mm || mm == &init_mm)
@@ -276,13 +331,33 @@
 	}
 	/* so now there is no need to lock mmap_sem! */
 #endif /* CONFIG_MOSIX_DIAG */
+#ifdef SSI_BALANCE_MEMORY
+	BUG_ON(func);
+	down_read(&mm->mmap_sem);
+	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next) {
+		isfile = (vma->vm_file != NULL);
+		addr = vma->vm_start;
+		pgdir = pgd_offset(mm, addr);
+
+		spin_lock(&mm->page_table_lock);
+		for(; addr < vma->vm_end; addr = pgd_end, pgdir++) {
+			cond_resched_lock(&mm->page_table_lock);
+
+			pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
+			if(pgd_end > vma->vm_end || pgd_end <= addr)
+				pgd_end = vma->vm_end;
+			if(pgd_none(*pgdir) || pgd_bad(*pgdir))
+				continue;
+			count += __run_over_dirty_pg(&addr, pgdir, pgd_end,
+							isfile, count_in_file);
+		}
+		spin_unlock(&mm->page_table_lock);
+	}
+	up_read(&mm->mmap_sem);
+#else /* SSI_BALANCE_MEMORY */
 	addr = 0;
 loop:
 	let_go = run_over_maxchunk;
-#ifdef SSI_BALANCE_MEMORY
-	down_read(&mm->mmap_sem);
-	spin_lock(&mm->page_table_lock);
-#endif
 	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next)
 	if(addr < vma->vm_end)
 	{
@@ -295,12 +370,7 @@
 	    {
 		if(let_go-- == 0)
 		{
-#ifdef SSI_BALANCE_MEMORY
-			spin_unlock(&mm->page_table_lock);
-			up_read(&mm->mmap_sem);
-#else
 			yield();
-#endif
 			goto loop;
 		}
 		pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
@@ -308,9 +378,8 @@
 			pgd_end = vma->vm_end;
 		if(pgd_none(*pgdir) || pgd_bad(*pgdir))
 			continue;
-#ifndef SSI_BALANCE_MEMORY
+
 		spin_lock(&mm->page_table_lock);
-#endif
 		pudir = pud_offset(pgdir, addr);
 		pmdir = pmd_offset(pudir, addr);
 		for(; addr < pgd_end ; addr = pmd_end , pmdir++)
@@ -338,10 +407,6 @@
 				count++;
 			if(func)
 			{
-#ifdef SSI_BALANCE_MEMORY
-				BUG();
-				for (;;);
-#endif
 				spin_unlock(&mm->page_table_lock);
 				if((err = (*func)(addr, PAGE_SIZE))) {
 					pte_unmap(pte_dir);
@@ -352,15 +417,10 @@
 		    }
 		    pte_unmap(pte_dir);
 		}
-#ifndef SSI_BALANCE_MEMORY
 		spin_unlock(&mm->page_table_lock);
-#endif
 	    }
 	}
-#ifdef SSI_BALANCE_MEMORY
-	spin_unlock(&mm->page_table_lock);
-	up_read(&mm->mmap_sem);
-#endif
+#endif /* !SSI_BALANCE_MEMORY */
 	return(count);
 }
 

Index: freemem.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/cluster/ssi/mosixll/freemem.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- freemem.c	17 Dec 2009 06:43:51 -0000	1.11
+++ freemem.c	18 Apr 2010 20:42:24 -0000	1.12
@@ -44,8 +44,8 @@
 int pages_to_keep_free;
 int latest_free_mem;
 static int marker;
-#endif
 static int sort_age_maxchunk;
+#endif
 
 #ifdef SSI_BALANCE_MEMORY
 static inline unsigned long 
@@ -417,20 +417,20 @@
 sort_and_age_pages(struct mm_struct *mm)
 {
 #ifdef SSI_BALANCE_MEMORY
-	unsigned long used = 0, swapped = 0;
+	pud_t *pudir;
+	unsigned long pud_end, used = 0, swapped = 0;
 #else
 	int used = 0, unused = 0, swapped = 0, private_unused = 0;
-#endif
+	static int let_go = -1;
+#endif /* !SSI_BALANCE_MEMORY */
 	int need_flush = 0;
 	register struct vm_area_struct *vma;
 	pgd_t *pgdir;
-	pud_t *pudir;
 	pmd_t *pmdir;
 	pte_t *pte;
 	pte_t *pte_dir;
 	struct page *page;
 	unsigned long addr, start, pgd_end, pmd_end;
-	static int let_go = -1;
 	int interval = sort_interval(1);
 
 	if(!mm->last_memsort && interval)
@@ -440,14 +440,45 @@
 		if((u16)((jiffies & 0xffff) - mm->used) < interval)
 			return;
 	}
+#ifdef SSI_BALANCE_MEMORY
+	down_read(&mm->mmap_sem);
+	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next) {
+		start = vma->vm_start;
+
+		spin_lock(&mm->page_table_lock);
+		pgdir = pgd_offset(mm, start);
+		for(addr = start ; addr < vma->vm_end ;
+			addr = pgd_end , pgdir++)
+		{
+			cond_resched_lock(&mm->page_table_lock);
+
+			pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
+			if(pgd_end > vma->vm_end || pgd_end <= addr)
+				pgd_end = vma->vm_end;
+			if(pgd_none(*pgdir) || pgd_bad(*pgdir))
+				continue;
+
+			pudir = pud_offset(pgdir, addr);
+		    for(; addr < pgd_end ; addr = pud_end , pudir++)
+		    {
+			pud_end = (addr + PUD_SIZE) & PUD_MASK;
+			if(pud_end > pgd_end || pud_end <= addr)
+				pud_end = pgd_end;
+			if(pud_none(*pudir) || pud_bad(*pudir))
+				continue;
+
+			pmdir = pmd_offset(pudir, addr);
+			for(; addr < pud_end ; addr = pmd_end , pmdir++)
+			{
+				pmd_end = (addr + PMD_SIZE) & PMD_MASK;
+				if(pmd_end > pud_end || pmd_end <= addr)
+					pmd_end = pud_end;
+#else /* SSI_BALANCE_MEMORY */
 	addr = 0;
 loop:
 	if(let_go == -1)
 		let_go = sort_age_maxchunk;
 
-#ifdef SSI_BALANCE_MEMORY
-	down_read(&mm->mmap_sem);
-#endif
 	spin_lock(&mm->page_table_lock);
 
 	for(vma = mm->mmap ; vma != NULL ; vma = vma->vm_next)
@@ -463,11 +494,7 @@
 			if(let_go-- == 0)
 			{
 				spin_unlock(&mm->page_table_lock);
-#ifdef SSI_BALANCE_MEMORY
-				up_read(&mm->mmap_sem);
-#else
 				yield();
-#endif
 				goto loop;
 			}
 			pgd_end = (addr + PGDIR_SIZE) & PGDIR_MASK;
@@ -475,13 +502,13 @@
 				pgd_end = vma->vm_end;
 			if(pgd_none(*pgdir) || pgd_bad(*pgdir))
 				continue;
-			pudir = pud_offset(pgdir, addr);
-			pmdir = pmd_offset(pudir, addr);
+			pmdir = pmd_offset(pgdir, addr);
 			for(; addr < pgd_end ; addr = pmd_end , pmdir++)
 			{
 				pmd_end = (addr + PMD_SIZE) & PMD_MASK;
 				if(pmd_end > pgd_end)
 					pmd_end = pgd_end;
+#endif /* !SSI_BALANCE_MEMORY */
 				if(pmd_none(*pmdir) || pmd_bad(*pmdir))
 					continue;
 				pte = pte_dir = pte_offset_map(pmdir, addr);
@@ -530,16 +557,22 @@
 	}
 				pte_unmap(pte_dir);
 			}
+#ifdef SSI_BALANCE_MEMORY
+		    } /* for pudir */
+#endif
 		}
+#ifdef SSI_BALANCE_MEMORY
+		spin_unlock(&mm->page_table_lock);
+#endif
 	}
 	if(need_flush)
 		flush_tlb_mm(mm);
-	spin_unlock(&mm->page_table_lock);
 #ifdef SSI_BALANCE_MEMORY
 	up_read(&mm->mmap_sem);
 
 	spin_lock(&mm->memsort_lock);
 #else
+	spin_unlock(&mm->page_table_lock);
 	write_lock_irq(&tasklist_lock);
 #endif
 	mm->used = used;
@@ -565,7 +598,9 @@
 #endif /* CONFIG_MOSIX_DEBUG */
 }
 
+#ifndef SSI_BALANCE_MEMORY
 #define	SORT_AGE_MAGIC		2490368
+#endif
 
 int
 mosix_mem_daemon(void *nothing)
@@ -591,6 +626,7 @@
 		pages_to_keep_free = MAX_PAGES_TO_KEEP_FREE;
 	compute_freemem();
 
+#ifndef SSI_BALANCE_MEMORY
 	/* "sort_and_age_pages" can take very long for large memories:
 	 * we must therefore allow other processes to take over at least
 	 * about every millisecond.
@@ -598,6 +634,7 @@
 	sort_age_maxchunk = loops_per_jiffy / SORT_AGE_MAGIC;
 	if(!sort_age_maxchunk)	/* very slow processors */
 		sort_age_maxchunk = 1;
+#endif /* !SSI_BALANCE_MEMORY */
 	while (1)
 	{
 		current->state = TASK_INTERRUPTIBLE;


------------------------------------------------------------------------------
Download Intel&#174; Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev