lkml.org 
[lkml]   [1997]   [Jan]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectZeroD 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++;

\
 
 \ /
  Last update: 2005-03-22 13:38    [W:0.051 / U:0.892 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site