/* * Copyright (C) 2010 Timo Kokkonen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _PAGEMAP_H #define _PAGEMAP_H #include #include #include "utils.h" #include "list.h" #include "rbtree.h" #define PAGE_SHIFT 12 #define PAGE_SIZE (1 << PAGE_SHIFT) struct maps; struct maps_list { struct maps *map; struct list_head list; }; #define list_to_maps_list(list_head) \ container_of((list_head), struct maps_list, list) #define BITRANGE(first, last) (((2ll << (last - first)) - 1) << first) struct pageframe { struct rb_node tree; struct list_head ml; /* List of mappings which refer to this pfn */ unsigned long long pf; /* page frame entry from /proc/pid/pagemap */ unsigned long long kpageflags; unsigned long long kpagecount; int refcount; }; struct pageframe *pf_insert(struct rb_root *root, struct pageframe *pf); struct pageframe *pf_search(struct rb_root *root, struct pageframe *pf); #define rb_to_pageframe(tree_struct) \ container_of((tree_struct), struct pageframe, tree) static inline void clear_pageframe(struct pageframe *pf) { memset(pf, 0, sizeof(*pf)); INIT_LIST_HEAD(&pf->ml); } static inline int page_present(struct pageframe *p) { return !!(BITRANGE(63, 63) & p->pf); } static inline int page_swapped(struct pageframe *p) { return !!(BITRANGE(62, 62) & p->pf); } static inline int page_shift(struct pageframe *p) { return (BITRANGE(55, 60) & p->pf) >> 55; } static inline long int pfn(struct pageframe *p) { return (BITRANGE(0, 54) & p->pf); } static inline int swap_type(struct pageframe *p) { return (BITRANGE(0, 4) & p->pf); } static inline int swap_offset(struct pageframe *p) { return (BITRANGE(5, 54) & p->pf) >> 5; } enum kpageflags { LOCKED, ERROR, REFERENCED, UPTODATE, DIRTY, LRU, ACTIVE, SLAB, WRITEBACK, RECLAIM, BUDDY, MMAP, ANON, SWAPCACHE, SWAPBACKED, COMPOUND_HEAD, COMPOUND_TAIL, HUGE, UNEVICTABLE, HWPOISON, NOPAGE, KSM, THP, __PAGEFLAGS_LAST, }; #define KPAGEFLAGS_NUM __PAGEFLAGS_LAST struct kpageflag_str { int flag; char *str; }; extern struct kpageflag_str kpageflag_str[]; static inline int kpageflag_is_set(struct pageframe *p, int flag) { return !!(BITRANGE(flag, flag) & p->kpageflags); } static inline char *kpageflag_to_str(int flag) { int i; for (i = 0; i < KPAGEFLAGS_NUM; i++) if (kpageflag_str[i].flag == flag) return kpageflag_str[i].str; return NULL; } struct maps { struct list_head list; /* Memory segment of a mapping */ unsigned long start; unsigned long end; unsigned long size; long int pages_present; long int pages_swapped; /* Name of the mapping, such as library name or something else */ char name[128]; int pid; /* Process which address space the mapping belongs to */ int tid; /* thread id */ }; #define list_to_maps(list_head) \ container_of((list_head), struct maps, list) struct process { struct maps *maps; struct list_head list; int pid; int tid; char name[256]; long int pages_present; long int pages_swapped; long int pages_unique; int is_initial_pid; }; #define PARSE_PID 0x1 #define PARSE_MAP_NAME 0x2 #define PARSE_DUMP 0x8 #define PARSE_NOADD_TREE 0x10 #define PARSE_SHARED_MAPPING 0x20 struct pidlist { struct list_head list; int pid; }; struct parse_opts { struct list_head pidlist; int parse_mask; char *name; int with_threads; }; static inline void init_parse_opts(struct parse_opts *p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pidlist); } static inline struct pidlist *alloc_pidlist(void) { struct pidlist *p = calloc(sizeof(*p), 1); if (p == NULL) return p; INIT_LIST_HEAD(&p->list); return p; } #define is_parse_option(parse_opts, flag) \ (!!((parse_opts)->parse_mask & (flag))) #endif