patch-1.3.39 linux/mm/memory.c

Next file: linux/mm/mmap.c
Previous file: linux/kernel/ksyms.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.38/linux/mm/memory.c linux/mm/memory.c
@@ -118,60 +118,30 @@
 	pmd_free(pmd);
 }
 	
-int new_page_tables(struct task_struct * tsk)
-{
-	pgd_t * page_dir, * new_pg;
-	int i;
-
-	if (!(new_pg = pgd_alloc()))
-		return -ENOMEM;
-	page_dir = pgd_offset(&init_mm, 0);
-	for (i = USER_PTRS_PER_PGD ; i < PTRS_PER_PGD ; i++)
-		new_pg[i] = page_dir[i];
-	SET_PAGE_DIR(tsk, new_pg);
-	tsk->mm->pgd = new_pg;
-	return 0;
-}
-
 /*
  * 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. Note that
- * unlike 'free_page_tables()', this function still leaves a valid
- * page-table-tree in memory: it just removes the user pages. The two
- * functions are similar, but there is a fundamental difference.
+ * is needed by execve(), so that old pages aren't in the way.
  */
 void clear_page_tables(struct task_struct * tsk)
 {
 	int i;
 	pgd_t * page_dir;
 
-	if (!tsk)
-		return;
-	if (tsk == task[0])
-		panic("task[0] (swapper) doesn't support exec()\n");
-	page_dir = pgd_offset(tsk->mm, 0);
-	if (!page_dir) {
-		printk("%s trying to clear NULL page-directory: not good\n", tsk->comm);
-		return;
-	}
-	if (pgd_inuse(page_dir)) {
-		if (new_page_tables(tsk))
-			oom(tsk);
-		pgd_free(page_dir);
-		return;
-	}
-	if (page_dir == swapper_pg_dir) {
+	page_dir = tsk->mm->pgd;
+	if (!page_dir || page_dir == swapper_pg_dir) {
 		printk("%s trying to clear kernel page-directory: not good\n", tsk->comm);
 		return;
 	}
 	for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
 		free_one_pgd(page_dir + i);
 	invalidate();
-	return;
 }
 
 /*
- * This function frees up all page tables of a process when it exits.
+ * This function frees up all page tables of a process when it exits. It
+ * is the same as "clear_page_tables()", except it also changes the process'
+ * page table directory to the kernel page tables and then frees the old
+ * page table directory.
  */
 void free_page_tables(struct task_struct * tsk)
 {
@@ -184,10 +154,6 @@
 		return;
 	}
 	SET_PAGE_DIR(tsk, swapper_pg_dir);
-	if (pgd_inuse(page_dir)) {
-		pgd_free(page_dir);
-		return;
-	}
 	tsk->mm->pgd = swapper_pg_dir;	/* or else... */
 	for (i = 0 ; i < PTRS_PER_PGD ; i++)
 		free_one_pgd(page_dir + i);
@@ -195,6 +161,21 @@
 	invalidate();
 }
 
+int new_page_tables(struct task_struct * tsk)
+{
+	pgd_t * page_dir, * new_pg;
+	int i;
+
+	if (!(new_pg = pgd_alloc()))
+		return -ENOMEM;
+	page_dir = pgd_offset(&init_mm, 0);
+	for (i = USER_PTRS_PER_PGD ; i < PTRS_PER_PGD ; i++)
+		new_pg[i] = page_dir[i];
+	SET_PAGE_DIR(tsk, new_pg);
+	tsk->mm->pgd = new_pg;
+	return 0;
+}
+
 static inline void copy_one_pte(pte_t * old_pte, pte_t * new_pte)
 {
 	pte_t pte = *old_pte;
@@ -324,7 +305,7 @@
 	swap_free(pte_val(page));
 }
 
-static inline void unmap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size)
+static inline void zap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size)
 {
 	pte_t * pte;
 	unsigned long end;
@@ -332,7 +313,7 @@
 	if (pmd_none(*pmd))
 		return;
 	if (pmd_bad(*pmd)) {
-		printk("unmap_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
+		printk("zap_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
 		pmd_clear(pmd);
 		return;
 	}
@@ -350,7 +331,7 @@
 	} while (address < end);
 }
 
-static inline void unmap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size)
+static inline void zap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size)
 {
 	pmd_t * pmd;
 	unsigned long end;
@@ -358,7 +339,7 @@
 	if (pgd_none(*dir))
 		return;
 	if (pgd_bad(*dir)) {
-		printk("unmap_pmd_range: bad pgd (%08lx)\n", pgd_val(*dir));
+		printk("zap_pmd_range: bad pgd (%08lx)\n", pgd_val(*dir));
 		pgd_clear(dir);
 		return;
 	}
@@ -368,7 +349,7 @@
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	do {
-		unmap_pte_range(pmd, address, end - address);
+		zap_pte_range(pmd, address, end - address);
 		address = (address + PMD_SIZE) & PMD_MASK; 
 		pmd++;
 	} while (address < end);
@@ -384,21 +365,12 @@
 
 	dir = pgd_offset(mm, address);
 	while (address < end) {
-		unmap_pmd_range(dir, address, end - address);
+		zap_pmd_range(dir, address, end - address);
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
 		dir++;
 	}
 	invalidate();
 	return 0;
-}
-
-/*
- * a more complete version of free_page_tables which performs with page
- * granularity.
- */
-int unmap_page_range(unsigned long address, unsigned long size)
-{
-	return zap_page_range(current->mm, address, size);
 }
 
 static inline void zeromap_pte_range(pte_t * pte, unsigned long address, unsigned long size, pte_t zero_pte)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this