From b899706ea96eca97dbc47cd3ae56b124fc349569 Mon Sep 17 00:00:00 2001 From: Joel Fernandes Date: Sat, 5 May 2018 14:58:08 -0700 Subject: [PATCH] mm: emit tracepoint when rss watermark is hit Useful to track how rss is changing per tgid. Required for the memory visibility work being done for Android. Original patch by Tim Murray: https://partner-android-review.googlesource.com/c/kernel/private/msm-google/+/1081280 Changes from original patch: - don't bloat mm_struct - add some noise reduction to rss tracking Mot-CRs-fixed: (CR) Change-Id: Ief904334235ff4380244e5803d7853579e70d202 Signed-off-by: Joel Fernandes Reviewed-on: https://gerrit.mot.com/1453726 SME-Granted: SME Approvals Granted Tested-by: Jira Key SLTApproved: Slta Waiver Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- include/linux/mm.h | 14 +++++++++++--- include/trace/events/kmem.h | 21 +++++++++++++++++++++ mm/memory.c | 17 +++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index b14ca733a2b9..131536db63db 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1504,19 +1504,27 @@ static inline unsigned long get_mm_counter(struct mm_struct *mm, int member) return (unsigned long)val; } +void mm_trace_rss_stat(int member, long count, long value); + static inline void add_mm_counter(struct mm_struct *mm, int member, long value) { - atomic_long_add(value, &mm->rss_stat.count[member]); + long count = atomic_long_add_return(value, &mm->rss_stat.count[member]); + + mm_trace_rss_stat(member, count, value); } static inline void inc_mm_counter(struct mm_struct *mm, int member) { - atomic_long_inc(&mm->rss_stat.count[member]); + long count = atomic_long_inc_return(&mm->rss_stat.count[member]); + + mm_trace_rss_stat(member, count, 1); } static inline void dec_mm_counter(struct mm_struct *mm, int member) { - atomic_long_dec(&mm->rss_stat.count[member]); + long count = atomic_long_dec_return(&mm->rss_stat.count[member]); + + mm_trace_rss_stat(member, count, -1); } /* Optimized variant when page is already known not to be PageAnon */ diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index 285feeadac39..b5529c0d4e01 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h @@ -318,6 +318,27 @@ TRACE_EVENT(mm_page_alloc_extfrag, __entry->change_ownership) ); +TRACE_EVENT(rss_stat, + + TP_PROTO(int member, + long count), + + TP_ARGS(member, count), + + TP_STRUCT__entry( + __field(int, member) + __field(long, size) + ), + + TP_fast_assign( + __entry->member = member; + __entry->size = (count << PAGE_SHIFT); + ), + + TP_printk("member=%d size=%ldB", + __entry->member, + __entry->size) + ); #endif /* _TRACE_KMEM_H */ /* This part must be outside protection */ diff --git a/mm/memory.c b/mm/memory.c index 16956844e553..a92eba1f2821 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -71,6 +71,8 @@ #include #include +#include + #include #include #include @@ -139,6 +141,21 @@ static int __init init_zero_pfn(void) } core_initcall(init_zero_pfn); +/* + * This threshold is the boundary in the value space, that the counter has to + * advance before we trace it. Should be a power of 2. It is to reduce unwanted + * trace overhead. The counter is number of pages. + */ +#define TRACE_MM_COUNTER_THRESHOLD 128 + +void mm_trace_rss_stat(int member, long count, long value) +{ + long thresh_mask = ~(TRACE_MM_COUNTER_THRESHOLD - 1); + + /* Threshold roll-over, trace it */ + if ((count & thresh_mask) != ((count - value) & thresh_mask)) + trace_rss_stat(member, count); +} #if defined(SPLIT_RSS_COUNTING) -- 2.20.1