at v5.0-rc2 4.5 kB view raw
1/* 2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 3 * 4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; 8 * version 2.1 of the License (not later!) 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this program; if not, see <http://www.gnu.org/licenses> 17 * 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 */ 20#include <stdio.h> 21#include <stdlib.h> 22#include <string.h> 23 24#include "event-parse.h" 25#include "trace-seq.h" 26 27static void write_state(struct trace_seq *s, int val) 28{ 29 const char states[] = "SDTtZXxW"; 30 int found = 0; 31 int i; 32 33 for (i = 0; i < (sizeof(states) - 1); i++) { 34 if (!(val & (1 << i))) 35 continue; 36 37 if (found) 38 trace_seq_putc(s, '|'); 39 40 found = 1; 41 trace_seq_putc(s, states[i]); 42 } 43 44 if (!found) 45 trace_seq_putc(s, 'R'); 46} 47 48static void write_and_save_comm(struct tep_format_field *field, 49 struct tep_record *record, 50 struct trace_seq *s, int pid) 51{ 52 const char *comm; 53 int len; 54 55 comm = (char *)(record->data + field->offset); 56 len = s->len; 57 trace_seq_printf(s, "%.*s", 58 field->size, comm); 59 60 /* make sure the comm has a \0 at the end. */ 61 trace_seq_terminate(s); 62 comm = &s->buffer[len]; 63 64 /* Help out the comm to ids. This will handle dups */ 65 tep_register_comm(field->event->pevent, comm, pid); 66} 67 68static int sched_wakeup_handler(struct trace_seq *s, 69 struct tep_record *record, 70 struct tep_event *event, void *context) 71{ 72 struct tep_format_field *field; 73 unsigned long long val; 74 75 if (tep_get_field_val(s, event, "pid", record, &val, 1)) 76 return trace_seq_putc(s, '!'); 77 78 field = tep_find_any_field(event, "comm"); 79 if (field) { 80 write_and_save_comm(field, record, s, val); 81 trace_seq_putc(s, ':'); 82 } 83 trace_seq_printf(s, "%lld", val); 84 85 if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0) 86 trace_seq_printf(s, " [%lld]", val); 87 88 if (tep_get_field_val(s, event, "success", record, &val, 1) == 0) 89 trace_seq_printf(s, " success=%lld", val); 90 91 if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) 92 trace_seq_printf(s, " CPU:%03llu", val); 93 94 return 0; 95} 96 97static int sched_switch_handler(struct trace_seq *s, 98 struct tep_record *record, 99 struct tep_event *event, void *context) 100{ 101 struct tep_format_field *field; 102 unsigned long long val; 103 104 if (tep_get_field_val(s, event, "prev_pid", record, &val, 1)) 105 return trace_seq_putc(s, '!'); 106 107 field = tep_find_any_field(event, "prev_comm"); 108 if (field) { 109 write_and_save_comm(field, record, s, val); 110 trace_seq_putc(s, ':'); 111 } 112 trace_seq_printf(s, "%lld ", val); 113 114 if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) 115 trace_seq_printf(s, "[%d] ", (int) val); 116 117 if (tep_get_field_val(s, event, "prev_state", record, &val, 0) == 0) 118 write_state(s, val); 119 120 trace_seq_puts(s, " ==> "); 121 122 if (tep_get_field_val(s, event, "next_pid", record, &val, 1)) 123 return trace_seq_putc(s, '!'); 124 125 field = tep_find_any_field(event, "next_comm"); 126 if (field) { 127 write_and_save_comm(field, record, s, val); 128 trace_seq_putc(s, ':'); 129 } 130 trace_seq_printf(s, "%lld", val); 131 132 if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0) 133 trace_seq_printf(s, " [%d]", (int) val); 134 135 return 0; 136} 137 138int TEP_PLUGIN_LOADER(struct tep_handle *pevent) 139{ 140 tep_register_event_handler(pevent, -1, "sched", "sched_switch", 141 sched_switch_handler, NULL); 142 143 tep_register_event_handler(pevent, -1, "sched", "sched_wakeup", 144 sched_wakeup_handler, NULL); 145 146 tep_register_event_handler(pevent, -1, "sched", "sched_wakeup_new", 147 sched_wakeup_handler, NULL); 148 return 0; 149} 150 151void TEP_PLUGIN_UNLOADER(struct tep_handle *pevent) 152{ 153 tep_unregister_event_handler(pevent, -1, "sched", "sched_switch", 154 sched_switch_handler, NULL); 155 156 tep_unregister_event_handler(pevent, -1, "sched", "sched_wakeup", 157 sched_wakeup_handler, NULL); 158 159 tep_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new", 160 sched_wakeup_handler, NULL); 161}