Commit | Line | Data |
---|---|---|
be075489 MK |
1 | #include <linux/mm.h> |
2 | #include <linux/mm_event.h> | |
3 | #include <linux/sched.h> | |
4 | #include <linux/vmalloc.h> | |
5 | #include <linux/seq_file.h> | |
6 | #include <linux/debugfs.h> | |
7 | ||
8 | #define CREATE_TRACE_POINTS | |
9 | #include <trace/events/mm_event.h> | |
d2a22b87 MK |
10 | /* msec */ |
11 | static unsigned long period_ms = 500; | |
be075489 MK |
12 | |
13 | void mm_event_task_init(struct task_struct *tsk) | |
14 | { | |
15 | memset(tsk->mm_event, 0, sizeof(tsk->mm_event)); | |
16 | tsk->next_period = 0; | |
17 | } | |
18 | ||
19 | static void record_stat(void) | |
20 | { | |
21 | if (time_is_before_eq_jiffies(current->next_period)) { | |
22 | int i; | |
23 | ||
24 | for (i = 0; i < MM_TYPE_NUM; i++) { | |
25 | if (current->mm_event[i].count == 0) | |
26 | continue; | |
27 | ||
28 | trace_mm_event_record(i, ¤t->mm_event[i]); | |
29 | memset(¤t->mm_event[i], 0, | |
30 | sizeof(struct mm_event_task)); | |
31 | } | |
d2a22b87 | 32 | current->next_period = jiffies + msecs_to_jiffies(period_ms); |
be075489 MK |
33 | } |
34 | } | |
35 | ||
36 | void mm_event_start(ktime_t *time) | |
37 | { | |
38 | *time = ktime_get(); | |
39 | } | |
40 | ||
41 | void mm_event_end(enum mm_event_type event, ktime_t start) | |
42 | { | |
43 | s64 elapsed = ktime_us_delta(ktime_get(), start); | |
44 | ||
45 | current->mm_event[event].count++; | |
46 | current->mm_event[event].accm_lat += elapsed; | |
47 | if (elapsed > current->mm_event[event].max_lat) | |
48 | current->mm_event[event].max_lat = elapsed; | |
49 | record_stat(); | |
50 | } | |
51 | ||
cee78bb6 MK |
52 | void mm_event_count(enum mm_event_type event, int count) |
53 | { | |
54 | current->mm_event[event].count += count; | |
55 | record_stat(); | |
56 | } | |
57 | ||
be075489 MK |
58 | static struct dentry *mm_event_root; |
59 | ||
d2a22b87 MK |
60 | static int period_ms_set(void *data, u64 val) |
61 | { | |
62 | if (val < 1 || val > ULONG_MAX) | |
63 | return -EINVAL; | |
64 | ||
65 | period_ms = (unsigned long)val; | |
66 | return 0; | |
67 | } | |
68 | ||
69 | static int period_ms_get(void *data, u64 *val) | |
70 | { | |
71 | *val = period_ms; | |
72 | return 0; | |
73 | } | |
74 | ||
75 | DEFINE_SIMPLE_ATTRIBUTE(period_ms_operations, period_ms_get, | |
76 | period_ms_set, "%llu\n"); | |
77 | ||
be075489 MK |
78 | static int __init mm_event_init(void) |
79 | { | |
d2a22b87 MK |
80 | struct dentry *entry; |
81 | ||
be075489 MK |
82 | mm_event_root = debugfs_create_dir("mm_event", NULL); |
83 | if (!mm_event_root) { | |
84 | pr_warn("debugfs dir <mm_event> creation failed\n"); | |
85 | return PTR_ERR(mm_event_root); | |
86 | } | |
87 | ||
d2a22b87 MK |
88 | entry = debugfs_create_file("period_ms", 0644, |
89 | mm_event_root, NULL, &period_ms_operations); | |
90 | ||
91 | if (IS_ERR(entry)) { | |
92 | pr_warn("debugfs file mm_event_task creation failed\n"); | |
93 | debugfs_remove_recursive(mm_event_root); | |
94 | return PTR_ERR(entry); | |
95 | } | |
96 | ||
be075489 MK |
97 | return 0; |
98 | } | |
99 | subsys_initcall(mm_event_init); |