From: Dave McCracken <dmccr@us.ibm.com>
To: Linux Memory Management <linux-mm@kvack.org>
Subject: [PATCH] Optimize away pte_chains for single mappings
Date: Tue, 09 Jul 2002 13:35:46 -0500 [thread overview]
Message-ID: <55160000.1026239746@baldur.austin.ibm.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 723 bytes --]
Here's a patch that optimizes out using a struct pte_chain when there's
only one mapping for that page. It re-uses the pte_chain pointer in struct
page, with an appropriate flag. The patch is based on Rik's latest 2.5.25
rmap patch.
I've done basic testing on it (it boots and runs simple commands).
This version of the patch uses an anonymous union, so it only builds with
gcc 3.x. I'm working on an alternate version of the patch, but wanted to
get this one out for people to look at.
Dave McCracken
======================================================================
Dave McCracken IBM Linux Base Kernel Team 1-512-838-3059
dmccr@us.ibm.com T/L 678-3059
[-- Attachment #2: rmap-opt-2.5.25.diff --]
[-- Type: text/plain, Size: 6289 bytes --]
--- linux-2.5.25-rmap/./include/linux/mm.h Mon Jul 8 15:37:35 2002
+++ linux-2.5.25-rmap-opt/./include/linux/mm.h Tue Jul 9 13:28:32 2002
@@ -157,8 +157,11 @@
updated asynchronously */
struct list_head lru; /* Pageout list, eg. active_list;
protected by pagemap_lru_lock !! */
- struct pte_chain * pte_chain; /* Reverse pte mapping pointer.
+ union {
+ struct pte_chain * pte_chain; /* Reverse pte mapping pointer.
* protected by PG_chainlock */
+ pte_t * pte_direct;
+ };
unsigned long private; /* mapping-private opaque data */
/*
--- linux-2.5.25-rmap/./include/linux/page-flags.h Mon Jul 8 15:37:35 2002
+++ linux-2.5.25-rmap-opt/./include/linux/page-flags.h Tue Jul 9 10:31:28 2002
@@ -66,6 +66,7 @@
#define PG_writeback 13 /* Page is under writeback */
#define PG_nosave 15 /* Used for system suspend/resume */
#define PG_chainlock 16 /* lock bit for ->pte_chain */
+#define PG_direct 17 /* ->pte_chain points directly at pte */
/*
* Global page accounting. One instance per CPU.
@@ -216,6 +217,12 @@
#define TestSetPageNosave(page) test_and_set_bit(PG_nosave, &(page)->flags)
#define ClearPageNosave(page) clear_bit(PG_nosave, &(page)->flags)
#define TestClearPageNosave(page) test_and_clear_bit(PG_nosave, &(page)->flags)
+
+#define PageDirect(page) test_bit(PG_direct, &(page)->flags)
+#define SetPageDirect(page) set_bit(PG_direct, &(page)->flags)
+#define TestSetPageDirect(page) test_and_set_bit(PG_direct, &(page)->flags)
+#define ClearPageDirect(page) clear_bit(PG_direct, &(page)->flags)
+#define TestClearPageDirect(page) test_and_clear_bit(PG_direct, &(page)->flags)
/*
* inlines for acquisition and release of PG_chainlock
--- linux-2.5.25-rmap/./mm/rmap.c Mon Jul 8 15:37:35 2002
+++ linux-2.5.25-rmap-opt/./mm/rmap.c Tue Jul 9 12:46:07 2002
@@ -71,10 +71,15 @@
if (TestClearPageReferenced(page))
referenced++;
- /* Check all the page tables mapping this page. */
- for (pc = page->pte_chain; pc; pc = pc->next) {
- if (ptep_test_and_clear_young(pc->ptep))
+ if (PageDirect(page)) {
+ if (ptep_test_and_clear_young(page->pte_direct))
referenced++;
+ } else {
+ /* Check all the page tables mapping this page. */
+ for (pc = page->pte_chain; pc; pc = pc->next) {
+ if (ptep_test_and_clear_young(pc->ptep))
+ referenced++;
+ }
}
return referenced;
}
@@ -108,22 +113,39 @@
pte_chain_lock(page);
{
struct pte_chain * pc;
- for (pc = page->pte_chain; pc; pc = pc->next) {
- if (pc->ptep == ptep)
+ if (PageDirect(page)) {
+ if (page->pte_direct == ptep)
BUG();
+ } else {
+ for (pc = page->pte_chain; pc; pc = pc->next) {
+ if (pc->ptep == ptep)
+ BUG();
+ }
}
}
pte_chain_unlock(page);
#endif
- pte_chain = pte_chain_alloc();
-
pte_chain_lock(page);
- /* Hook up the pte_chain to the page. */
- pte_chain->ptep = ptep;
- pte_chain->next = page->pte_chain;
- page->pte_chain = pte_chain;
+ if (PageDirect(page)) {
+ /* Convert a direct pointer into a pte_chain */
+ pte_chain = pte_chain_alloc();
+ pte_chain->ptep = page->pte_direct;
+ pte_chain->next = NULL;
+ page->pte_chain = pte_chain;
+ ClearPageDirect(page);
+ }
+ if (page->pte_chain) {
+ /* Hook up the pte_chain to the page. */
+ pte_chain = pte_chain_alloc();
+ pte_chain->ptep = ptep;
+ pte_chain->next = page->pte_chain;
+ page->pte_chain = pte_chain;
+ } else {
+ page->pte_direct = ptep;
+ SetPageDirect(page);
+ }
pte_chain_unlock(page);
}
@@ -149,18 +171,38 @@
return;
pte_chain_lock(page);
- for (pc = page->pte_chain; pc; prev_pc = pc, pc = pc->next) {
- if (pc->ptep == ptep) {
- pte_chain_free(pc, prev_pc, page);
+
+ if (PageDirect(page)) {
+ if (page->pte_direct == ptep) {
+ page->pte_direct = NULL;
+ ClearPageDirect(page);
goto out;
}
+ } else {
+ for (pc = page->pte_chain; pc; prev_pc = pc, pc = pc->next) {
+ if (pc->ptep == ptep) {
+ pte_chain_free(pc, prev_pc, page);
+ /* Check whether we can convert to direct */
+ pc = page->pte_chain;
+ if (!pc->next) {
+ page->pte_direct = pc->ptep;
+ SetPageDirect(page);
+ pte_chain_free(pc, NULL, NULL);
+ }
+ goto out;
+ }
+ }
}
#ifdef DEBUG_RMAP
/* Not found. This should NEVER happen! */
printk(KERN_ERR "page_remove_rmap: pte_chain %p not present.\n", ptep);
printk(KERN_ERR "page_remove_rmap: only found: ");
- for (pc = page->pte_chain; pc; pc = pc->next)
- printk("%p ", pc->ptep);
+ if (PageDirect(page)) {
+ printk("%p ", page->pte_direct);
+ } else {
+ for (pc = page->pte_chain; pc; pc = pc->next)
+ printk("%p ", pc->ptep);
+ }
printk("\n");
printk(KERN_ERR "page_remove_rmap: driver cleared PG_reserved ?\n");
#endif
@@ -270,22 +312,42 @@
if (!page->mapping)
BUG();
- for (pc = page->pte_chain; pc; pc = next_pc) {
- next_pc = pc->next;
- switch (try_to_unmap_one(page, pc->ptep)) {
+ if (PageDirect(page)) {
+ switch (ret = try_to_unmap_one(page, page->pte_direct)) {
case SWAP_SUCCESS:
- /* Free the pte_chain struct. */
- pte_chain_free(pc, prev_pc, page);
- break;
+ page->pte_direct = NULL;
+ ClearPageDirect(page);
+ return ret;
case SWAP_AGAIN:
- /* Skip this pte, remembering status. */
- prev_pc = pc;
- ret = SWAP_AGAIN;
- continue;
case SWAP_FAIL:
- return SWAP_FAIL;
case SWAP_ERROR:
- return SWAP_ERROR;
+ return ret;
+ }
+ } else {
+ for (pc = page->pte_chain; pc; pc = next_pc) {
+ next_pc = pc->next;
+ switch (try_to_unmap_one(page, pc->ptep)) {
+ case SWAP_SUCCESS:
+ /* Free the pte_chain struct. */
+ pte_chain_free(pc, prev_pc, page);
+ break;
+ case SWAP_AGAIN:
+ /* Skip this pte, remembering status. */
+ prev_pc = pc;
+ ret = SWAP_AGAIN;
+ continue;
+ case SWAP_FAIL:
+ return SWAP_FAIL;
+ case SWAP_ERROR:
+ return SWAP_ERROR;
+ }
+ }
+ /* Check whether we can convert to direct pte pointer */
+ pc = page->pte_chain;
+ if (pc && !pc->next) {
+ page->pte_direct = pc->ptep;
+ SetPageDirect(page);
+ pte_chain_free(pc, NULL, NULL);
}
}
next reply other threads:[~2002-07-09 18:36 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-07-09 18:35 Dave McCracken [this message]
2002-07-13 13:13 ` Daniel Phillips
2002-07-15 14:02 ` Dave McCracken
2002-07-15 14:56 ` Daniel Phillips
2002-07-15 15:40 ` Matti Aarnio
2002-07-15 16:10 ` Daniel Phillips
2002-07-15 16:34 ` Rik van Riel
2002-07-15 16:42 ` Daniel Phillips
2002-07-15 20:57 ` Andrew Morton
2002-07-16 4:50 ` Daniel Phillips
2002-07-15 16:30 ` Daniel Phillips
2002-07-15 16:55 ` Matti Aarnio
2002-07-15 17:50 ` Daniel Phillips
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55160000.1026239746@baldur.austin.ibm.com \
--to=dmccr@us.ibm.com \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox