gator: ARM DS-5.3 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_events_meminfo.c
1 /**
2  * Copyright (C) ARM Limited 2010. 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 <linux/workqueue.h>
11 #include <linux/version.h>
12 #include <linux/slab.h>
13 #include <linux/mm.h>
14 #include <linux/fs.h>
15 #include <trace/events/kmem.h>
17 #include "gator.h"
18 #include "gator_trace.h"
20 #define MEMINFO_MEMFREE         0
21 #define MEMINFO_MEMUSED         1
22 #define MEMINFO_BUFFERRAM       2
23 #define MEMINFO_TOTAL           3
25 static ulong meminfo_global_enabled;
26 static ulong meminfo_enabled[MEMINFO_TOTAL];
27 static ulong meminfo_key[MEMINFO_TOTAL];
28 static int meminfo_buffer[MEMINFO_TOTAL * 2];
29 static int meminfo_length = 0;
30 static unsigned int mem_event = 0;
31 static bool new_data_avail;
33 static void wq_sched_handler(struct work_struct *wsptr);
35 DECLARE_WORK(work, wq_sched_handler);
37 GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) {
38         mem_event++;
39 }
41 GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) {
42         mem_event++;
43 }
45 GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) {
46         mem_event++;
47 }
49 static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root)
50 {
51         struct dentry *dir;
52         int i;
54         for (i = 0; i < MEMINFO_TOTAL; i++) {
55                 switch (i) {
56                 case MEMINFO_MEMFREE:
57                         dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memfree");
58                         break;
59                 case MEMINFO_MEMUSED:
60                         dir = gatorfs_mkdir(sb, root, "Linux_meminfo_memused");
61                         break;
62                 case MEMINFO_BUFFERRAM:
63                         dir = gatorfs_mkdir(sb, root, "Linux_meminfo_bufferram");
64                         break;
65                 default:
66                         return -1;
67                 }
68                 if (!dir) {
69                         return -1;
70                 }
71                 gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]);
72                 gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_key[i]);
73         }
75         return 0;
76 }
78 static int gator_events_meminfo_init(int *key)
79 {
80         int i;
82         meminfo_global_enabled = 0;
83         for (i = 0; i < MEMINFO_TOTAL; i++) {
84                 meminfo_enabled[i] = 0;
85                 meminfo_key[i] = *key;
86                 *key = *key + 1;
87         }
89         return 0;
90 }
92 static int gator_events_meminfo_start(void)
93 {
94         int i;
96         new_data_avail = true;
97         for (i = 0; i < MEMINFO_TOTAL; i++) {
98                 if (meminfo_enabled[i]) {
99                         meminfo_global_enabled = 1;
100                 }
101         }
103         if (meminfo_global_enabled == 0)
104                 return 0;
106         if (GATOR_REGISTER_TRACE(mm_page_free_direct))
107                 goto mm_page_free_direct_exit;
108         if (GATOR_REGISTER_TRACE(mm_pagevec_free))
109                 goto mm_pagevec_free_exit;
110         if (GATOR_REGISTER_TRACE(mm_page_alloc))
111                 goto mm_page_alloc_exit;
113         return 0;
115 mm_page_alloc_exit:
116         GATOR_UNREGISTER_TRACE(mm_pagevec_free);
117 mm_pagevec_free_exit:
118         GATOR_UNREGISTER_TRACE(mm_page_free_direct);
119 mm_page_free_direct_exit:
120         return -1;
123 static void gator_events_meminfo_stop(void)
125         int i;
127         if (meminfo_global_enabled) {
128                 GATOR_UNREGISTER_TRACE(mm_page_free_direct);
129                 GATOR_UNREGISTER_TRACE(mm_pagevec_free);
130                 GATOR_UNREGISTER_TRACE(mm_page_alloc);
131         }
133         meminfo_global_enabled = 0;
134         for (i = 0; i < MEMINFO_TOTAL; i++) {
135                 meminfo_enabled[i] = 0;
136         }
139 // Must be run in a work queue as the kernel function si_meminfo() can sleep
140 static void wq_sched_handler(struct work_struct *wsptr)
142         struct sysinfo info;
143         int i, len, value;
145         meminfo_length = len = 0;
147         si_meminfo(&info);
148         for (i = 0; i < MEMINFO_TOTAL; i++) {
149                 if (meminfo_enabled[i]) {
150                         switch (i) {
151                         case MEMINFO_MEMFREE:
152                                 value = info.freeram * PAGE_SIZE;
153                                 break;
154                         case MEMINFO_MEMUSED:
155                                 value = (info.totalram - info.freeram) * PAGE_SIZE;
156                                 break;
157                         case MEMINFO_BUFFERRAM:
158                                 value = info.bufferram * PAGE_SIZE;
159                                 break;
160                         default:
161                                 value = 0;
162                                 break;
163                         }
164                         meminfo_buffer[len++] = meminfo_key[i];
165                         meminfo_buffer[len++] = value;
166                 }
167         }
169         meminfo_length = len;
170         new_data_avail = true;
173 static int gator_events_meminfo_read(int **buffer)
175         static unsigned int last_mem_event = 0;
177         if (smp_processor_id() || !meminfo_global_enabled)
178                 return 0;
180         if (last_mem_event != mem_event) {
181                 last_mem_event = mem_event;
182                 schedule_work(&work);
183         }
185         if (!new_data_avail)
186                 return 0;
188         new_data_avail = false;
190         if (buffer)
191                 *buffer = meminfo_buffer;
193         return meminfo_length;
196 int gator_events_meminfo_install(gator_interface *gi) {
197         gi->create_files = gator_events_meminfo_create_files;
198         gi->init = gator_events_meminfo_init;
199         gi->start = gator_events_meminfo_start;
200         gi->stop = gator_events_meminfo_stop;
201         gi->read = gator_events_meminfo_read;
202         return 0;