linux/samples/ftrace/sample-trace-array.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/module.h>
   3#include <linux/kthread.h>
   4#include <linux/trace.h>
   5#include <linux/trace_events.h>
   6#include <linux/timer.h>
   7#include <linux/err.h>
   8#include <linux/jiffies.h>
   9#include <linux/workqueue.h>
  10
  11/*
  12 * Any file that uses trace points, must include the header.
  13 * But only one file, must include the header by defining
  14 * CREATE_TRACE_POINTS first.  This will make the C code that
  15 * creates the handles for the trace points.
  16 */
  17#define CREATE_TRACE_POINTS
  18#include "sample-trace-array.h"
  19
  20struct trace_array *tr;
  21static void mytimer_handler(struct timer_list *unused);
  22static struct task_struct *simple_tsk;
  23
  24static void trace_work_fn(struct work_struct *work)
  25{
  26        /*
  27         * Disable tracing for event "sample_event".
  28         */
  29        trace_array_set_clr_event(tr, "sample-subsystem", "sample_event",
  30                        false);
  31}
  32static DECLARE_WORK(trace_work, trace_work_fn);
  33
  34/*
  35 * mytimer: Timer setup to disable tracing for event "sample_event". This
  36 * timer is only for the purposes of the sample module to demonstrate access of
  37 * Ftrace instances from within kernel.
  38 */
  39static DEFINE_TIMER(mytimer, mytimer_handler);
  40
  41static void mytimer_handler(struct timer_list *unused)
  42{
  43        schedule_work(&trace_work);
  44}
  45
  46static void simple_thread_func(int count)
  47{
  48        set_current_state(TASK_INTERRUPTIBLE);
  49        schedule_timeout(HZ);
  50
  51        /*
  52         * Printing count value using trace_array_printk() - trace_printk()
  53         * equivalent for the instance buffers.
  54         */
  55        trace_array_printk(tr, _THIS_IP_, "trace_array_printk: count=%d\n",
  56                        count);
  57        /*
  58         * Tracepoint for event "sample_event". This will print the
  59         * current value of count and current jiffies.
  60         */
  61        trace_sample_event(count, jiffies);
  62}
  63
  64static int simple_thread(void *arg)
  65{
  66        int count = 0;
  67        unsigned long delay = msecs_to_jiffies(5000);
  68
  69        /*
  70         * Enable tracing for "sample_event".
  71         */
  72        trace_array_set_clr_event(tr, "sample-subsystem", "sample_event", true);
  73
  74        /*
  75         * Adding timer - mytimer. This timer will disable tracing after
  76         * delay seconds.
  77         *
  78         */
  79        add_timer(&mytimer);
  80        mod_timer(&mytimer, jiffies+delay);
  81
  82        while (!kthread_should_stop())
  83                simple_thread_func(count++);
  84
  85        del_timer(&mytimer);
  86        cancel_work_sync(&trace_work);
  87
  88        /*
  89         * trace_array_put() decrements the reference counter associated with
  90         * the trace array - "tr". We are done using the trace array, hence
  91         * decrement the reference counter so that it can be destroyed using
  92         * trace_array_destroy().
  93         */
  94        trace_array_put(tr);
  95
  96        return 0;
  97}
  98
  99static int __init sample_trace_array_init(void)
 100{
 101        /*
 102         * Return a pointer to the trace array with name "sample-instance" if it
 103         * exists, else create a new trace array.
 104         *
 105         * NOTE: This function increments the reference counter
 106         * associated with the trace array - "tr".
 107         */
 108        tr = trace_array_get_by_name("sample-instance");
 109
 110        if (!tr)
 111                return -1;
 112        /*
 113         * If context specific per-cpu buffers havent already been allocated.
 114         */
 115        trace_printk_init_buffers();
 116
 117        simple_tsk = kthread_run(simple_thread, NULL, "sample-instance");
 118        if (IS_ERR(simple_tsk)) {
 119                trace_array_put(tr);
 120                trace_array_destroy(tr);
 121                return -1;
 122        }
 123
 124        return 0;
 125}
 126
 127static void __exit sample_trace_array_exit(void)
 128{
 129        kthread_stop(simple_tsk);
 130
 131        /*
 132         * We are unloading our module and no longer require the trace array.
 133         * Remove/destroy "tr" using trace_array_destroy()
 134         */
 135        trace_array_destroy(tr);
 136}
 137
 138module_init(sample_trace_array_init);
 139module_exit(sample_trace_array_exit);
 140
 141MODULE_AUTHOR("Divya Indi");
 142MODULE_DESCRIPTION("Sample module for kernel access to Ftrace instances");
 143MODULE_LICENSE("GPL");
 144