📄 preem_latency.c
字号:
#define HEAD2 (2 - HEAD_LINES)static int g_read_completed = 0;static int g_cpu = 0;static char g_buff[84];static int g_buffidx = 0;static int g_buf_end = 0;static int __noinstrument latencytimes_read_proc(char *page_buffer, char **my_first_byte, off_t virtual_start, int length, int *eof, void *data){ int my_buffer_offset = 0; char * const my_base = page_buffer; int i,j,max; struct LatencyData *l; *my_first_byte = page_buffer; if (virtual_start == 0){ /* Just been opened */ logFlag = 0; /* stop logging */ g_read_completed = HEAD1; g_cpu = 0; g_buffidx = 0; g_buf_end = 0; } else if ((i = g_buf_end - g_buffidx) > 0){ if (i > length) i = length; memcpy(my_base, &g_buff[g_buffidx], i); g_buffidx += i; return i; } else if (g_read_completed == NUM_LOG_ENTRY) { if (++g_cpu >= smp_num_cpus) { *eof = 1; reset_latencyData(); logFlag = 1; /* start logging */ return 0; } g_read_completed = HEAD1; } g_buffidx = 0; l = &latencyData[g_cpu]; switch (g_read_completed) { case HEAD1: g_buf_end = sprintf(&g_buff[0], "cpu %d worst %d latency times of %d measured in this period.\n", g_cpu,NUM_LOG_ENTRY,l->numIntrs); break; case HEAD2: g_buf_end = sprintf(&g_buff[0], " usec cause mask start line/file address end line/file\n"); break; default: for (j = max = i = 0;j < NUM_LOG_ENTRY; j++){ if( l->entry[j].latency > max ){ max = l->entry[j].latency; i = j; } } g_buf_end = sprintf(&g_buff[0], "%6d %10s %8x %5d/%-15s %8x %5d/%s\n", (int)clock_to_usecs(l->entry[i].latency), (l->entry[i].cause == -99) ? "unknown" : (l->entry[i].cause < 0) ? irq_desc[~l->entry[i].cause].action->name : (l->entry[i].cause > CAUSE_MAX) ? "Unknown" : cause_name[l->entry[i].cause], l->entry[i].mask, l->entry[i].start.FileLine, l->entry[i].start.FileName == (char *)0 ? "entry.S" : l->entry[i].start.FileName, l->entry[i].start.Address, /*l->entry[i].start.ProcId, l->entry[i].start.ProcName,*/ l->entry[i].end.FileLine, l->entry[i].end.FileName == (char *)0 ? "entry.S" : l->entry[i].end.FileName /*, l->entry[i].end.ProcId, l->entry[i].end.ProcName*/); /* Clearing these two effectivly clears the entry */ l->entry[i].latency = 0; l->entry[i].end.Address = 0; } g_read_completed++; if ((i = g_buf_end) > length) i = length; memcpy(my_base, &g_buff[0], i); g_buffidx += i; return i;}int __noinstrument __init latencytimes_init(void){ readclock_init();#ifdef CONFIG_PROC_FS create_proc_read_entry("latencytimes", 0, 0, latencytimes_read_proc, 0);#endif reset_latencyData(); return 0;}__initcall(latencytimes_init);static int detail_cpu = -1;static int detail_lineno = -1;static char *detail_file = NULL;#define DETAILFILEBUFSIZ 64static char detail_filebuf[DETAILFILEBUFSIZ + 1];#define DETAILMAXENTRIES 256static int detail_do = 0;struct detail_entry { int code; const char *fname; int lineno; unsigned rtnaddr; int pid; int count; int intr; unsigned clock;};struct detail_info { unsigned latency; int entries; struct detail_entry entry[DETAILMAXENTRIES];};static struct detail_info detail_info = { 0 };static struct detail_info detail_report = { 0 };static int detail_freeze_collect = 1;static int detail_freeze_report = 1;static void __noinstrument detail_reset(void){ detail_info.entries = 0; detail_info.latency = 0; detail_report.entries = 0; detail_report.latency = 0; detail_freeze_collect = 0; detail_freeze_report = 0;}static int __noinstrument detail_match(int lineno, char *file, int cpu){ return ((detail_lineno == -1) || (lineno == detail_lineno)) && ((detail_cpu == -1) || (cpu == detail_cpu)) && ((detail_file == NULL) || (strcmp(file, detail_file) == 0));}asmlinkage void __noinstrument latency_detail(int code, void *rtnaddr, const char *fname, unsigned lineno){ struct detail_entry *e; unsigned long flags; if (detail_freeze_collect == 1) return; save_flags(flags); cli(); if (! detail_do && (((code == 1) && ((preempt_get_count() & ~PREEMPT_ACTIVE) == 1)) || (code == 3)) && detail_match(lineno, (char *) fname, smp_processor_id())) { detail_do = 1; readclock(detail_info.latency); } if (detail_do && detail_match(detail_lineno, detail_file, smp_processor_id())) { detail_freeze_collect = 1; barrier(); if (detail_info.entries == DETAILMAXENTRIES) e = &detail_info.entry[DETAILMAXENTRIES - 1]; else { e = &detail_info.entry[detail_info.entries]; detail_info.entries++; } barrier(); e->code = code; e->fname = fname; e->lineno = lineno; e->rtnaddr = (int) rtnaddr; e->pid = current->pid; e->count = preempt_get_count(); e->intr = in_interrupt(); readclock(e->clock); if (((code == 0) && ((e->count & ~PREEMPT_ACTIVE) == 1)) || (code == 2) || ((code == 3) && (detail_info.entries != 0))) { detail_info.latency = CLKDIFF(detail_info.latency, e->clock); if ((detail_freeze_report == 0) && (detail_info.latency > detail_report.latency)) detail_report = detail_info; detail_do = 0; detail_info.entries = 0; barrier(); } detail_freeze_collect = 0; barrier(); } restore_flags(flags); return;}static ssize_t __noinstrument detail_read(struct file *file, char *buf, size_t buflen, loff_t *offset){ int bytes = 0; static int idet = 0; char *activity[] = { "stop ", "start ", "fstop ", "fstart" }; if (*offset == 0){ detail_freeze_collect = 1; detail_freeze_report = 1; barrier(); idet = 0; bytes = sprintf(buf, "%d entries latency %d usecs:\n", detail_report.entries, (int) clock_to_usecs(detail_report.latency)); } else if (idet >= detail_report.entries) { detail_reset(); return 0; } else { bytes = sprintf(buf, "%s %5d/%-25s %8x %6d %5x %d %d\n", activity[detail_report.entry[idet].code], detail_report.entry[idet].lineno, detail_report.entry[idet].fname ? detail_report.entry[idet].fname : "entry.S", detail_report.entry[idet].rtnaddr, detail_report.entry[idet].pid, detail_report.entry[idet].count, detail_report.entry[idet].intr, idet == 0 ? 0 : (int)clock_to_usecs(CLKDIFF(detail_report.entry[idet-1].clock, detail_report.entry[idet].clock))); idet++; } *offset += bytes; return bytes;}#define WRBUFSIZ 1024static char wrbuf[WRBUFSIZ];static ssize_t __noinstrument detail_write(struct file *file, const char *buf, size_t buflen, loff_t *offset){ int wrbuflen = buflen > WRBUFSIZ - 1 ? WRBUFSIZ - 1 : buflen; char *cp = NULL; memcpy(wrbuf, buf, wrbuflen); wrbuf[wrbuflen] = '\0'; cp = strtok(wrbuf, " \t\n"); while (cp != NULL) { if (strcmp(cp, "line") == 0) { cp = strtok(NULL, " \t\n"); if (cp) { detail_lineno = (int) simple_strtoul(cp, NULL, 10); printk(KERN_INFO "PREEMPT_TIMES_DETAIL line=%d\n", detail_lineno); } } else if (strcmp(cp, "cpu") == 0) { cp = strtok(NULL, " \t\n"); if (cp) { detail_cpu = (int) simple_strtoul(cp, NULL, 10); printk(KERN_INFO "PREEMPT_TIMES_DETAIL cpu=%d\n", detail_cpu); } } else if (strcmp(cp, "file") == 0) { cp = strtok(NULL, " \t\n"); if (cp) { int len = strlen(cp); if (len > DETAILFILEBUFSIZ) len = DETAILFILEBUFSIZ; if (strcmp(cp, "*") == 0) detail_file = NULL; else { memcpy(detail_filebuf, cp, len); detail_filebuf[len] = '\0'; detail_file = detail_filebuf; } printk(KERN_INFO "PREEMPT_TIMES_DETAIL file=%s\n", detail_file ? detail_file : "*"); } } else { printk(KERN_ERR "PREEMPT_TIMES_DETAIL invalid key %s\n", cp); } cp = strtok(NULL," \t\n"); } detail_reset(); return wrbuflen;} int __init __noinstrument latencydetail_init(void){#ifdef CONFIG_PROC_FS static struct file_operations detail_fileops = { read: detail_read, write: detail_write, }; struct proc_dir_entry *entry; entry = create_proc_entry("latencydetail", S_IRUGO|S_IWUSR, NULL); if (entry) entry->proc_fops = &detail_fileops;#endif return 0;}__initcall(latencydetail_init);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -