patch-2.2.0-pre8 linux/mm/memory.c
Next file: linux/mm/mmap.c
Previous file: linux/mm/filemap.c
Back to the patch index
Back to the overall index
- Lines: 96
- Date:
Mon Jan 18 17:33:10 1999
- Orig file:
v2.2.0-pre7/linux/mm/memory.c
- Orig date:
Thu Jan 7 15:11:41 1999
diff -u --recursive --new-file v2.2.0-pre7/linux/mm/memory.c linux/mm/memory.c
@@ -126,48 +126,36 @@
* This function clears all user-level page tables of a process - this
* is needed by execve(), so that old pages aren't in the way.
*/
-void clear_page_tables(struct task_struct * tsk)
+void clear_page_tables(struct mm_struct *mm, unsigned long first, int nr)
{
- pgd_t * page_dir = tsk->mm->pgd;
- int i;
-
- if (!page_dir || page_dir == swapper_pg_dir)
- goto out_bad;
- for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
- free_one_pgd(page_dir + i);
-
- /* keep the page table cache within bounds */
- check_pgt_cache();
- return;
+ pgd_t * page_dir = mm->pgd;
-out_bad:
- printk(KERN_ERR
- "clear_page_tables: %s trying to clear kernel pgd\n",
- tsk->comm);
- return;
+ if (page_dir && page_dir != swapper_pg_dir) {
+ page_dir += first;
+ do {
+ free_one_pgd(page_dir);
+ page_dir++;
+ } while (--nr);
+
+ /* keep the page table cache within bounds */
+ check_pgt_cache();
+ }
}
/*
- * This function frees up all page tables of a process when it exits. It
- * is the same as "clear_page_tables()", except it also frees the old
- * page table directory.
+ * This function just free's the page directory - the
+ * pages tables themselves have been freed earlier by
+ * clear_page_tables().
*/
void free_page_tables(struct mm_struct * mm)
{
pgd_t * page_dir = mm->pgd;
- int i;
- if (!page_dir)
- goto out;
- if (page_dir == swapper_pg_dir)
- goto out_bad;
- for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
- free_one_pgd(page_dir + i);
- pgd_free(page_dir);
-
- /* keep the page table cache within bounds */
- check_pgt_cache();
-out:
+ if (page_dir) {
+ if (page_dir == swapper_pg_dir)
+ goto out_bad;
+ pgd_free(page_dir);
+ }
return;
out_bad:
@@ -204,7 +192,7 @@
pgd_t * src_pgd, * dst_pgd;
unsigned long address = vma->vm_start;
unsigned long end = vma->vm_end;
- unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE;
+ unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
src_pgd = pgd_offset(src, address)-1;
dst_pgd = pgd_offset(dst, address)-1;
@@ -277,10 +265,15 @@
set_pte(dst_pte, pte);
goto cont_copy_pte_range;
}
- if (cow)
+ /* If it's a COW mapping, write protect it both in the parent and the child */
+ if (cow) {
pte = pte_wrprotect(pte);
+ set_pte(src_pte, pte);
+ }
+ /* If it's a shared mapping, mark it clean in the child */
+ if (vma->vm_flags & VM_SHARED)
+ pte = pte_mkclean(pte);
set_pte(dst_pte, pte_mkold(pte));
- set_pte(src_pte, pte);
atomic_inc(&mem_map[page_nr].count);
cont_copy_pte_range: address += PAGE_SIZE;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov