linux/samples/trace_events/trace-events-sample.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/module.h>
   3#include <linux/kthread.h>
   4
   5/*
   6 * Any file that uses trace points, must include the header.
   7 * But only one file, must include the header by defining
   8 * CREATE_TRACE_POINTS first.  This will make the C code that
   9 * creates the handles for the trace points.
  10 */
  11#define CREATE_TRACE_POINTS
  12#include "trace-events-sample.h"
  13
  14static const char *random_strings[] = {
  15        "Mother Goose",
  16        "Snoopy",
  17        "Gandalf",
  18        "Frodo",
  19        "One ring to rule them all"
  20};
  21
  22static void simple_thread_func(int cnt)
  23{
  24        int array[6];
  25        int len = cnt % 5;
  26        int i;
  27
  28        set_current_state(TASK_INTERRUPTIBLE);
  29        schedule_timeout(HZ);
  30
  31        for (i = 0; i < len; i++)
  32                array[i] = i + 1;
  33        array[i] = 0;
  34
  35        /* Silly tracepoints */
  36        trace_foo_bar("hello", cnt, array, random_strings[len],
  37                      current->cpus_ptr);
  38
  39        trace_foo_with_template_simple("HELLO", cnt);
  40
  41        trace_foo_bar_with_cond("Some times print", cnt);
  42
  43        trace_foo_with_template_cond("prints other times", cnt);
  44
  45        trace_foo_with_template_print("I have to be different", cnt);
  46}
  47
  48static int simple_thread(void *arg)
  49{
  50        int cnt = 0;
  51
  52        while (!kthread_should_stop())
  53                simple_thread_func(cnt++);
  54
  55        return 0;
  56}
  57
  58static struct task_struct *simple_tsk;
  59static struct task_struct *simple_tsk_fn;
  60
  61static void simple_thread_func_fn(int cnt)
  62{
  63        set_current_state(TASK_INTERRUPTIBLE);
  64        schedule_timeout(HZ);
  65
  66        /* More silly tracepoints */
  67        trace_foo_bar_with_fn("Look at me", cnt);
  68        trace_foo_with_template_fn("Look at me too", cnt);
  69}
  70
  71static int simple_thread_fn(void *arg)
  72{
  73        int cnt = 0;
  74
  75        while (!kthread_should_stop())
  76                simple_thread_func_fn(cnt++);
  77
  78        return 0;
  79}
  80
  81static DEFINE_MUTEX(thread_mutex);
  82static int simple_thread_cnt;
  83
  84int foo_bar_reg(void)
  85{
  86        mutex_lock(&thread_mutex);
  87        if (simple_thread_cnt++)
  88                goto out;
  89
  90        pr_info("Starting thread for foo_bar_fn\n");
  91        /*
  92         * We shouldn't be able to start a trace when the module is
  93         * unloading (there's other locks to prevent that). But
  94         * for consistency sake, we still take the thread_mutex.
  95         */
  96        simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
  97 out:
  98        mutex_unlock(&thread_mutex);
  99        return 0;
 100}
 101
 102void foo_bar_unreg(void)
 103{
 104        mutex_lock(&thread_mutex);
 105        if (--simple_thread_cnt)
 106                goto out;
 107
 108        pr_info("Killing thread for foo_bar_fn\n");
 109        if (simple_tsk_fn)
 110                kthread_stop(simple_tsk_fn);
 111        simple_tsk_fn = NULL;
 112 out:
 113        mutex_unlock(&thread_mutex);
 114}
 115
 116static int __init trace_event_init(void)
 117{
 118        simple_tsk = kthread_run(simple_thread, NULL, "event-sample");
 119        if (IS_ERR(simple_tsk))
 120                return -1;
 121
 122        return 0;
 123}
 124
 125static void __exit trace_event_exit(void)
 126{
 127        kthread_stop(simple_tsk);
 128        mutex_lock(&thread_mutex);
 129        if (simple_tsk_fn)
 130                kthread_stop(simple_tsk_fn);
 131        simple_tsk_fn = NULL;
 132        mutex_unlock(&thread_mutex);
 133}
 134
 135module_init(trace_event_init);
 136module_exit(trace_event_exit);
 137
 138MODULE_AUTHOR("Steven Rostedt");
 139MODULE_DESCRIPTION("trace-events-sample");
 140MODULE_LICENSE("GPL");
 141