Merge second patch-bomb from Andrew Morton: - a couple of hotfixes - the rest of MM - a new timer slack control in procfs - a couple of procfs fixes - a few misc things - some printk tweaks - lib/ updates, notably to radix-tree. - add my and Nick Piggin's old userspace radix-tree test harness to tools/testing/radix-tree/. Matthew said it was a godsend during the radix-tree work he did. - a few code-size improvements, switching to __always_inline where gcc screwed up. - partially implement character sets in sscanf * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (118 commits) sscanf: implement basic character sets lib/bug.c: use common WARN helper param: convert some "on"/"off" users to strtobool lib: add "on"/"off" support to kstrtobool lib: update single-char callers of strtobool() lib: move strtobool() to kstrtobool() include/linux/unaligned: force inlining of byteswap operations include/uapi/linux/byteorder, swab: force inlining of some byteswap operations include/asm-generic/atomic-long.h: force inlining of some atomic_long operations usb: common: convert to use match_string() helper ide: hpt366: convert to use match_string() helper ata: hpt366: convert to use match_string() helper power: ab8500: convert to use match_string() helper power: charger_manager: convert to use match_string() helper drm/edid: convert to use match_string() helper pinctrl: convert to use match_string() helper device property: convert to use match_string() helper lib/string: introduce match_string() helper radix-tree tests: add test for radix_tree_iter_next radix-tree tests: add regression3 test ...tirimbino
commit
814a2bf957
@ -0,0 +1,173 @@ |
||||
#ifndef _LINUX_PAGE_REF_H |
||||
#define _LINUX_PAGE_REF_H |
||||
|
||||
#include <linux/atomic.h> |
||||
#include <linux/mm_types.h> |
||||
#include <linux/page-flags.h> |
||||
#include <linux/tracepoint-defs.h> |
||||
|
||||
extern struct tracepoint __tracepoint_page_ref_set; |
||||
extern struct tracepoint __tracepoint_page_ref_mod; |
||||
extern struct tracepoint __tracepoint_page_ref_mod_and_test; |
||||
extern struct tracepoint __tracepoint_page_ref_mod_and_return; |
||||
extern struct tracepoint __tracepoint_page_ref_mod_unless; |
||||
extern struct tracepoint __tracepoint_page_ref_freeze; |
||||
extern struct tracepoint __tracepoint_page_ref_unfreeze; |
||||
|
||||
#ifdef CONFIG_DEBUG_PAGE_REF |
||||
|
||||
/*
|
||||
* Ideally we would want to use the trace_<tracepoint>_enabled() helper |
||||
* functions. But due to include header file issues, that is not |
||||
* feasible. Instead we have to open code the static key functions. |
||||
* |
||||
* See trace_##name##_enabled(void) in include/linux/tracepoint.h |
||||
*/ |
||||
#define page_ref_tracepoint_active(t) static_key_false(&(t).key) |
||||
|
||||
extern void __page_ref_set(struct page *page, int v); |
||||
extern void __page_ref_mod(struct page *page, int v); |
||||
extern void __page_ref_mod_and_test(struct page *page, int v, int ret); |
||||
extern void __page_ref_mod_and_return(struct page *page, int v, int ret); |
||||
extern void __page_ref_mod_unless(struct page *page, int v, int u); |
||||
extern void __page_ref_freeze(struct page *page, int v, int ret); |
||||
extern void __page_ref_unfreeze(struct page *page, int v); |
||||
|
||||
#else |
||||
|
||||
#define page_ref_tracepoint_active(t) false |
||||
|
||||
static inline void __page_ref_set(struct page *page, int v) |
||||
{ |
||||
} |
||||
static inline void __page_ref_mod(struct page *page, int v) |
||||
{ |
||||
} |
||||
static inline void __page_ref_mod_and_test(struct page *page, int v, int ret) |
||||
{ |
||||
} |
||||
static inline void __page_ref_mod_and_return(struct page *page, int v, int ret) |
||||
{ |
||||
} |
||||
static inline void __page_ref_mod_unless(struct page *page, int v, int u) |
||||
{ |
||||
} |
||||
static inline void __page_ref_freeze(struct page *page, int v, int ret) |
||||
{ |
||||
} |
||||
static inline void __page_ref_unfreeze(struct page *page, int v) |
||||
{ |
||||
} |
||||
|
||||
#endif |
||||
|
||||
static inline int page_ref_count(struct page *page) |
||||
{ |
||||
return atomic_read(&page->_count); |
||||
} |
||||
|
||||
static inline int page_count(struct page *page) |
||||
{ |
||||
return atomic_read(&compound_head(page)->_count); |
||||
} |
||||
|
||||
static inline void set_page_count(struct page *page, int v) |
||||
{ |
||||
atomic_set(&page->_count, v); |
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_set)) |
||||
__page_ref_set(page, v); |
||||
} |
||||
|
||||
/*
|
||||
* Setup the page count before being freed into the page allocator for |
||||
* the first time (boot or memory hotplug) |
||||
*/ |
||||
static inline void init_page_count(struct page *page) |
||||
{ |
||||
set_page_count(page, 1); |
||||
} |
||||
|
||||
static inline void page_ref_add(struct page *page, int nr) |
||||
{ |
||||
atomic_add(nr, &page->_count); |
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) |
||||
__page_ref_mod(page, nr); |
||||
} |
||||
|
||||
static inline void page_ref_sub(struct page *page, int nr) |
||||
{ |
||||
atomic_sub(nr, &page->_count); |
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) |
||||
__page_ref_mod(page, -nr); |
||||
} |
||||
|
||||
static inline void page_ref_inc(struct page *page) |
||||
{ |
||||
atomic_inc(&page->_count); |
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) |
||||
__page_ref_mod(page, 1); |
||||
} |
||||
|
||||
static inline void page_ref_dec(struct page *page) |
||||
{ |
||||
atomic_dec(&page->_count); |
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod)) |
||||
__page_ref_mod(page, -1); |
||||
} |
||||
|
||||
static inline int page_ref_sub_and_test(struct page *page, int nr) |
||||
{ |
||||
int ret = atomic_sub_and_test(nr, &page->_count); |
||||
|
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_test)) |
||||
__page_ref_mod_and_test(page, -nr, ret); |
||||
return ret; |
||||
} |
||||
|
||||
static inline int page_ref_dec_and_test(struct page *page) |
||||
{ |
||||
int ret = atomic_dec_and_test(&page->_count); |
||||
|
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_test)) |
||||
__page_ref_mod_and_test(page, -1, ret); |
||||
return ret; |
||||
} |
||||
|
||||
static inline int page_ref_dec_return(struct page *page) |
||||
{ |
||||
int ret = atomic_dec_return(&page->_count); |
||||
|
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_and_return)) |
||||
__page_ref_mod_and_return(page, -1, ret); |
||||
return ret; |
||||
} |
||||
|
||||
static inline int page_ref_add_unless(struct page *page, int nr, int u) |
||||
{ |
||||
int ret = atomic_add_unless(&page->_count, nr, u); |
||||
|
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_mod_unless)) |
||||
__page_ref_mod_unless(page, nr, ret); |
||||
return ret; |
||||
} |
||||
|
||||
static inline int page_ref_freeze(struct page *page, int count) |
||||
{ |
||||
int ret = likely(atomic_cmpxchg(&page->_count, count, 0) == count); |
||||
|
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_freeze)) |
||||
__page_ref_freeze(page, count, ret); |
||||
return ret; |
||||
} |
||||
|
||||
static inline void page_ref_unfreeze(struct page *page, int count) |
||||
{ |
||||
VM_BUG_ON_PAGE(page_count(page) != 0, page); |
||||
VM_BUG_ON(count == 0); |
||||
|
||||
atomic_set(&page->_count, count); |
||||
if (page_ref_tracepoint_active(__tracepoint_page_ref_unfreeze)) |
||||
__page_ref_unfreeze(page, count); |
||||
} |
||||
|
||||
#endif |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue