plugin_sched_switch.c (3667B)
1// SPDX-License-Identifier: LGPL-2.1 2/* 3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com> 4 */ 5#include <stdio.h> 6#include <stdlib.h> 7#include <string.h> 8 9#include "event-parse.h" 10#include "trace-seq.h" 11 12static void write_state(struct trace_seq *s, int val) 13{ 14 const char states[] = "SDTtZXxW"; 15 int found = 0; 16 int i; 17 18 for (i = 0; i < (sizeof(states) - 1); i++) { 19 if (!(val & (1 << i))) 20 continue; 21 22 if (found) 23 trace_seq_putc(s, '|'); 24 25 found = 1; 26 trace_seq_putc(s, states[i]); 27 } 28 29 if (!found) 30 trace_seq_putc(s, 'R'); 31} 32 33static void write_and_save_comm(struct tep_format_field *field, 34 struct tep_record *record, 35 struct trace_seq *s, int pid) 36{ 37 const char *comm; 38 int len; 39 40 comm = (char *)(record->data + field->offset); 41 len = s->len; 42 trace_seq_printf(s, "%.*s", 43 field->size, comm); 44 45 /* make sure the comm has a \0 at the end. */ 46 trace_seq_terminate(s); 47 comm = &s->buffer[len]; 48 49 /* Help out the comm to ids. This will handle dups */ 50 tep_register_comm(field->event->tep, comm, pid); 51} 52 53static int sched_wakeup_handler(struct trace_seq *s, 54 struct tep_record *record, 55 struct tep_event *event, void *context) 56{ 57 struct tep_format_field *field; 58 unsigned long long val; 59 60 if (tep_get_field_val(s, event, "pid", record, &val, 1)) 61 return trace_seq_putc(s, '!'); 62 63 field = tep_find_any_field(event, "comm"); 64 if (field) { 65 write_and_save_comm(field, record, s, val); 66 trace_seq_putc(s, ':'); 67 } 68 trace_seq_printf(s, "%lld", val); 69 70 if (tep_get_field_val(s, event, "prio", record, &val, 0) == 0) 71 trace_seq_printf(s, " [%lld]", val); 72 73 if (tep_get_field_val(s, event, "success", record, &val, 1) == 0) 74 trace_seq_printf(s, " success=%lld", val); 75 76 if (tep_get_field_val(s, event, "target_cpu", record, &val, 0) == 0) 77 trace_seq_printf(s, " CPU:%03llu", val); 78 79 return 0; 80} 81 82static int sched_switch_handler(struct trace_seq *s, 83 struct tep_record *record, 84 struct tep_event *event, void *context) 85{ 86 struct tep_format_field *field; 87 unsigned long long val; 88 89 if (tep_get_field_val(s, event, "prev_pid", record, &val, 1)) 90 return trace_seq_putc(s, '!'); 91 92 field = tep_find_any_field(event, "prev_comm"); 93 if (field) { 94 write_and_save_comm(field, record, s, val); 95 trace_seq_putc(s, ':'); 96 } 97 trace_seq_printf(s, "%lld ", val); 98 99 if (tep_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) 100 trace_seq_printf(s, "[%d] ", (int) val); 101 102 if (tep_get_field_val(s, event, "prev_state", record, &val, 0) == 0) 103 write_state(s, val); 104 105 trace_seq_puts(s, " ==> "); 106 107 if (tep_get_field_val(s, event, "next_pid", record, &val, 1)) 108 return trace_seq_putc(s, '!'); 109 110 field = tep_find_any_field(event, "next_comm"); 111 if (field) { 112 write_and_save_comm(field, record, s, val); 113 trace_seq_putc(s, ':'); 114 } 115 trace_seq_printf(s, "%lld", val); 116 117 if (tep_get_field_val(s, event, "next_prio", record, &val, 0) == 0) 118 trace_seq_printf(s, " [%d]", (int) val); 119 120 return 0; 121} 122 123int TEP_PLUGIN_LOADER(struct tep_handle *tep) 124{ 125 tep_register_event_handler(tep, -1, "sched", "sched_switch", 126 sched_switch_handler, NULL); 127 128 tep_register_event_handler(tep, -1, "sched", "sched_wakeup", 129 sched_wakeup_handler, NULL); 130 131 tep_register_event_handler(tep, -1, "sched", "sched_wakeup_new", 132 sched_wakeup_handler, NULL); 133 return 0; 134} 135 136void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) 137{ 138 tep_unregister_event_handler(tep, -1, "sched", "sched_switch", 139 sched_switch_handler, NULL); 140 141 tep_unregister_event_handler(tep, -1, "sched", "sched_wakeup", 142 sched_wakeup_handler, NULL); 143 144 tep_unregister_event_handler(tep, -1, "sched", "sched_wakeup_new", 145 sched_wakeup_handler, NULL); 146}