aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-03-23 13:22:12 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-06 03:30:28 -0400
commitbcbcb37cdb67d8100acfa66df40c4d636c28c4d1 (patch)
treefbd624736ad77f079e531495f557953d4d875229
parent803d4f3980f6e220b27311a283aab0a4d68b6709 (diff)
perf_counter tools: use mmap() output
update kerneltop to use the mmap() output to gather overflow information Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Wu Fengguang <fengguang.wu@intel.com> Cc: Paul Mackerras <paulus@samba.org> Orig-LKML-Reference: <20090323172417.677932499@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--Documentation/perf_counter/kerneltop.c93
1 files changed, 79 insertions, 14 deletions
diff --git a/Documentation/perf_counter/kerneltop.c b/Documentation/perf_counter/kerneltop.c
index a72c9bd28071..80b790553ec8 100644
--- a/Documentation/perf_counter/kerneltop.c
+++ b/Documentation/perf_counter/kerneltop.c
@@ -84,6 +84,7 @@
84#include <sys/prctl.h> 84#include <sys/prctl.h>
85#include <sys/wait.h> 85#include <sys/wait.h>
86#include <sys/uio.h> 86#include <sys/uio.h>
87#include <sys/mman.h>
87 88
88#include <linux/unistd.h> 89#include <linux/unistd.h>
89 90
@@ -119,17 +120,25 @@ typedef long long __s64;
119 120
120 121
121#ifdef __x86_64__ 122#ifdef __x86_64__
122# define __NR_perf_counter_open 295 123#define __NR_perf_counter_open 295
124#define rmb() asm volatile("lfence" ::: "memory")
125#define cpu_relax() asm volatile("rep; nop" ::: "memory");
123#endif 126#endif
124 127
125#ifdef __i386__ 128#ifdef __i386__
126# define __NR_perf_counter_open 333 129#define __NR_perf_counter_open 333
130#define rmb() asm volatile("lfence" ::: "memory")
131#define cpu_relax() asm volatile("rep; nop" ::: "memory");
127#endif 132#endif
128 133
129#ifdef __powerpc__ 134#ifdef __powerpc__
130#define __NR_perf_counter_open 319 135#define __NR_perf_counter_open 319
136#define rmb() asm volatile ("sync" ::: "memory")
137#define cpu_relax() asm volatile ("" ::: "memory");
131#endif 138#endif
132 139
140#define unlikely(x) __builtin_expect(!!(x), 0)
141
133asmlinkage int sys_perf_counter_open( 142asmlinkage int sys_perf_counter_open(
134 struct perf_counter_hw_event *hw_event_uptr __user, 143 struct perf_counter_hw_event *hw_event_uptr __user,
135 pid_t pid, 144 pid_t pid,
@@ -181,6 +190,7 @@ static int profile_cpu = -1;
181static int nr_cpus = 0; 190static int nr_cpus = 0;
182static int nmi = 1; 191static int nmi = 1;
183static int group = 0; 192static int group = 0;
193static unsigned int page_size;
184 194
185static char *vmlinux; 195static char *vmlinux;
186 196
@@ -1117,16 +1127,68 @@ static void process_options(int argc, char *argv[])
1117 } 1127 }
1118} 1128}
1119 1129
1130struct mmap_data {
1131 int counter;
1132 void *base;
1133 unsigned int mask;
1134 unsigned int prev;
1135};
1136
1137static unsigned int mmap_read_head(struct mmap_data *md)
1138{
1139 struct perf_counter_mmap_page *pc = md->base;
1140 unsigned int seq, head;
1141
1142repeat:
1143 rmb();
1144 seq = pc->lock;
1145
1146 if (unlikely(seq & 1)) {
1147 cpu_relax();
1148 goto repeat;
1149 }
1150
1151 head = pc->data_head;
1152
1153 rmb();
1154 if (pc->lock != seq)
1155 goto repeat;
1156
1157 return head;
1158}
1159
1160static void mmap_read(struct mmap_data *md)
1161{
1162 unsigned int head = mmap_read_head(md);
1163 unsigned int old = md->prev;
1164 unsigned char *data = md->base + page_size;
1165
1166 if (head - old > md->mask) {
1167 printf("ERROR: failed to keep up with mmap data\n");
1168 exit(-1);
1169 }
1170
1171 for (; old != head;) {
1172 __u64 *ptr = (__u64 *)&data[old & md->mask];
1173 old += sizeof(__u64);
1174
1175 process_event(*ptr, md->counter);
1176 }
1177
1178 md->prev = old;
1179}
1180
1120int main(int argc, char *argv[]) 1181int main(int argc, char *argv[])
1121{ 1182{
1122 struct pollfd event_array[MAX_NR_CPUS][MAX_COUNTERS]; 1183 struct pollfd event_array[MAX_NR_CPUS][MAX_COUNTERS];
1184 struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS];
1123 struct perf_counter_hw_event hw_event; 1185 struct perf_counter_hw_event hw_event;
1124 int i, counter, group_fd; 1186 int i, counter, group_fd;
1125 unsigned int cpu; 1187 unsigned int cpu;
1126 uint64_t ip;
1127 ssize_t res;
1128 int ret; 1188 int ret;
1129 1189
1190 page_size = sysconf(_SC_PAGE_SIZE);
1191
1130 process_options(argc, argv); 1192 process_options(argc, argv);
1131 1193
1132 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 1194 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
@@ -1153,8 +1215,6 @@ int main(int argc, char *argv[])
1153 hw_event.record_type = PERF_RECORD_IRQ; 1215 hw_event.record_type = PERF_RECORD_IRQ;
1154 hw_event.nmi = nmi; 1216 hw_event.nmi = nmi;
1155 1217
1156 printf("FOO: %d %llx %llx\n", counter, event_id[counter], event_count[counter]);
1157
1158 fd[i][counter] = sys_perf_counter_open(&hw_event, tid, cpu, group_fd, 0); 1218 fd[i][counter] = sys_perf_counter_open(&hw_event, tid, cpu, group_fd, 0);
1159 fcntl(fd[i][counter], F_SETFL, O_NONBLOCK); 1219 fcntl(fd[i][counter], F_SETFL, O_NONBLOCK);
1160 if (fd[i][counter] < 0) { 1220 if (fd[i][counter] < 0) {
@@ -1174,6 +1234,17 @@ int main(int argc, char *argv[])
1174 1234
1175 event_array[i][counter].fd = fd[i][counter]; 1235 event_array[i][counter].fd = fd[i][counter];
1176 event_array[i][counter].events = POLLIN; 1236 event_array[i][counter].events = POLLIN;
1237
1238 mmap_array[i][counter].counter = counter;
1239 mmap_array[i][counter].prev = 0;
1240 mmap_array[i][counter].mask = 2*page_size - 1;
1241 mmap_array[i][counter].base = mmap(NULL, 3*page_size,
1242 PROT_READ, MAP_SHARED, fd[i][counter], 0);
1243 if (mmap_array[i][counter].base == MAP_FAILED) {
1244 printf("kerneltop error: failed to mmap with %d (%s)\n",
1245 errno, strerror(errno));
1246 exit(-1);
1247 }
1177 } 1248 }
1178 } 1249 }
1179 1250
@@ -1188,14 +1259,8 @@ int main(int argc, char *argv[])
1188 int hits = events; 1259 int hits = events;
1189 1260
1190 for (i = 0; i < nr_cpus; i++) { 1261 for (i = 0; i < nr_cpus; i++) {
1191 for (counter = 0; counter < nr_counters; counter++) { 1262 for (counter = 0; counter < nr_counters; counter++)
1192 res = read(fd[i][counter], (char *) &ip, sizeof(ip)); 1263 mmap_read(&mmap_array[i][counter]);
1193 if (res > 0) {
1194 assert(res == sizeof(ip));
1195
1196 process_event(ip, counter);
1197 }
1198 }
1199 } 1264 }
1200 1265
1201 if (time(NULL) >= last_refresh + delay_secs) { 1266 if (time(NULL) >= last_refresh + delay_secs) {