linux/tools/lib/traceevent/plugin_sched_switch.c
<<
>>
Prefs
   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
  26static void write_state(struct trace_seq *s, int val)
  27{
  28        const char states[] = "SDTtZXxW";
  29        int found = 0;
  30        int i;
  31
  32        for (i = 0; i < (sizeof(states) - 1); i++) {
  33                if (!(val & (1 << i)))
  34                        continue;
  35
  36                if (found)
  37                        trace_seq_putc(s, '|');
  38
  39                found = 1;
  40                trace_seq_putc(s, states[i]);
  41        }
  42
  43        if (!found)
  44                trace_seq_putc(s, 'R');
  45}
  46
  47static void write_and_save_comm(struct format_field *field,
  48                                struct pevent_record *record,
  49                                struct trace_seq *s, int pid)
  50{
  51        const char *comm;
  52        int len;
  53
  54        comm = (char *)(record->data + field->offset);
  55        len = s->len;
  56        trace_seq_printf(s, "%.*s",
  57                         field->size, comm);
  58
  59        /* make sure the comm has a \0 at the end. */
  60        trace_seq_terminate(s);
  61        comm = &s->buffer[len];
  62
  63        /* Help out the comm to ids. This will handle dups */
  64        pevent_register_comm(field->event->pevent, comm, pid);
  65}
  66
  67static int sched_wakeup_handler(struct trace_seq *s,
  68                                struct pevent_record *record,
  69                                struct event_format *event, void *context)
  70{
  71        struct format_field *field;
  72        unsigned long long val;
  73
  74        if (pevent_get_field_val(s, event, "pid", record, &val, 1))
  75                return trace_seq_putc(s, '!');
  76
  77        field = pevent_find_any_field(event, "comm");
  78        if (field) {
  79                write_and_save_comm(field, record, s, val);
  80                trace_seq_putc(s, ':');
  81        }
  82        trace_seq_printf(s, "%lld", val);
  83
  84        if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0)
  85                trace_seq_printf(s, " [%lld]", val);
  86
  87        if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0)
  88                trace_seq_printf(s, " success=%lld", val);
  89
  90        if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0)
  91                trace_seq_printf(s, " CPU:%03llu", val);
  92
  93        return 0;
  94}
  95
  96static int sched_switch_handler(struct trace_seq *s,
  97                                struct pevent_record *record,
  98                                struct event_format *event, void *context)
  99{
 100        struct format_field *field;
 101        unsigned long long val;
 102
 103        if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1))
 104                return trace_seq_putc(s, '!');
 105
 106        field = pevent_find_any_field(event, "prev_comm");
 107        if (field) {
 108                write_and_save_comm(field, record, s, val);
 109                trace_seq_putc(s, ':');
 110        }
 111        trace_seq_printf(s, "%lld ", val);
 112
 113        if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
 114                trace_seq_printf(s, "[%lld] ", val);
 115
 116        if (pevent_get_field_val(s,  event, "prev_state", record, &val, 0) == 0)
 117                write_state(s, val);
 118
 119        trace_seq_puts(s, " ==> ");
 120
 121        if (pevent_get_field_val(s, event, "next_pid", record, &val, 1))
 122                return trace_seq_putc(s, '!');
 123
 124        field = pevent_find_any_field(event, "next_comm");
 125        if (field) {
 126                write_and_save_comm(field, record, s, val);
 127                trace_seq_putc(s, ':');
 128        }
 129        trace_seq_printf(s, "%lld", val);
 130
 131        if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
 132                trace_seq_printf(s, " [%lld]", val);
 133
 134        return 0;
 135}
 136
 137int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
 138{
 139        pevent_register_event_handler(pevent, -1, "sched", "sched_switch",
 140                                      sched_switch_handler, NULL);
 141
 142        pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup",
 143                                      sched_wakeup_handler, NULL);
 144
 145        pevent_register_event_handler(pevent, -1, "sched", "sched_wakeup_new",
 146                                      sched_wakeup_handler, NULL);
 147        return 0;
 148}
 149
 150void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
 151{
 152        pevent_unregister_event_handler(pevent, -1, "sched", "sched_switch",
 153                                        sched_switch_handler, NULL);
 154
 155        pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup",
 156                                        sched_wakeup_handler, NULL);
 157
 158        pevent_unregister_event_handler(pevent, -1, "sched", "sched_wakeup_new",
 159                                        sched_wakeup_handler, NULL);
 160}
 161