Messages in this thread Patch in this message | | | Date | Fri, 17 Jul 1998 21:49:55 -0400 | From | Bill Hawes <> | Subject | patch to trim page table cache |
| |
The current kernel has no provision to drain down the page table cache when the system needs memory, which is not good for fragmentation and probably counterproductive for performance as well. The attached patch redefines the check_pgt_cache() routine and passes an argument to specify whether to drain the cache or keep it between the watermarks.
I've placed a call to trim_pgt_cache(1) in do_try_to_free_page() so that the page table cache drains gradually when the system starts swapping.
The patch also corrects an apparent kernel locking problem in arch/i386/kernel/process.c. The SMP version of sys_idle() doesn't get the kernel lock before calling check_pgt_cache(), but since the pgt quicklists don't have spinlock protection, the kernel lock is necessary for SMP safety. I've moved the kernel lock upwards to cover it.
Tested lightly and seems to work OK.
Regards, Bill--- linux-2.1.109/include/linux/mm.h.old Fri Jul 17 09:34:42 1998 +++ linux-2.1.109/include/linux/mm.h Fri Jul 17 21:03:39 1998 @@ -277,7 +281,8 @@ extern void vmtruncate(struct inode * inode, unsigned long offset); extern void handle_mm_fault(struct task_struct *tsk,struct vm_area_struct *vma, unsigned long address, int write_access); -extern void check_pgt_cache(void); +extern void trim_pgt_cache(int); +#define check_pgt_cache() trim_pgt_cache(0) extern void make_pages_present(unsigned long addr, unsigned long end); extern unsigned long paging_init(unsigned long start_mem, unsigned long end_mem); --- linux-2.1.109/mm/memory.c.old Fri Jul 3 10:33:11 1998 +++ linux-2.1.109/mm/memory.c Fri Jul 17 21:10:47 1998 @@ -939,9 +954,9 @@ */ int pgt_cache_water[2] = { 25, 50 }; -void check_pgt_cache(void) +void trim_pgt_cache(int must_free) { - if(pgtable_cache_size > pgt_cache_water[0]) { + if(pgtable_cache_size > (must_free ? 0 : pgt_cache_water[0])) { do { if(pgd_quicklist) free_pgd_slow(get_pgd_fast()); --- linux-2.1.109/mm/vmscan.c.old Fri Jul 17 09:10:45 1998 +++ linux-2.1.109/mm/vmscan.c Fri Jul 17 20:34:57 1998 @@ -453,6 +453,9 @@ /* Always trim SLAB caches when memory gets low. */ kmem_cache_reap(gfp_mask); + /* Trim back the page table cache. */ + trim_pgt_cache(1); + /* We try harder if we are waiting .. */ stop = 3; if (gfp_mask & __GFP_WAIT) @@ -533,7 +536,6 @@ add_wait_queue(&kswapd_wait, &wait); while (1) { int tries; - int tried = 0; current->state = TASK_INTERRUPTIBLE; flush_signals(current); --- linux-2.1.109/arch/i386/kernel/process.c.old Fri Jul 17 09:10:28 1998 +++ linux-2.1.109/arch/i386/kernel/process.c Fri Jul 17 20:35:13 1998 @@ -158,16 +158,18 @@ if(current_cpu_data.hlt_works_ok && !hlt_counter && !need_resched) __asm("hlt"); + + lock_kernel(); + /* Need the kernel lock for this ... */ check_pgt_cache(); /* * tq_scheduler currently assumes we're running in a process * context (ie that we hold the kernel lock..) */ if (tq_scheduler) { - lock_kernel(); run_task_queue(&tq_scheduler); - unlock_kernel(); } + unlock_kernel(); /* endless idle loop with no priority at all */ current->counter = -100; schedule(); | |