diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/mm.h | 5 | ||||
| -rw-r--r-- | include/linux/page-flags.h | 28 | ||||
| -rw-r--r-- | include/linux/swap.h | 14 |
3 files changed, 46 insertions, 1 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 163e19fd7b33..0c0b6d41dbb0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -130,6 +130,9 @@ struct vm_operations_struct { struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int unused); }; +/* forward declaration; pte_chain is meant to be internal to rmap.c */ +struct pte_chain; + /* * Each physical page in the system has a struct page associated with * it to keep track of whatever it is we are using the page for at the @@ -154,6 +157,8 @@ struct page { 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. + * protected by PG_chainlock */ unsigned long private; /* mapping-private opaque data */ /* diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 93a6f27cb454..7cdd56c8cc3e 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -47,7 +47,7 @@ * locked- and dirty-page accounting. The top eight bits of page->flags are * used for page->zone, so putting flag bits there doesn't work. */ -#define PG_locked 0 /* Page is locked. Don't touch. */ +#define PG_locked 0 /* Page is locked. Don't touch. */ #define PG_error 1 #define PG_referenced 2 #define PG_uptodate 3 @@ -65,6 +65,7 @@ #define PG_private 12 /* Has something at ->private */ #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 */ /* * Global page accounting. One instance per CPU. @@ -217,6 +218,31 @@ extern void get_page_state(struct page_state *ret); #define TestClearPageNosave(page) test_and_clear_bit(PG_nosave, &(page)->flags) /* + * inlines for acquisition and release of PG_chainlock + */ +static inline void pte_chain_lock(struct page *page) +{ + /* + * Assuming the lock is uncontended, this never enters + * the body of the outer loop. If it is contended, then + * within the inner loop a non-atomic test is used to + * busywait with less bus contention for a good time to + * attempt to acquire the lock bit. + */ + preempt_disable(); + while (test_and_set_bit(PG_chainlock, &page->flags)) { + while (test_bit(PG_chainlock, &page->flags)) + cpu_relax(); + } +} + +static inline void pte_chain_unlock(struct page *page) +{ + clear_bit(PG_chainlock, &page->flags); + preempt_enable(); +} + +/* * The PageSwapCache predicate doesn't use a PG_flag at this time, * but it may again do so one day. */ diff --git a/include/linux/swap.h b/include/linux/swap.h index 0b448a811a39..8ba0854d69af 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -142,6 +142,19 @@ struct sysinfo; struct address_space; struct zone_t; +/* linux/mm/rmap.c */ +extern int FASTCALL(page_referenced(struct page *)); +extern void FASTCALL(page_add_rmap(struct page *, pte_t *)); +extern void FASTCALL(page_remove_rmap(struct page *, pte_t *)); +extern int FASTCALL(try_to_unmap(struct page *)); +extern int FASTCALL(page_over_rsslimit(struct page *)); + +/* return values of try_to_unmap */ +#define SWAP_SUCCESS 0 +#define SWAP_AGAIN 1 +#define SWAP_FAIL 2 +#define SWAP_ERROR 3 + /* linux/mm/swap.c */ extern void FASTCALL(lru_cache_add(struct page *)); extern void FASTCALL(__lru_cache_del(struct page *)); @@ -168,6 +181,7 @@ int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page); extern void show_swap_cache_info(void); #endif extern int add_to_swap_cache(struct page *, swp_entry_t); +extern int add_to_swap(struct page *); extern void __delete_from_swap_cache(struct page *page); extern void delete_from_swap_cache(struct page *page); extern int move_to_swap_cache(struct page *page, swp_entry_t entry); |
