LCOV - code coverage report
Current view: top level - kernel/trace - trace_sched_switch.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 97 0.0 %
Date: 2014-02-18 Functions: 0 13 0.0 %
Branches: 0 42 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * trace context switch
       3                 :            :  *
       4                 :            :  * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
       5                 :            :  *
       6                 :            :  */
       7                 :            : #include <linux/module.h>
       8                 :            : #include <linux/fs.h>
       9                 :            : #include <linux/debugfs.h>
      10                 :            : #include <linux/kallsyms.h>
      11                 :            : #include <linux/uaccess.h>
      12                 :            : #include <linux/ftrace.h>
      13                 :            : #include <trace/events/sched.h>
      14                 :            : 
      15                 :            : #include "trace.h"
      16                 :            : 
      17                 :            : static struct trace_array       *ctx_trace;
      18                 :            : static int __read_mostly        tracer_enabled;
      19                 :            : static int                      sched_ref;
      20                 :            : static DEFINE_MUTEX(sched_register_mutex);
      21                 :            : static int                      sched_stopped;
      22                 :            : 
      23                 :            : 
      24                 :            : void
      25                 :          0 : tracing_sched_switch_trace(struct trace_array *tr,
      26                 :            :                            struct task_struct *prev,
      27                 :            :                            struct task_struct *next,
      28                 :            :                            unsigned long flags, int pc)
      29                 :            : {
      30                 :            :         struct ftrace_event_call *call = &event_context_switch;
      31                 :          0 :         struct ring_buffer *buffer = tr->trace_buffer.buffer;
      32                 :            :         struct ring_buffer_event *event;
      33                 :            :         struct ctx_switch_entry *entry;
      34                 :            : 
      35                 :          0 :         event = trace_buffer_lock_reserve(buffer, TRACE_CTX,
      36                 :            :                                           sizeof(*entry), flags, pc);
      37         [ #  # ]:          0 :         if (!event)
      38                 :          0 :                 return;
      39                 :          0 :         entry   = ring_buffer_event_data(event);
      40                 :          0 :         entry->prev_pid                      = prev->pid;
      41                 :          0 :         entry->prev_prio             = prev->prio;
      42                 :          0 :         entry->prev_state            = prev->state;
      43                 :          0 :         entry->next_pid                      = next->pid;
      44                 :          0 :         entry->next_prio             = next->prio;
      45                 :          0 :         entry->next_state            = next->state;
      46                 :          0 :         entry->next_cpu      = task_cpu(next);
      47                 :            : 
      48         [ #  # ]:          0 :         if (!call_filter_check_discard(call, entry, buffer, event))
      49                 :          0 :                 trace_buffer_unlock_commit(buffer, event, flags, pc);
      50                 :            : }
      51                 :            : 
      52                 :            : static void
      53                 :          0 : probe_sched_switch(void *ignore, struct task_struct *prev, struct task_struct *next)
      54                 :            : {
      55                 :            :         struct trace_array_cpu *data;
      56                 :            :         unsigned long flags;
      57                 :            :         int cpu;
      58                 :            :         int pc;
      59                 :            : 
      60         [ #  # ]:          0 :         if (unlikely(!sched_ref))
      61                 :            :                 return;
      62                 :            : 
      63                 :          0 :         tracing_record_cmdline(prev);
      64                 :          0 :         tracing_record_cmdline(next);
      65                 :            : 
      66 [ #  # ][ #  # ]:          0 :         if (!tracer_enabled || sched_stopped)
      67                 :            :                 return;
      68                 :            : 
      69                 :            :         pc = preempt_count();
      70                 :            :         local_irq_save(flags);
      71                 :          0 :         cpu = raw_smp_processor_id();
      72                 :          0 :         data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
      73                 :            : 
      74         [ #  # ]:          0 :         if (likely(!atomic_read(&data->disabled)))
      75                 :          0 :                 tracing_sched_switch_trace(ctx_trace, prev, next, flags, pc);
      76                 :            : 
      77         [ #  # ]:          0 :         local_irq_restore(flags);
      78                 :            : }
      79                 :            : 
      80                 :            : void
      81                 :          0 : tracing_sched_wakeup_trace(struct trace_array *tr,
      82                 :            :                            struct task_struct *wakee,
      83                 :            :                            struct task_struct *curr,
      84                 :            :                            unsigned long flags, int pc)
      85                 :            : {
      86                 :            :         struct ftrace_event_call *call = &event_wakeup;
      87                 :            :         struct ring_buffer_event *event;
      88                 :            :         struct ctx_switch_entry *entry;
      89                 :          0 :         struct ring_buffer *buffer = tr->trace_buffer.buffer;
      90                 :            : 
      91                 :          0 :         event = trace_buffer_lock_reserve(buffer, TRACE_WAKE,
      92                 :            :                                           sizeof(*entry), flags, pc);
      93         [ #  # ]:          0 :         if (!event)
      94                 :          0 :                 return;
      95                 :          0 :         entry   = ring_buffer_event_data(event);
      96                 :          0 :         entry->prev_pid                      = curr->pid;
      97                 :          0 :         entry->prev_prio             = curr->prio;
      98                 :          0 :         entry->prev_state            = curr->state;
      99                 :          0 :         entry->next_pid                      = wakee->pid;
     100                 :          0 :         entry->next_prio             = wakee->prio;
     101                 :          0 :         entry->next_state            = wakee->state;
     102                 :          0 :         entry->next_cpu                      = task_cpu(wakee);
     103                 :            : 
     104         [ #  # ]:          0 :         if (!call_filter_check_discard(call, entry, buffer, event))
     105                 :          0 :                 trace_buffer_unlock_commit(buffer, event, flags, pc);
     106                 :            : }
     107                 :            : 
     108                 :            : static void
     109                 :          0 : probe_sched_wakeup(void *ignore, struct task_struct *wakee, int success)
     110                 :            : {
     111                 :            :         struct trace_array_cpu *data;
     112                 :            :         unsigned long flags;
     113                 :            :         int cpu, pc;
     114                 :            : 
     115         [ #  # ]:          0 :         if (unlikely(!sched_ref))
     116                 :            :                 return;
     117                 :            : 
     118                 :          0 :         tracing_record_cmdline(current);
     119                 :            : 
     120 [ #  # ][ #  # ]:          0 :         if (!tracer_enabled || sched_stopped)
     121                 :            :                 return;
     122                 :            : 
     123                 :            :         pc = preempt_count();
     124                 :            :         local_irq_save(flags);
     125                 :          0 :         cpu = raw_smp_processor_id();
     126                 :          0 :         data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
     127                 :            : 
     128         [ #  # ]:          0 :         if (likely(!atomic_read(&data->disabled)))
     129                 :          0 :                 tracing_sched_wakeup_trace(ctx_trace, wakee, current,
     130                 :            :                                            flags, pc);
     131                 :            : 
     132         [ #  # ]:          0 :         local_irq_restore(flags);
     133                 :            : }
     134                 :            : 
     135                 :          0 : static int tracing_sched_register(void)
     136                 :            : {
     137                 :            :         int ret;
     138                 :            : 
     139                 :            :         ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
     140         [ #  # ]:          0 :         if (ret) {
     141                 :          0 :                 pr_info("wakeup trace: Couldn't activate tracepoint"
     142                 :            :                         " probe to kernel_sched_wakeup\n");
     143                 :          0 :                 return ret;
     144                 :            :         }
     145                 :            : 
     146                 :            :         ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
     147         [ #  # ]:          0 :         if (ret) {
     148                 :          0 :                 pr_info("wakeup trace: Couldn't activate tracepoint"
     149                 :            :                         " probe to kernel_sched_wakeup_new\n");
     150                 :          0 :                 goto fail_deprobe;
     151                 :            :         }
     152                 :            : 
     153                 :            :         ret = register_trace_sched_switch(probe_sched_switch, NULL);
     154         [ #  # ]:          0 :         if (ret) {
     155                 :          0 :                 pr_info("sched trace: Couldn't activate tracepoint"
     156                 :            :                         " probe to kernel_sched_switch\n");
     157                 :            :                 goto fail_deprobe_wake_new;
     158                 :            :         }
     159                 :            : 
     160                 :            :         return ret;
     161                 :            : fail_deprobe_wake_new:
     162                 :            :         unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
     163                 :            : fail_deprobe:
     164                 :            :         unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
     165                 :          0 :         return ret;
     166                 :            : }
     167                 :            : 
     168                 :          0 : static void tracing_sched_unregister(void)
     169                 :            : {
     170                 :            :         unregister_trace_sched_switch(probe_sched_switch, NULL);
     171                 :            :         unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
     172                 :            :         unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
     173                 :          0 : }
     174                 :            : 
     175                 :          0 : static void tracing_start_sched_switch(void)
     176                 :            : {
     177                 :          0 :         mutex_lock(&sched_register_mutex);
     178         [ #  # ]:          0 :         if (!(sched_ref++))
     179                 :          0 :                 tracing_sched_register();
     180                 :          0 :         mutex_unlock(&sched_register_mutex);
     181                 :          0 : }
     182                 :            : 
     183                 :          0 : static void tracing_stop_sched_switch(void)
     184                 :            : {
     185                 :          0 :         mutex_lock(&sched_register_mutex);
     186         [ #  # ]:          0 :         if (!(--sched_ref))
     187                 :          0 :                 tracing_sched_unregister();
     188                 :          0 :         mutex_unlock(&sched_register_mutex);
     189                 :          0 : }
     190                 :            : 
     191                 :          0 : void tracing_start_cmdline_record(void)
     192                 :            : {
     193                 :          0 :         tracing_start_sched_switch();
     194                 :          0 : }
     195                 :            : 
     196                 :          0 : void tracing_stop_cmdline_record(void)
     197                 :            : {
     198                 :          0 :         tracing_stop_sched_switch();
     199                 :          0 : }
     200                 :            : 
     201                 :            : /**
     202                 :            :  * tracing_start_sched_switch_record - start tracing context switches
     203                 :            :  *
     204                 :            :  * Turns on context switch tracing for a tracer.
     205                 :            :  */
     206                 :          0 : void tracing_start_sched_switch_record(void)
     207                 :            : {
     208         [ #  # ]:          0 :         if (unlikely(!ctx_trace)) {
     209                 :          0 :                 WARN_ON(1);
     210                 :          0 :                 return;
     211                 :            :         }
     212                 :            : 
     213                 :          0 :         tracing_start_sched_switch();
     214                 :            : 
     215                 :          0 :         mutex_lock(&sched_register_mutex);
     216                 :          0 :         tracer_enabled++;
     217                 :          0 :         mutex_unlock(&sched_register_mutex);
     218                 :            : }
     219                 :            : 
     220                 :            : /**
     221                 :            :  * tracing_stop_sched_switch_record - start tracing context switches
     222                 :            :  *
     223                 :            :  * Turns off context switch tracing for a tracer.
     224                 :            :  */
     225                 :          0 : void tracing_stop_sched_switch_record(void)
     226                 :            : {
     227                 :          0 :         mutex_lock(&sched_register_mutex);
     228                 :          0 :         tracer_enabled--;
     229         [ #  # ]:          0 :         WARN_ON(tracer_enabled < 0);
     230                 :          0 :         mutex_unlock(&sched_register_mutex);
     231                 :            : 
     232                 :          0 :         tracing_stop_sched_switch();
     233                 :          0 : }
     234                 :            : 
     235                 :            : /**
     236                 :            :  * tracing_sched_switch_assign_trace - assign a trace array for ctx switch
     237                 :            :  * @tr: trace array pointer to assign
     238                 :            :  *
     239                 :            :  * Some tracers might want to record the context switches in their
     240                 :            :  * trace. This function lets those tracers assign the trace array
     241                 :            :  * to use.
     242                 :            :  */
     243                 :          0 : void tracing_sched_switch_assign_trace(struct trace_array *tr)
     244                 :            : {
     245                 :          0 :         ctx_trace = tr;
     246                 :          0 : }
     247                 :            : 

Generated by: LCOV version 1.9