linux/kernel/trace/trace_sched_switch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * trace context switch
   4 *
   5 * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
   6 *
   7 */
   8#include <linux/module.h>
   9#include <linux/kallsyms.h>
  10#include <linux/uaccess.h>
  11#include <linux/ftrace.h>
  12#include <trace/events/sched.h>
  13
  14#include "trace.h"
  15
  16#define RECORD_CMDLINE  1
  17#define RECORD_TGID     2
  18
  19static int              sched_cmdline_ref;
  20static int              sched_tgid_ref;
  21static DEFINE_MUTEX(sched_register_mutex);
  22
  23static void
  24probe_sched_switch(void *ignore, bool preempt,
  25                   struct task_struct *prev, struct task_struct *next)
  26{
  27        int flags;
  28
  29        flags = (RECORD_TGID * !!sched_tgid_ref) +
  30                (RECORD_CMDLINE * !!sched_cmdline_ref);
  31
  32        if (!flags)
  33                return;
  34        tracing_record_taskinfo_sched_switch(prev, next, flags);
  35}
  36
  37static void
  38probe_sched_wakeup(void *ignore, struct task_struct *wakee)
  39{
  40        int flags;
  41
  42        flags = (RECORD_TGID * !!sched_tgid_ref) +
  43                (RECORD_CMDLINE * !!sched_cmdline_ref);
  44
  45        if (!flags)
  46                return;
  47        tracing_record_taskinfo(current, flags);
  48}
  49
  50static int tracing_sched_register(void)
  51{
  52        int ret;
  53
  54        ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
  55        if (ret) {
  56                pr_info("wakeup trace: Couldn't activate tracepoint"
  57                        " probe to kernel_sched_wakeup\n");
  58                return ret;
  59        }
  60
  61        ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
  62        if (ret) {
  63                pr_info("wakeup trace: Couldn't activate tracepoint"
  64                        " probe to kernel_sched_wakeup_new\n");
  65                goto fail_deprobe;
  66        }
  67
  68        ret = register_trace_sched_switch(probe_sched_switch, NULL);
  69        if (ret) {
  70                pr_info("sched trace: Couldn't activate tracepoint"
  71                        " probe to kernel_sched_switch\n");
  72                goto fail_deprobe_wake_new;
  73        }
  74
  75        return ret;
  76fail_deprobe_wake_new:
  77        unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
  78fail_deprobe:
  79        unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
  80        return ret;
  81}
  82
  83static void tracing_sched_unregister(void)
  84{
  85        unregister_trace_sched_switch(probe_sched_switch, NULL);
  86        unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
  87        unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
  88}
  89
  90static void tracing_start_sched_switch(int ops)
  91{
  92        bool sched_register;
  93
  94        mutex_lock(&sched_register_mutex);
  95        sched_register = (!sched_cmdline_ref && !sched_tgid_ref);
  96
  97        switch (ops) {
  98        case RECORD_CMDLINE:
  99                sched_cmdline_ref++;
 100                break;
 101
 102        case RECORD_TGID:
 103                sched_tgid_ref++;
 104                break;
 105        }
 106
 107        if (sched_register && (sched_cmdline_ref || sched_tgid_ref))
 108                tracing_sched_register();
 109        mutex_unlock(&sched_register_mutex);
 110}
 111
 112static void tracing_stop_sched_switch(int ops)
 113{
 114        mutex_lock(&sched_register_mutex);
 115
 116        switch (ops) {
 117        case RECORD_CMDLINE:
 118                sched_cmdline_ref--;
 119                break;
 120
 121        case RECORD_TGID:
 122                sched_tgid_ref--;
 123                break;
 124        }
 125
 126        if (!sched_cmdline_ref && !sched_tgid_ref)
 127                tracing_sched_unregister();
 128        mutex_unlock(&sched_register_mutex);
 129}
 130
 131void tracing_start_cmdline_record(void)
 132{
 133        tracing_start_sched_switch(RECORD_CMDLINE);
 134}
 135
 136void tracing_stop_cmdline_record(void)
 137{
 138        tracing_stop_sched_switch(RECORD_CMDLINE);
 139}
 140
 141void tracing_start_tgid_record(void)
 142{
 143        tracing_start_sched_switch(RECORD_TGID);
 144}
 145
 146void tracing_stop_tgid_record(void)
 147{
 148        tracing_stop_sched_switch(RECORD_TGID);
 149}
 150