
From: Christoph Lameter <clameter@sgi.com>

The new accounting patches add function calls to critical code paths. 
These statistics have traditionally be gathered during the timer tick. 
Accounting is dependent on stime being incremented:

void acct_update_integrals(void)
{
        struct task_struct *tsk = current;

        if (likely(tsk->mm)) {
                long delta = tsk->stime - tsk->acct_stimexpd;

                tsk->acct_stimexpd = tsk->stime;
                tsk->acct_rss_mem1 += delta * tsk->mm->rss;
                tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
        }
}

If stime has not increased then delta == 0 and nothing happens just a
multiplication with zero....

Thus one may move the calls to the timer interrupt and only call
acct_update_integrals if stime has been incremented.  This will avoid
having to spent time to gather statistics in the hot paths of the vm.

One disadvantage is that rss etc may now peak between stime increments
without being noticed.  But I think we are mostly interested in prolonged
memory use rather than accurate data on the max rss ever reached.

Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/exec.c            |    4 ++--
 25-akpm/include/linux/acct.h |    4 ++--
 25-akpm/include/linux/mm.h   |    2 +-
 25-akpm/kernel/acct.c        |    4 +---
 25-akpm/kernel/exit.c        |    4 ++--
 25-akpm/kernel/timer.c       |    5 +++++
 25-akpm/mm/memory.c          |   14 +-------------
 25-akpm/mm/mmap.c            |    9 ---------
 25-akpm/mm/mremap.c          |    6 ------
 25-akpm/mm/rmap.c            |    3 ---
 25-akpm/mm/swapfile.c        |    3 ---
 11 files changed, 14 insertions(+), 44 deletions(-)

diff -puN fs/exec.c~move-accounting-function-calls-out-of-critical-vm-code-paths fs/exec.c
--- 25/fs/exec.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.623478608 -0800
+++ 25-akpm/fs/exec.c	2005-01-05 17:05:54.652474200 -0800
@@ -1166,8 +1166,8 @@ int do_execve(char * filename,
 
 		/* execve success */
 		security_bprm_free(bprm);
-		acct_update_integrals();
-		update_mem_hiwater();
+		acct_update_integrals(current);
+		update_mem_hiwater(current);
 		kfree(bprm);
 		return retval;
 	}
diff -puN include/linux/acct.h~move-accounting-function-calls-out-of-critical-vm-code-paths include/linux/acct.h
--- 25/include/linux/acct.h~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.624478456 -0800
+++ 25-akpm/include/linux/acct.h	2005-01-05 17:05:54.648474808 -0800
@@ -120,12 +120,12 @@ struct acct_v3
 struct super_block;
 extern void acct_auto_close(struct super_block *sb);
 extern void acct_process(long exitcode);
-extern void acct_update_integrals(void);
+extern void acct_update_integrals(struct task_struct *tsk);
 extern void acct_clear_integrals(struct task_struct *tsk);
 #else
 #define acct_auto_close(x)	do { } while (0)
 #define acct_process(x)		do { } while (0)
-#define acct_update_integrals()		do { } while (0)
+#define acct_update_integrals(x)	do { } while (0)
 #define acct_clear_integrals(task)	do { } while (0)
 #endif
 
diff -puN include/linux/mm.h~move-accounting-function-calls-out-of-critical-vm-code-paths include/linux/mm.h
--- 25/include/linux/mm.h~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.626478152 -0800
+++ 25-akpm/include/linux/mm.h	2005-01-05 17:05:54.647474960 -0800
@@ -838,7 +838,7 @@ static inline void vm_stat_unaccount(str
 }
 
 /* update per process rss and vm hiwater data */
-extern void update_mem_hiwater(void);
+extern void update_mem_hiwater(struct task_struct *tsk);
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
diff -puN kernel/acct.c~move-accounting-function-calls-out-of-critical-vm-code-paths kernel/acct.c
--- 25/kernel/acct.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.627478000 -0800
+++ 25-akpm/kernel/acct.c	2005-01-05 17:05:54.648474808 -0800
@@ -534,10 +534,8 @@ void acct_process(long exitcode)
  * acct_update_integrals
  *    -  update mm integral fields in task_struct
  */
-void acct_update_integrals(void)
+void acct_update_integrals(struct task_struct *tsk)
 {
-	struct task_struct *tsk = current;
-
 	if (likely(tsk->mm)) {
 		long delta = tsk->stime - tsk->acct_stimexpd;
 
diff -puN kernel/exit.c~move-accounting-function-calls-out-of-critical-vm-code-paths kernel/exit.c
--- 25/kernel/exit.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.628477848 -0800
+++ 25-akpm/kernel/exit.c	2005-01-05 17:05:54.645475264 -0800
@@ -801,8 +801,8 @@ fastcall NORET_TYPE void do_exit(long co
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
 	}
 
-	acct_update_integrals();
-	update_mem_hiwater();
+	acct_update_integrals(current);
+	update_mem_hiwater(current);
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
 	if (group_dead)
 		acct_process(code);
diff -puN kernel/timer.c~move-accounting-function-calls-out-of-critical-vm-code-paths kernel/timer.c
--- 25/kernel/timer.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.630477544 -0800
+++ 25-akpm/kernel/timer.c	2005-01-05 17:05:54.642475720 -0800
@@ -32,6 +32,7 @@
 #include <linux/jiffies.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
+#include <linux/acct.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -815,6 +816,10 @@ static inline void do_process_times(stru
 		if (psecs / HZ >= p->signal->rlim[RLIMIT_CPU].rlim_max)
 			send_sig(SIGKILL, p, 1);
 	}
+	if (system) {
+		acct_update_integrals(p);
+		update_mem_hiwater(p);
+	}
 }
 
 static inline void do_it_virt(struct task_struct * p, unsigned long ticks)
diff -puN mm/memory.c~move-accounting-function-calls-out-of-critical-vm-code-paths mm/memory.c
--- 25/mm/memory.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.631477392 -0800
+++ 25-akpm/mm/memory.c	2005-01-05 17:05:54.644475416 -0800
@@ -46,7 +46,6 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/rmap.h>
-#include <linux/acct.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
@@ -739,7 +738,6 @@ void zap_page_range(struct vm_area_struc
 	tlb = tlb_gather_mmu(mm, 0);
 	unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
 	tlb_finish_mmu(tlb, address, end);
-	acct_update_integrals();
 	spin_unlock(&mm->page_table_lock);
 }
 
@@ -1336,8 +1334,6 @@ static int do_wp_page(struct mm_struct *
 			mm->anon_rss--;
 		if (PageReserved(old_page)) {
 			++mm->rss;
-			acct_update_integrals();
-			update_mem_hiwater();
 		} else
 			page_remove_rmap(old_page);
 		break_cow(vma, new_page, address, page_table);
@@ -1620,8 +1616,6 @@ static int do_swap_page(struct mm_struct
 		remove_exclusive_swap_page(page);
 
 	mm->rss++;
-	acct_update_integrals();
-	update_mem_hiwater();
 
 	pte = mk_pte(page, vma->vm_page_prot);
 	if (write_access && can_share_swap_page(page)) {
@@ -1688,8 +1682,6 @@ do_anonymous_page(struct mm_struct *mm, 
 			goto out;
 		}
 		mm->rss++;
-		acct_update_integrals();
-		update_mem_hiwater();
 		entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
 							 vma->vm_page_prot)),
 				      vma);
@@ -1799,8 +1791,6 @@ retry:
 	if (pte_none(*page_table)) {
 		if (!PageReserved(new_page))
 			++mm->rss;
-		acct_update_integrals();
-		update_mem_hiwater();
 
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
@@ -2124,10 +2114,8 @@ EXPORT_SYMBOL(vmalloc_to_pfn);
  * update_mem_hiwater
  *	- update per process rss and vm high water data
  */
-void update_mem_hiwater(void)
+void update_mem_hiwater(struct task_struct *tsk)
 {
-	struct task_struct *tsk = current;
-
 	if (tsk->mm) {
 		if (tsk->mm->hiwater_rss < tsk->mm->rss)
 			tsk->mm->hiwater_rss = tsk->mm->rss;
diff -puN mm/mmap.c~move-accounting-function-calls-out-of-critical-vm-code-paths mm/mmap.c
--- 25/mm/mmap.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.633477088 -0800
+++ 25-akpm/mm/mmap.c	2005-01-05 17:05:54.651474352 -0800
@@ -21,7 +21,6 @@
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
-#include <linux/acct.h>
 #include <linux/mount.h>
 #include <linux/mempolicy.h>
 #include <linux/rmap.h>
@@ -1109,8 +1108,6 @@ out:	
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
-	acct_update_integrals();
-	update_mem_hiwater();
 	return addr;
 
 unmap_and_free_vma:
@@ -1457,8 +1454,6 @@ int expand_stack(struct vm_area_struct *
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
-	acct_update_integrals();
-	update_mem_hiwater();
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1522,8 +1517,6 @@ int expand_stack(struct vm_area_struct *
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
-	acct_update_integrals();
-        update_mem_hiwater();
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1911,8 +1904,6 @@ out:
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
 	}
-	acct_update_integrals();
-	update_mem_hiwater();
 	return addr;
 }
 
diff -puN mm/mremap.c~move-accounting-function-calls-out-of-critical-vm-code-paths mm/mremap.c
--- 25/mm/mremap.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.634476936 -0800
+++ 25-akpm/mm/mremap.c	2005-01-05 17:05:54.651474352 -0800
@@ -16,7 +16,6 @@
 #include <linux/fs.h>
 #include <linux/highmem.h>
 #include <linux/security.h>
-#include <linux/acct.h>
 #include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
@@ -251,9 +250,6 @@ static unsigned long move_vma(struct vm_
 					   new_addr + new_len);
 	}
 
-	acct_update_integrals();
-	update_mem_hiwater();
-
 	return new_addr;
 }
 
@@ -390,8 +386,6 @@ unsigned long do_mremap(unsigned long ad
 				make_pages_present(addr + old_len,
 						   addr + new_len);
 			}
-			acct_update_integrals();
-			update_mem_hiwater();
 			ret = addr;
 			goto out;
 		}
diff -puN mm/rmap.c~move-accounting-function-calls-out-of-critical-vm-code-paths mm/rmap.c
--- 25/mm/rmap.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.636476632 -0800
+++ 25-akpm/mm/rmap.c	2005-01-05 17:05:54.649474656 -0800
@@ -51,7 +51,6 @@
 #include <linux/swapops.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/acct.h>
 #include <linux/rmap.h>
 #include <linux/rcupdate.h>
 
@@ -607,7 +606,6 @@ static int try_to_unmap_one(struct page 
 	}
 
 	mm->rss--;
-	acct_update_integrals();
 	page_remove_rmap(page);
 	page_cache_release(page);
 
@@ -712,7 +710,6 @@ static void try_to_unmap_cluster(unsigne
 
 		page_remove_rmap(page);
 		page_cache_release(page);
-		acct_update_integrals();
 		mm->rss--;
 		(*mapcount)--;
 	}
diff -puN mm/swapfile.c~move-accounting-function-calls-out-of-critical-vm-code-paths mm/swapfile.c
--- 25/mm/swapfile.c~move-accounting-function-calls-out-of-critical-vm-code-paths	2005-01-05 17:05:54.637476480 -0800
+++ 25-akpm/mm/swapfile.c	2005-01-05 17:05:54.646475112 -0800
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/rmap.h>
 #include <linux/security.h>
-#include <linux/acct.h>
 #include <linux/backing-dev.h>
 #include <linux/syscalls.h>
 
@@ -437,8 +436,6 @@ unuse_pte(struct vm_area_struct *vma, un
 	set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
 	page_add_anon_rmap(page, vma, address);
 	swap_free(entry);
-	acct_update_integrals();
-	update_mem_hiwater();
 }
 
 /* vma->vm_mm->page_table_lock is held */
_
