Messages in this thread Patch in this message |  | | Date | Tue, 7 Jan 1997 20:08:59 +0100 (MET) | From | Ingo Molnar <> | Subject | Since no one else has stepped forward: 'ZeroD' patch |
| |
Here is a patch that implements 'ZeroD', a simple kernel thread that uses up CPU idle time to keep a pool of pre-zeroed pages around. Almost anything that doesnt burn 100% CPU time all the time should benefit from this.
the patch is against a clean 2.1.20. Comments, ideas, flames welcome.
--mingo
diff -u --recursive --new-file --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 Thu Jan 2 14:34:30 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) diff -u --recursive --new-file --exclude-from=exclude_from linux-2.1.20_orig/init/main.c linux/init/main.c --- linux-2.1.20_orig/init/main.c Thu Jan 2 14:13:27 1997 +++ linux/init/main.c Tue Jan 7 20:05:51 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 -u --recursive --new-file --exclude-from=exclude_from linux-2.1.20_orig/mm/Makefile linux/mm/Makefile --- linux-2.1.20_orig/mm/Makefile Fri Mar 22 11:56:56 1996 +++ 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 -u --recursive --new-file --exclude-from=exclude_from linux-2.1.20_orig/mm/zerod.c linux/mm/zerod.c --- linux-2.1.20_orig/mm/zerod.c Thu Jan 1 01:00:00 1970 +++ linux/mm/zerod.c Tue Jan 7 19:44:31 1997 @@ -0,0 +1,99 @@ +/* + * 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 32 + +static struct wait_queue *zerod_wait = NULL; +unsigned long nr_cleared_pages; + +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; +} + + + + +
|  |