Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / tools / lib / traceevent / plugin_sched_switch.c
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
26 static 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
47 static 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
67 static 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
96 static 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
137 int 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
150 void 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 }