mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-30 10:55:03 +00:00
[PATCH] mm: ptd_alloc inline and out
It seems odd to me that, whereas pud_alloc and pmd_alloc test inline, only calling out-of-line __pud_alloc __pmd_alloc if allocation needed, pte_alloc_map and pte_alloc_kernel are entirely out-of-line. Though it does add a little to kernel size, change them to macros testing inline, calling __pte_alloc or __pte_alloc_kernel to allocate out-of-line. Mark none of them as fastcalls, leave that to CONFIG_REGPARM or not. It also seems more natural for the out-of-line functions to leave the offset calculation and map to the inline, which has to do it anyway for the common case. At least mremap move wants __pte_alloc without _map. Macros rather than inline functions, certainly to avoid the header file issues which arise from CONFIG_HIGHPTE needing kmap_types.h, but also in case any architectures I haven't built would have other such problems. Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
872fec16d9
commit
1bb3630e89
4 changed files with 61 additions and 88 deletions
|
@ -10,14 +10,9 @@
|
||||||
|
|
||||||
#define pud_t pgd_t
|
#define pud_t pgd_t
|
||||||
|
|
||||||
#define pmd_alloc(mm, pud, address) \
|
#define pmd_alloc(mm, pud, address) \
|
||||||
({ pmd_t *ret; \
|
((unlikely(pgd_none(*(pud))) && __pmd_alloc(mm, pud, address))? \
|
||||||
if (pgd_none(*pud)) \
|
NULL: pmd_offset(pud, address))
|
||||||
ret = __pmd_alloc(mm, pud, address); \
|
|
||||||
else \
|
|
||||||
ret = pmd_offset(pud, address); \
|
|
||||||
ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define pud_alloc(mm, pgd, address) (pgd)
|
#define pud_alloc(mm, pgd, address) (pgd)
|
||||||
#define pud_offset(pgd, start) (pgd)
|
#define pud_offset(pgd, start) (pgd)
|
||||||
|
|
|
@ -704,10 +704,6 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int vmtruncate(struct inode * inode, loff_t offset);
|
extern int vmtruncate(struct inode * inode, loff_t offset);
|
||||||
extern pud_t *FASTCALL(__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address));
|
|
||||||
extern pmd_t *FASTCALL(__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address));
|
|
||||||
extern pte_t *FASTCALL(pte_alloc_kernel(pmd_t *pmd, unsigned long address));
|
|
||||||
extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address));
|
|
||||||
extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
|
extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot);
|
||||||
extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot);
|
extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot);
|
||||||
extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
|
extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);
|
||||||
|
@ -760,32 +756,36 @@ struct shrinker;
|
||||||
extern struct shrinker *set_shrinker(int, shrinker_t);
|
extern struct shrinker *set_shrinker(int, shrinker_t);
|
||||||
extern void remove_shrinker(struct shrinker *shrinker);
|
extern void remove_shrinker(struct shrinker *shrinker);
|
||||||
|
|
||||||
/*
|
int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address);
|
||||||
* On a two-level or three-level page table, this ends up being trivial. Thus
|
int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address);
|
||||||
* the inlining and the symmetry break with pte_alloc_map() that does all
|
int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address);
|
||||||
* of this out-of-line.
|
int __pte_alloc_kernel(pmd_t *pmd, unsigned long address);
|
||||||
*/
|
|
||||||
/*
|
/*
|
||||||
* The following ifdef needed to get the 4level-fixup.h header to work.
|
* The following ifdef needed to get the 4level-fixup.h header to work.
|
||||||
* Remove it when 4level-fixup.h has been removed.
|
* Remove it when 4level-fixup.h has been removed.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_MMU
|
#if defined(CONFIG_MMU) && !defined(__ARCH_HAS_4LEVEL_HACK)
|
||||||
#ifndef __ARCH_HAS_4LEVEL_HACK
|
|
||||||
static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
static inline pud_t *pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
||||||
{
|
{
|
||||||
if (pgd_none(*pgd))
|
return (unlikely(pgd_none(*pgd)) && __pud_alloc(mm, pgd, address))?
|
||||||
return __pud_alloc(mm, pgd, address);
|
NULL: pud_offset(pgd, address);
|
||||||
return pud_offset(pgd, address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
static inline pmd_t *pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
||||||
{
|
{
|
||||||
if (pud_none(*pud))
|
return (unlikely(pud_none(*pud)) && __pmd_alloc(mm, pud, address))?
|
||||||
return __pmd_alloc(mm, pud, address);
|
NULL: pmd_offset(pud, address);
|
||||||
return pmd_offset(pud, address);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* CONFIG_MMU && !__ARCH_HAS_4LEVEL_HACK */
|
||||||
#endif /* CONFIG_MMU */
|
|
||||||
|
#define pte_alloc_map(mm, pmd, address) \
|
||||||
|
((unlikely(!pmd_present(*(pmd))) && __pte_alloc(mm, pmd, address))? \
|
||||||
|
NULL: pte_offset_map(pmd, address))
|
||||||
|
|
||||||
|
#define pte_alloc_kernel(pmd, address) \
|
||||||
|
((unlikely(!pmd_present(*(pmd))) && __pte_alloc_kernel(pmd, address))? \
|
||||||
|
NULL: pte_offset_kernel(pmd, address))
|
||||||
|
|
||||||
extern void free_area_init(unsigned long * zones_size);
|
extern void free_area_init(unsigned long * zones_size);
|
||||||
extern void free_area_init_node(int nid, pg_data_t *pgdat,
|
extern void free_area_init_node(int nid, pg_data_t *pgdat,
|
||||||
|
|
93
mm/memory.c
93
mm/memory.c
|
@ -280,50 +280,39 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_t fastcall *pte_alloc_map(struct mm_struct *mm, pmd_t *pmd,
|
int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
|
||||||
unsigned long address)
|
|
||||||
{
|
{
|
||||||
if (!pmd_present(*pmd)) {
|
struct page *new;
|
||||||
struct page *new;
|
|
||||||
|
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
new = pte_alloc_one(mm, address);
|
new = pte_alloc_one(mm, address);
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
if (!new)
|
if (!new)
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
/*
|
|
||||||
* Because we dropped the lock, we should re-check the
|
if (pmd_present(*pmd)) /* Another has populated it */
|
||||||
* entry, as somebody else could have populated it..
|
pte_free(new);
|
||||||
*/
|
else {
|
||||||
if (pmd_present(*pmd)) {
|
|
||||||
pte_free(new);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
mm->nr_ptes++;
|
mm->nr_ptes++;
|
||||||
inc_page_state(nr_page_table_pages);
|
inc_page_state(nr_page_table_pages);
|
||||||
pmd_populate(mm, pmd, new);
|
pmd_populate(mm, pmd, new);
|
||||||
}
|
}
|
||||||
out:
|
return 0;
|
||||||
return pte_offset_map(pmd, address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pte_t fastcall * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
|
int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
|
||||||
{
|
{
|
||||||
if (!pmd_present(*pmd)) {
|
pte_t *new = pte_alloc_one_kernel(&init_mm, address);
|
||||||
pte_t *new;
|
if (!new)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
new = pte_alloc_one_kernel(&init_mm, address);
|
spin_lock(&init_mm.page_table_lock);
|
||||||
if (!new)
|
if (pmd_present(*pmd)) /* Another has populated it */
|
||||||
return NULL;
|
pte_free_kernel(new);
|
||||||
|
else
|
||||||
spin_lock(&init_mm.page_table_lock);
|
pmd_populate_kernel(&init_mm, pmd, new);
|
||||||
if (pmd_present(*pmd))
|
spin_unlock(&init_mm.page_table_lock);
|
||||||
pte_free_kernel(new);
|
return 0;
|
||||||
else
|
|
||||||
pmd_populate_kernel(&init_mm, pmd, new);
|
|
||||||
spin_unlock(&init_mm.page_table_lock);
|
|
||||||
}
|
|
||||||
return pte_offset_kernel(pmd, address);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss)
|
static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss)
|
||||||
|
@ -2093,7 +2082,7 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||||
* Allocate page upper directory.
|
* Allocate page upper directory.
|
||||||
* We've already handled the fast-path in-line.
|
* We've already handled the fast-path in-line.
|
||||||
*/
|
*/
|
||||||
pud_t fastcall *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
|
||||||
{
|
{
|
||||||
pud_t *new;
|
pud_t *new;
|
||||||
|
|
||||||
|
@ -2103,19 +2092,17 @@ pud_t fastcall *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr
|
||||||
if (!new) {
|
if (!new) {
|
||||||
if (mm != &init_mm) /* Temporary bridging hack */
|
if (mm != &init_mm) /* Temporary bridging hack */
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
if (pgd_present(*pgd)) {
|
if (pgd_present(*pgd)) /* Another has populated it */
|
||||||
pud_free(new);
|
pud_free(new);
|
||||||
goto out;
|
else
|
||||||
}
|
pgd_populate(mm, pgd, new);
|
||||||
pgd_populate(mm, pgd, new);
|
|
||||||
out:
|
|
||||||
if (mm == &init_mm) /* Temporary bridging hack */
|
if (mm == &init_mm) /* Temporary bridging hack */
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
return pud_offset(pgd, address);
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* __PAGETABLE_PUD_FOLDED */
|
#endif /* __PAGETABLE_PUD_FOLDED */
|
||||||
|
|
||||||
|
@ -2124,7 +2111,7 @@ pud_t fastcall *__pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr
|
||||||
* Allocate page middle directory.
|
* Allocate page middle directory.
|
||||||
* We've already handled the fast-path in-line.
|
* We've already handled the fast-path in-line.
|
||||||
*/
|
*/
|
||||||
pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
||||||
{
|
{
|
||||||
pmd_t *new;
|
pmd_t *new;
|
||||||
|
|
||||||
|
@ -2134,28 +2121,24 @@ pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr
|
||||||
if (!new) {
|
if (!new) {
|
||||||
if (mm != &init_mm) /* Temporary bridging hack */
|
if (mm != &init_mm) /* Temporary bridging hack */
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
return NULL;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&mm->page_table_lock);
|
spin_lock(&mm->page_table_lock);
|
||||||
#ifndef __ARCH_HAS_4LEVEL_HACK
|
#ifndef __ARCH_HAS_4LEVEL_HACK
|
||||||
if (pud_present(*pud)) {
|
if (pud_present(*pud)) /* Another has populated it */
|
||||||
pmd_free(new);
|
pmd_free(new);
|
||||||
goto out;
|
else
|
||||||
}
|
pud_populate(mm, pud, new);
|
||||||
pud_populate(mm, pud, new);
|
|
||||||
#else
|
#else
|
||||||
if (pgd_present(*pud)) {
|
if (pgd_present(*pud)) /* Another has populated it */
|
||||||
pmd_free(new);
|
pmd_free(new);
|
||||||
goto out;
|
else
|
||||||
}
|
pgd_populate(mm, pud, new);
|
||||||
pgd_populate(mm, pud, new);
|
|
||||||
#endif /* __ARCH_HAS_4LEVEL_HACK */
|
#endif /* __ARCH_HAS_4LEVEL_HACK */
|
||||||
|
|
||||||
out:
|
|
||||||
if (mm == &init_mm) /* Temporary bridging hack */
|
if (mm == &init_mm) /* Temporary bridging hack */
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
return pmd_offset(pud, address);
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* __PAGETABLE_PMD_FOLDED */
|
#endif /* __PAGETABLE_PMD_FOLDED */
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ static pmd_t *alloc_new_pmd(struct mm_struct *mm, unsigned long addr)
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pud_t *pud;
|
pud_t *pud;
|
||||||
pmd_t *pmd = NULL;
|
pmd_t *pmd = NULL;
|
||||||
pte_t *pte;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do need page_table_lock: because allocators expect that.
|
* We do need page_table_lock: because allocators expect that.
|
||||||
|
@ -66,12 +65,8 @@ static pmd_t *alloc_new_pmd(struct mm_struct *mm, unsigned long addr)
|
||||||
if (!pmd)
|
if (!pmd)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
pte = pte_alloc_map(mm, pmd, addr);
|
if (!pmd_present(*pmd) && __pte_alloc(mm, pmd, addr))
|
||||||
if (!pte) {
|
|
||||||
pmd = NULL;
|
pmd = NULL;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
pte_unmap(pte);
|
|
||||||
out:
|
out:
|
||||||
spin_unlock(&mm->page_table_lock);
|
spin_unlock(&mm->page_table_lock);
|
||||||
return pmd;
|
return pmd;
|
||||||
|
|
Loading…
Add table
Reference in a new issue