Messages in this thread Patch in this message | | | Date | Tue, 7 Jan 1997 23:03:49 +0100 (MET) | From | Ingo Molnar <> | Subject | ZeroD patch, version #2 |
| |
Ok, this one does the COW page flip thing too.
--mingo
diff -ru --exclude-from=exclude_from linux-2.1.20_orig/mm/Makefile linux/mm/Makefile --- linux-2.1.20_orig/mm/Makefile Tue Jan 7 20:07:41 1997 +++ linux/mm/Makefile Tue Jan 7 18:22:48 1997 @@ -8,7 +8,7 @@ # Note 2! The CFLAGS definition is now in the main makefile... O_TARGET := mm.o -O_OBJS := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \ +O_OBJS := zerod.o memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \ kmalloc.o vmalloc.o \ swap.o vmscan.o page_io.o page_alloc.o swap_state.o swapfile.o diff -ru --exclude-from=exclude_from linux-2.1.20_orig/mm/zerod.c linux/mm/zerod.c --- linux-2.1.20_orig/mm/zerod.c Tue Jan 7 20:07:41 1997 +++ linux/mm/zerod.c Tue Jan 7 22:51:22 1997 @@ -0,0 +1,122 @@ +/* + * linux/mm/zerod.c + * + * Copyright (C) 1997 Ingo Molnar + * + * This kernel thread keeps a pool of pre-zeroed pages. It runs at + * lowest possible process priority, so it will use up only idle time. + * It's a simple 'idle time' --> 'cleared page' converter. + */ + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/wait.h> + +#define DEBUG_ZEROD +#ifdef DEBUG_ZEROD +#define dprintk(args...) printk(## args) +#else +#define dprintk(args...) { ; }/* nothing */ +#endif + +/* + * This one must be power of 2. + */ +#define ZEROD_POOLSIZE 64 + +static struct wait_queue *zerod_wait = NULL; + +unsigned long cleared_pages [ZEROD_POOLSIZE]; +int first_page, last_page; + +int zerod(void * unused) +{ + unsigned long page; + int i; + + printk("zerod started.\n"); + + current->session = 1; + current->pgrp = 1; + sprintf(current->comm, "zerod"); + + /* + * Set to the lowest possible priority: + */ + current->priority = 0; + + last_page = first_page = 0; + + for (i=0; i<ZEROD_POOLSIZE; i++) + cleared_pages[i]=0; + + /* + * Never ending loop, clearing pages all the time: + */ + for (;;) { + while (!cleared_pages[last_page]) { + + page = __get_free_page(GFP_KERNEL); + if (page) { + clear_page(page); + cli(); + cleared_pages[last_page++]=page; + last_page &= ZEROD_POOLSIZE-1; + sti(); + continue; + } + break; + } + sleep_on (&zerod_wait); + } +} + +unsigned long get_precleared_page (void) +{ + unsigned long flags; + unsigned long page=0; + + save_flags(flags); + cli(); + + if (cleared_pages[first_page]) { + page=cleared_pages[first_page]; + cleared_pages[first_page++]=0; + first_page &= ZEROD_POOLSIZE-1; + wake_up (&zerod_wait); + } + + restore_flags(flags); + return page; +} + +/* + * This is for fast switching a newly allocated but nonzero page with + * one of our prezeroed pages. Returns zero if unsuccessful. + * + * dont do printks in this function, it's deep in the heart of the VM system + */ + +int try_to_trade_for_zeroed_page(unsigned long * to) +{ + unsigned long flags; + unsigned long tmp_page; + + save_flags(flags); + cli(); + + if (cleared_pages[first_page]) { + tmp_page=cleared_pages[first_page]; + cleared_pages[first_page]=*to; + *to=tmp_page; + restore_flags(flags); + return 1; + } + + /* + * no luck: + */ + restore_flags(flags); + return 0; +} + diff -ru --exclude-from=exclude_from linux-2.1.20_orig/init/main.c linux/init/main.c --- linux-2.1.20_orig/init/main.c Tue Jan 7 20:07:41 1997 +++ linux/init/main.c Tue Jan 7 22:53:02 1997 @@ -58,6 +58,7 @@ extern int console_loglevel; static int init(void *); +extern int zerod(void *); extern int bdflush(void *); extern int kswapd(void *); @@ -905,6 +906,11 @@ * make syscalls (and thus be locked). */ kernel_thread(init, NULL, 0); + + /* + * start up ZeroD: + */ + kernel_thread(zerod, NULL, 0); /* * task[0] is meant to be used as an "idle" task: it may not sleep, but * it might do some general things like count free pages or it could be diff -ru --exclude-from=exclude_from linux-2.1.20_orig/include/linux/mm.h linux/include/linux/mm.h --- linux-2.1.20_orig/include/linux/mm.h Tue Jan 7 20:07:41 1997 +++ linux/include/linux/mm.h Tue Jan 7 18:26:31 1997 @@ -230,10 +230,14 @@ #define __get_free_page(priority) __get_free_pages((priority),0,0) #define __get_dma_pages(priority, order) __get_free_pages((priority),(order),1) extern unsigned long __get_free_pages(int priority, unsigned long gfporder, int dma); +extern unsigned long get_precleared_page (void); extern inline unsigned long get_free_page(int priority) { unsigned long page; + + if ((page=get_precleared_page())) + return page; page = __get_free_page(priority); if (page) --- linux-2.1.20_orig/mm/memory.c Wed Jan 1 15:20:45 1997 +++ linux/mm/memory.c Tue Jan 7 22:37:59 1997 @@ -54,18 +54,21 @@ unsigned long num_physpages = 0; void * high_memory = NULL; +extern int try_to_trade_for_zeroed_page(unsigned long * to); + /* * We special-case the C-O-W ZERO_PAGE, because it's such * a common occurrence (no need to read the page to know * that it's zero - better for the cache and memory subsystem). */ -static inline void copy_cow_page(unsigned long from, unsigned long to) +static inline void copy_cow_page(unsigned long from, unsigned long * to) { if (from == ZERO_PAGE) { - clear_page(to); + if (!try_to_trade_for_zeroed_page(to)) + clear_page(*to); return; } - copy_page(to, from); + copy_page(*to, from); } #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) @@ -176,7 +179,7 @@ return 0; } -static inline void copy_one_pte(pte_t * old_pte, pte_t * new_pte, int cow) +static inline void copy_one_pte(pte_t * new_pte, pte_t * old_pte, int cow) { pte_t pte = *old_pte; unsigned long page_nr; @@ -225,10 +228,7 @@ if (end >= PMD_SIZE) end = PMD_SIZE; do { - /* I would like to switch arguments here, to make it - * consistent with copy_xxx_range and memcpy syntax. - */ - copy_one_pte(src_pte++, dst_pte++, cow); + copy_one_pte(dst_pte++, src_pte++, cow); address += PAGE_SIZE; } while (address < end); return 0; @@ -625,7 +625,11 @@ if (new_page) { if (PageReserved(mem_map + MAP_NR(old_page))) ++vma->vm_mm->rss; - copy_cow_page(old_page,new_page); + /* + * new_page might get switched for a prezeroed page, + * if this is a zero mapping. + */ + copy_cow_page(old_page,&new_page); flush_page_to_ram(old_page); flush_page_to_ram(new_page); flush_cache_page(vma, address); @@ -842,10 +846,9 @@ anonymous_page: entry = pte_wrprotect(mk_pte(ZERO_PAGE, vma->vm_page_prot)); if (write_access) { - unsigned long page = __get_free_page(GFP_KERNEL); + unsigned long page = get_free_page(GFP_KERNEL); if (!page) goto sigbus; - clear_page(page); entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); vma->vm_mm->rss++; tsk->min_flt++;
| |