📄 mm.h
字号:
#else /* CONFIG_HIGHMEM || WANT_PAGE_VIRTUAL */#define set_page_address(page, address) do { } while(0)#ifdef CONFIG_DISCONTIGMEM#define page_address(page) \ __va( ((page) - page_zone(page)->zone_mem_map) + \ page_zone(page)->zone_start_pfn << PAGE_SHIFT)#else#define page_address(page) __va(((page) - mem_map) << PAGE_SHIFT)#endif#endif /* CONFIG_HIGHMEM || WANT_PAGE_VIRTUAL */extern void FASTCALL(set_page_dirty(struct page *));/* * The first mb is necessary to safely close the critical section opened by the * TryLockPage(), the second mb is necessary to enforce ordering between * the clear_bit and the read of the waitqueue (to avoid SMP races with a * parallel wait_on_page). */#define PageError(page) test_bit(PG_error, &(page)->flags)#define SetPageError(page) set_bit(PG_error, &(page)->flags)#define ClearPageError(page) clear_bit(PG_error, &(page)->flags)#define PageReferenced(page) test_bit(PG_referenced, &(page)->flags)#define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags)#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags)#define PageTestandClearReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)#define PageSlab(page) test_bit(PG_slab, &(page)->flags)#define PageSetSlab(page) set_bit(PG_slab, &(page)->flags)#define PageClearSlab(page) clear_bit(PG_slab, &(page)->flags)#define PageReserved(page) test_bit(PG_reserved, &(page)->flags)#define PageActive(page) test_bit(PG_active, &(page)->flags)#define SetPageActive(page) set_bit(PG_active, &(page)->flags)#define ClearPageActive(page) clear_bit(PG_active, &(page)->flags)#define PageLRU(page) test_bit(PG_lru, &(page)->flags)#define TestSetPageLRU(page) test_and_set_bit(PG_lru, &(page)->flags)#define TestClearPageLRU(page) test_and_clear_bit(PG_lru, &(page)->flags)#ifdef CONFIG_HIGHMEM#define PageHighMem(page) test_bit(PG_highmem, &(page)->flags)#else#define PageHighMem(page) 0 /* needed to optimize away at compile time */#endif#define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags)#define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags)/* * Error return values for the *_nopage functions */#define NOPAGE_SIGBUS (NULL)#define NOPAGE_OOM ((struct page *) (-1))/* The array of struct pages */extern mem_map_t * mem_map;/* * There is only one page-allocator function, and two main namespaces to * it. The alloc_page*() variants return 'struct page *' and as such * can allocate highmem pages, the *get*page*() variants return * virtual kernel addresses to the allocated page(s). */extern struct page * FASTCALL(__alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist));extern struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order);static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order){ /* * Gets optimized away by the compiler. */ if (order >= MAX_ORDER) return NULL; /* * we get the zone list from the current node and the gfp_mask. * This zone list contains a maximum of * MAXNODES*MAX_NR_ZONES zones. */#ifndef HAVE_ARCH_VALIDATE return __alloc_pages(gfp_mask, order, NODE_DATA(numa_node_id())->node_zonelists + (gfp_mask & GFP_ZONEMASK));#else return arch_validate(__alloc_pages(gfp_mask, order, NODE_DATA(numa_node_id())->node_zonelists + (gfp_mask & GFP_ZONEMASK)), gfp_mask, order);#endif}#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)extern unsigned long FASTCALL(__get_free_pages(unsigned int gfp_mask, unsigned int order));extern unsigned long FASTCALL(get_zeroed_page(unsigned int gfp_mask));#define __get_free_page(gfp_mask) \ __get_free_pages((gfp_mask),0)#define __get_dma_pages(gfp_mask, order) \ __get_free_pages((gfp_mask) | GFP_DMA,(order))/* * The old interface name will be removed in 2.5: */#define get_free_page get_zeroed_page/* * There is only one 'core' page-freeing function. */extern void FASTCALL(__free_pages(struct page *page, unsigned int order));extern void FASTCALL(free_pages(unsigned long addr, unsigned int order));extern void * FASTCALL(alloc_exact(unsigned int size));extern void FASTCALL(free_exact(void * addr, unsigned int size));#define __free_page(page) __free_pages((page), 0)#define free_page(addr) free_pages((addr),0)extern int start_aggressive_readahead(unsigned int);extern void show_free_areas(void);extern void show_free_areas_node(pg_data_t *pgdat);extern void clear_page_tables(struct mm_struct *, unsigned long, int);extern int fail_writepage(struct page *);struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);struct file *shmem_file_setup(char * name, loff_t size);extern void shmem_lock(struct file * file, int lock);extern int shmem_zero_setup(struct vm_area_struct *);extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma);extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot);extern int vmtruncate(struct inode * inode, loff_t offset);extern pmd_t *FASTCALL(__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address));extern pte_t *FASTCALL(pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address));extern pte_t *FASTCALL(pte_alloc_atomic(struct mm_struct *mm, pmd_t *pmd, unsigned long address));extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access);extern int make_pages_present(unsigned long addr, unsigned long end);extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char *dst, int len);extern int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int len);extern int ptrace_attach(struct task_struct *tsk);extern int ptrace_detach(struct task_struct *, unsigned int);extern void ptrace_disable(struct task_struct *);extern int ptrace_check_attach(struct task_struct *task, int kill);int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);/* * On a two-level page table, this ends up being trivial. Thus the * inlining and the symmetry break with pte_alloc() that does all * of this out-of-line. */static inline pmd_t *pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address){ if (pgd_none(*pgd)) return __pmd_alloc(mm, pgd, address); return pmd_offset(pgd, address);}extern int pgt_cache_water[2];extern int check_pgt_cache(void);extern void free_area_init(unsigned long * zones_size);extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap, unsigned long * zones_size, unsigned long zone_start_pfn, unsigned long *zholes_size);extern void mem_init(void);extern void show_mem(void);extern void si_meminfo(struct sysinfo * val);extern void swapin_readahead(swp_entry_t);extern struct address_space swapper_space;#define PageSwapCache(page) ((page)->mapping == &swapper_space)static inline int is_page_cache_freeable(struct page * page){ return page_count(page) - !!page->buffers == 1;}extern int FASTCALL(make_exclusive_page(struct page *, int));extern int FASTCALL(remove_exclusive_swap_page(struct page *));extern void __free_pte(pte_t);/* mmap.c */extern void lock_vma_mappings(struct vm_area_struct *);extern void unlock_vma_mappings(struct vm_area_struct *);extern void insert_vm_struct(struct mm_struct *, struct vm_area_struct *);extern void __insert_vm_struct(struct mm_struct *, struct vm_area_struct *);extern void build_mmap_rb(struct mm_struct *);extern void exit_mmap(struct mm_struct *);extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long pgoff);static inline unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset){ unsigned long ret = -EINVAL; if ((offset + PAGE_ALIGN(len)) < offset) goto out; if (!(offset & ~PAGE_MASK)) ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);out: return ret;}extern int do_munmap(struct mm_struct *, unsigned long, size_t);extern unsigned long do_brk(unsigned long, unsigned long);static inline void __vma_unlink(struct mm_struct * mm, struct vm_area_struct * vma, struct vm_area_struct * prev){ prev->vm_next = vma->vm_next; rb_erase(&vma->vm_rb, &mm->mm_rb); if (mm->mmap_cache == vma) mm->mmap_cache = prev;}static inline int can_vma_merge(struct vm_area_struct * vma, unsigned long vm_flags){ if (!vma->vm_file && vma->vm_flags == vm_flags) return 1; else return 0;}struct zone_t;/* filemap.c */extern void remove_inode_page(struct page *);extern unsigned long page_unuse(struct page *);extern void truncate_inode_pages(struct address_space *, loff_t);/* generic vm_area_ops exported for stackable file systems */extern int filemap_sync(struct vm_area_struct *, unsigned long, size_t, unsigned int);extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int);/* * GFP bitmasks.. *//* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low four bits) */#define __GFP_DMA 0x01#define __GFP_HIGHMEM 0x02/* Action modifiers - doesn't change the zoning */#define __GFP_WAIT 0x10 /* Can wait and reschedule? */#define __GFP_HIGH 0x20 /* Should access emergency pools? */#define __GFP_IO 0x40 /* Can start low memory physical IO? */#define __GFP_HIGHIO 0x80 /* Can start high mem physical IO? */#define __GFP_FS 0x100 /* Can call down to low-level FS? */#define GFP_NOHIGHIO (__GFP_HIGH | __GFP_WAIT | __GFP_IO)#define GFP_NOIO (__GFP_HIGH | __GFP_WAIT)#define GFP_NOFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO)#define GFP_ATOMIC (__GFP_HIGH)#define GFP_USER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)#define GFP_HIGHUSER ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS | __GFP_HIGHMEM)#define GFP_KERNEL (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)#define GFP_KSWAPD ( __GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_FS)/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */#define GFP_DMA __GFP_DMAstatic inline unsigned int pf_gfp_mask(unsigned int gfp_mask){ /* avoid all memory balancing I/O methods if this task cannot block on I/O */ if (current->flags & PF_NOIO) gfp_mask &= ~(__GFP_IO | __GFP_HIGHIO | __GFP_FS); return gfp_mask;}extern int heap_stack_gap;/* * vma is the first one with address < vma->vm_end, * and even address < vma->vm_start. Have to extend vma. * * Locking: vm_start can decrease under you if you only hold * the read semaphore, you either need the write semaphore * or both the read semaphore and the page_table_lock acquired * if you want vm_start consistent. vm_end and the vma layout * are just consistent with only the read semaphore acquired * instead. */#define EXPAND_STACK_HAS_3_ARGSstatic inline int expand_stack(struct vm_area_struct * vma, unsigned long address, struct vm_area_struct * prev_vma){ unsigned long grow; int err = -ENOMEM; /* * vma->vm_start/vm_end cannot change under us because the caller is required * to hold the mmap_sem in write mode. We need to get the spinlock only * before relocating the vma range ourself. */ address &= PAGE_MASK; if (prev_vma && prev_vma->vm_end + (heap_stack_gap << PAGE_SHIFT) > address) goto out; spin_lock(&vma->vm_mm->page_table_lock); grow = (vma->vm_start - address) >> PAGE_SHIFT; if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur) goto out_unlock; vma->vm_start = address; vma->vm_pgoff -= grow; vma->vm_mm->total_vm += grow; if (vma->vm_flags & VM_LOCKED) vma->vm_mm->locked_vm += grow; err = 0; out_unlock: spin_unlock(&vma->vm_mm->page_table_lock); out: return err;}/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr, struct vm_area_struct **pprev);/* Look up the first VMA which intersects the interval start_addr..end_addr-1, NULL if none. Assume start_addr < end_addr. */static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr){ struct vm_area_struct * vma = find_vma(mm,start_addr); if (vma && end_addr <= vma->vm_start) vma = NULL; return vma;}extern struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr);extern struct page * vmalloc_to_page(void *addr);#endif /* __KERNEL__ */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -