![Christoph Lameter](/assets/img/avatar_default.png)
We need the offset from the page struct during slab_alloc and slab_free. In both cases we also reference the cacheline of the kmem_cache_cpu structure. We can therefore move the offset field into the kmem_cache_cpu structure freeing up 16 bits in the page struct. Moving the offset allows an allocation from slab_alloc() without touching the page struct in the hot path. The only thing left in slab_free() that touches the page struct cacheline for per cpu freeing is the checking of SlabDebug(page). The next patch deals with that. Use the available 16 bits to broaden page->inuse. More than 64k objects per slab become possible and we can get rid of the checks for that limitation. No need anymore to shrink the order of slabs if we boot with 2M sized slabs (slub_min_order=9). No need anymore to switch off the offset calculation for very large slabs since the field in the kmem_cache_cpu structure is 32 bits and so the offset field can now handle slab sizes of up to 8GB. Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
220 lines
7.3 KiB
C
220 lines
7.3 KiB
C
#ifndef _LINUX_MM_TYPES_H
|
|
#define _LINUX_MM_TYPES_H
|
|
|
|
#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
|
|
#include <linux/types.h>
|
|
#include <linux/threads.h>
|
|
#include <linux/list.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/prio_tree.h>
|
|
#include <linux/rbtree.h>
|
|
#include <linux/rwsem.h>
|
|
#include <linux/completion.h>
|
|
#include <asm/page.h>
|
|
#include <asm/mmu.h>
|
|
|
|
struct address_space;
|
|
|
|
#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
|
|
typedef atomic_long_t mm_counter_t;
|
|
#else /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
|
|
typedef unsigned long mm_counter_t;
|
|
#endif /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */
|
|
|
|
/*
|
|
* 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
|
|
* moment. Note that we have no way to track which tasks are using
|
|
* a page, though if it is a pagecache page, rmap structures can tell us
|
|
* who is mapping it.
|
|
*/
|
|
struct page {
|
|
unsigned long flags; /* Atomic flags, some possibly
|
|
* updated asynchronously */
|
|
atomic_t _count; /* Usage count, see below. */
|
|
union {
|
|
atomic_t _mapcount; /* Count of ptes mapped in mms,
|
|
* to show when page is mapped
|
|
* & limit reverse map searches.
|
|
*/
|
|
unsigned int inuse; /* SLUB: Nr of objects */
|
|
};
|
|
union {
|
|
struct {
|
|
unsigned long private; /* Mapping-private opaque data:
|
|
* usually used for buffer_heads
|
|
* if PagePrivate set; used for
|
|
* swp_entry_t if PageSwapCache;
|
|
* indicates order in the buddy
|
|
* system if PG_buddy is set.
|
|
*/
|
|
struct address_space *mapping; /* If low bit clear, points to
|
|
* inode address_space, or NULL.
|
|
* If page mapped as anonymous
|
|
* memory, low bit is set, and
|
|
* it points to anon_vma object:
|
|
* see PAGE_MAPPING_ANON below.
|
|
*/
|
|
};
|
|
#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
|
|
spinlock_t ptl;
|
|
#endif
|
|
struct kmem_cache *slab; /* SLUB: Pointer to slab */
|
|
struct page *first_page; /* Compound tail pages */
|
|
};
|
|
union {
|
|
pgoff_t index; /* Our offset within mapping. */
|
|
void *freelist; /* SLUB: freelist req. slab lock */
|
|
};
|
|
struct list_head lru; /* Pageout list, eg. active_list
|
|
* protected by zone->lru_lock !
|
|
*/
|
|
/*
|
|
* On machines where all RAM is mapped into kernel address space,
|
|
* we can simply calculate the virtual address. On machines with
|
|
* highmem some memory is mapped into kernel virtual memory
|
|
* dynamically, so we need a place to store that address.
|
|
* Note that this field could be 16 bits on x86 ... ;)
|
|
*
|
|
* Architectures with slow multiplication can define
|
|
* WANT_PAGE_VIRTUAL in asm/page.h
|
|
*/
|
|
#if defined(WANT_PAGE_VIRTUAL)
|
|
void *virtual; /* Kernel virtual address (NULL if
|
|
not kmapped, ie. highmem) */
|
|
#endif /* WANT_PAGE_VIRTUAL */
|
|
};
|
|
|
|
/*
|
|
* This struct defines a memory VMM memory area. There is one of these
|
|
* per VM-area/task. A VM area is any part of the process virtual memory
|
|
* space that has a special rule for the page-fault handlers (ie a shared
|
|
* library, the executable area etc).
|
|
*/
|
|
struct vm_area_struct {
|
|
struct mm_struct * vm_mm; /* The address space we belong to. */
|
|
unsigned long vm_start; /* Our start address within vm_mm. */
|
|
unsigned long vm_end; /* The first byte after our end address
|
|
within vm_mm. */
|
|
|
|
/* linked list of VM areas per task, sorted by address */
|
|
struct vm_area_struct *vm_next;
|
|
|
|
pgprot_t vm_page_prot; /* Access permissions of this VMA. */
|
|
unsigned long vm_flags; /* Flags, listed below. */
|
|
|
|
struct rb_node vm_rb;
|
|
|
|
/*
|
|
* For areas with an address space and backing store,
|
|
* linkage into the address_space->i_mmap prio tree, or
|
|
* linkage to the list of like vmas hanging off its node, or
|
|
* linkage of vma in the address_space->i_mmap_nonlinear list.
|
|
*/
|
|
union {
|
|
struct {
|
|
struct list_head list;
|
|
void *parent; /* aligns with prio_tree_node parent */
|
|
struct vm_area_struct *head;
|
|
} vm_set;
|
|
|
|
struct raw_prio_tree_node prio_tree_node;
|
|
} shared;
|
|
|
|
/*
|
|
* A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
|
|
* list, after a COW of one of the file pages. A MAP_SHARED vma
|
|
* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
|
|
* or brk vma (with NULL file) can only be in an anon_vma list.
|
|
*/
|
|
struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
|
|
struct anon_vma *anon_vma; /* Serialized by page_table_lock */
|
|
|
|
/* Function pointers to deal with this struct. */
|
|
struct vm_operations_struct * vm_ops;
|
|
|
|
/* Information about our backing store: */
|
|
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
|
|
units, *not* PAGE_CACHE_SIZE */
|
|
struct file * vm_file; /* File we map to (can be NULL). */
|
|
void * vm_private_data; /* was vm_pte (shared mem) */
|
|
unsigned long vm_truncate_count;/* truncate_count or restart_addr */
|
|
|
|
#ifndef CONFIG_MMU
|
|
atomic_t vm_usage; /* refcount (VMAs shared if !MMU) */
|
|
#endif
|
|
#ifdef CONFIG_NUMA
|
|
struct mempolicy *vm_policy; /* NUMA policy for the VMA */
|
|
#endif
|
|
};
|
|
|
|
struct mm_struct {
|
|
struct vm_area_struct * mmap; /* list of VMAs */
|
|
struct rb_root mm_rb;
|
|
struct vm_area_struct * mmap_cache; /* last find_vma result */
|
|
unsigned long (*get_unmapped_area) (struct file *filp,
|
|
unsigned long addr, unsigned long len,
|
|
unsigned long pgoff, unsigned long flags);
|
|
void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
|
|
unsigned long mmap_base; /* base of mmap area */
|
|
unsigned long task_size; /* size of task vm space */
|
|
unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */
|
|
unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */
|
|
pgd_t * pgd;
|
|
atomic_t mm_users; /* How many users with user space? */
|
|
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
|
|
int map_count; /* number of VMAs */
|
|
struct rw_semaphore mmap_sem;
|
|
spinlock_t page_table_lock; /* Protects page tables and some counters */
|
|
|
|
struct list_head mmlist; /* List of maybe swapped mm's. These are globally strung
|
|
* together off init_mm.mmlist, and are protected
|
|
* by mmlist_lock
|
|
*/
|
|
|
|
/* Special counters, in some configurations protected by the
|
|
* page_table_lock, in other configurations by being atomic.
|
|
*/
|
|
mm_counter_t _file_rss;
|
|
mm_counter_t _anon_rss;
|
|
|
|
unsigned long hiwater_rss; /* High-watermark of RSS usage */
|
|
unsigned long hiwater_vm; /* High-water virtual memory usage */
|
|
|
|
unsigned long total_vm, locked_vm, shared_vm, exec_vm;
|
|
unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
|
|
unsigned long start_code, end_code, start_data, end_data;
|
|
unsigned long start_brk, brk, start_stack;
|
|
unsigned long arg_start, arg_end, env_start, env_end;
|
|
|
|
unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
|
|
|
|
cpumask_t cpu_vm_mask;
|
|
|
|
/* Architecture-specific MM context */
|
|
mm_context_t context;
|
|
|
|
/* Swap token stuff */
|
|
/*
|
|
* Last value of global fault stamp as seen by this process.
|
|
* In other words, this value gives an indication of how long
|
|
* it has been since this task got the token.
|
|
* Look at mm/thrash.c
|
|
*/
|
|
unsigned int faultstamp;
|
|
unsigned int token_priority;
|
|
unsigned int last_interval;
|
|
|
|
unsigned long flags; /* Must use atomic bitops to access the bits */
|
|
|
|
/* coredumping support */
|
|
int core_waiters;
|
|
struct completion *core_startup_done, core_done;
|
|
|
|
/* aio bits */
|
|
rwlock_t ioctx_list_lock;
|
|
struct kioctx *ioctx_list;
|
|
};
|
|
|
|
#endif /* _LINUX_MM_TYPES_H */
|