gator: ARM DS-5.6 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_events_meminfo.c
1 /**
2  * Copyright (C) ARM Limited 2010-2011. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
10 #include "gator.h"
11 #include <linux/workqueue.h>
12 #include <trace/events/kmem.h>
14 #define MEMINFO_MEMFREE         0
15 #define MEMINFO_MEMUSED         1
16 #define MEMINFO_BUFFERRAM       2
17 #define MEMINFO_TOTAL           3
19 static ulong meminfo_global_enabled;
20 static ulong meminfo_enabled[MEMINFO_TOTAL];
21 static ulong meminfo_key[MEMINFO_TOTAL];
22 static int meminfo_buffer[MEMINFO_TOTAL * 2];
23 static int meminfo_length = 0;
24 static unsigned int mem_event = 0;
25 static bool new_data_avail;
27 static void wq_sched_handler(struct work_struct *wsptr);
29 DECLARE_WORK(work, wq_sched_handler);
31 GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) {
32         mem_event++;
33 }
35 GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) {
36         mem_event++;
37 }
39 GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) {
40         mem_event++;
41 }
43 static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root)
44 {
45         struct dentry *dir;
46         int i;
48         for (i = 0; i < MEMINFO_TOTAL; i++) {
49                 switch (i) {
50                 case MEMINFO_MEMFREE:
51                         dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memfree");
52                         break;
53                 case MEMINFO_MEMUSED:
54                         dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memused");
55                         break;
56                 case MEMINFO_BUFFERRAM:
57                         dir = gatorfs_mkdir(sb, root, "Linux_meminfo_bufferram");
58                         break;
59                 default:
60                         return -1;
61                 }
62                 if (!dir) {
63                         return -1;
64                 }
65                 gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
66                 gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_key[i]);
67         }
69         return 0;
70 }
72 static int gator_events_meminfo_start(void)
73 {
74         int i;
76         new_data_avail = true;
77         for (i = 0; i < MEMINFO_TOTAL; i++) {
78                 if (meminfo_enabled[i]) {
79                         meminfo_global_enabled = 1;
80                 }
81         }
83         if (meminfo_global_enabled == 0)
84                 return 0;
86         if (GATOR_REGISTER_TRACE(mm_page_free_direct))
87                 goto mm_page_free_direct_exit;
88         if (GATOR_REGISTER_TRACE(mm_pagevec_free))
89                 goto mm_pagevec_free_exit;
90         if (GATOR_REGISTER_TRACE(mm_page_alloc))
91                 goto mm_page_alloc_exit;
93         return 0;
95 mm_page_alloc_exit:
96         GATOR_UNREGISTER_TRACE(mm_pagevec_free);
97 mm_pagevec_free_exit:
98         GATOR_UNREGISTER_TRACE(mm_page_free_direct);
99 mm_page_free_direct_exit:
100         return -1;
103 static void gator_events_meminfo_stop(void)
105         int i;
107         if (meminfo_global_enabled) {
108                 GATOR_UNREGISTER_TRACE(mm_page_free_direct);
109                 GATOR_UNREGISTER_TRACE(mm_pagevec_free);
110                 GATOR_UNREGISTER_TRACE(mm_page_alloc);
111         }
113         meminfo_global_enabled = 0;
114         for (i = 0; i < MEMINFO_TOTAL; i++) {
115                 meminfo_enabled[i] = 0;
116         }
119 // Must be run in a work queue as the kernel function si_meminfo() can sleep
120 static void wq_sched_handler(struct work_struct *wsptr)
122         struct sysinfo info;
123         int i, len, value;
125         meminfo_length = len = 0;
127         si_meminfo(&info);
128         for (i = 0; i < MEMINFO_TOTAL; i++) {
129                 if (meminfo_enabled[i]) {
130                         switch (i) {
131                         case MEMINFO_MEMFREE:
132                                 value = info.freeram * PAGE_SIZE;
133                                 break;
134                         case MEMINFO_MEMUSED:
135                                 value = (info.totalram - info.freeram) * PAGE_SIZE;
136                                 break;
137                         case MEMINFO_BUFFERRAM:
138                                 value = info.bufferram * PAGE_SIZE;
139                                 break;
140                         default:
141                                 value = 0;
142                                 break;
143                         }
144                         meminfo_buffer[len++] = meminfo_key[i];
145                         meminfo_buffer[len++] = value;
146                 }
147         }
149         meminfo_length = len;
150         new_data_avail = true;
153 static int gator_events_meminfo_read(int **buffer)
155         static unsigned int last_mem_event = 0;
157         if (smp_processor_id() || !meminfo_global_enabled)
158                 return 0;
160         if (last_mem_event != mem_event) {
161                 last_mem_event = mem_event;
162                 schedule_work(&work);
163         }
165         if (!new_data_avail)
166                 return 0;
168         new_data_avail = false;
170         if (buffer)
171                 *buffer = meminfo_buffer;
173         return meminfo_length;
176 static struct gator_interface gator_events_meminfo_interface = {
177         .create_files = gator_events_meminfo_create_files,
178         .start = gator_events_meminfo_start,
179         .stop = gator_events_meminfo_stop,
180         .read = gator_events_meminfo_read,
181 };
183 int gator_events_meminfo_init(void)
185         int i;
187         meminfo_global_enabled = 0;
188         for (i = 0; i < MEMINFO_TOTAL; i++) {
189                 meminfo_enabled[i] = 0;
190                 meminfo_key[i] = gator_events_get_key();
191         }
193         return gator_events_install(&gator_events_meminfo_interface);
195 gator_events_init(gator_events_meminfo_init);