2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2009-04-15 05:37:03 +04:00
# include <linux/module.h>
# include <linux/kthread.h>
/*
* Any file that uses trace points , must include the header .
* But only one file , must include the header by defining
* CREATE_TRACE_POINTS first . This will make the C code that
* creates the handles for the trace points .
*/
# define CREATE_TRACE_POINTS
# include "trace-events-sample.h"
2015-02-09 23:27:04 +03:00
static const char * random_strings [ ] = {
" Mother Goose " ,
" Snoopy " ,
" Gandalf " ,
" Frodo " ,
" One ring to rule them all "
} ;
2009-04-15 05:37:03 +04:00
static void simple_thread_func ( int cnt )
{
2015-02-09 23:27:04 +03:00
int array [ 6 ] ;
int len = cnt % 5 ;
int i ;
2009-04-15 05:37:03 +04:00
set_current_state ( TASK_INTERRUPTIBLE ) ;
schedule_timeout ( HZ ) ;
2015-02-09 23:27:04 +03:00
for ( i = 0 ; i < len ; i + + )
array [ i ] = i + 1 ;
array [ i ] = 0 ;
2015-02-10 00:05:55 +03:00
/* Silly tracepoints */
2015-02-09 23:27:04 +03:00
trace_foo_bar ( " hello " , cnt , array , random_strings [ len ] ,
2019-04-23 17:26:36 +03:00
current - > cpus_ptr ) ;
2015-02-10 00:05:55 +03:00
2015-02-10 01:14:04 +03:00
trace_foo_with_template_simple ( " HELLO " , cnt ) ;
2015-02-10 00:05:55 +03:00
trace_foo_bar_with_cond ( " Some times print " , cnt ) ;
2015-02-10 01:14:04 +03:00
trace_foo_with_template_cond ( " prints other times " , cnt ) ;
trace_foo_with_template_print ( " I have to be different " , cnt ) ;
2009-04-15 05:37:03 +04:00
}
static int simple_thread ( void * arg )
{
int cnt = 0 ;
while ( ! kthread_should_stop ( ) )
simple_thread_func ( cnt + + ) ;
return 0 ;
}
static struct task_struct * simple_tsk ;
2015-02-10 00:32:19 +03:00
static struct task_struct * simple_tsk_fn ;
static void simple_thread_func_fn ( int cnt )
{
set_current_state ( TASK_INTERRUPTIBLE ) ;
schedule_timeout ( HZ ) ;
/* More silly tracepoints */
trace_foo_bar_with_fn ( " Look at me " , cnt ) ;
2015-02-10 01:14:04 +03:00
trace_foo_with_template_fn ( " Look at me too " , cnt ) ;
2015-02-10 00:32:19 +03:00
}
static int simple_thread_fn ( void * arg )
{
int cnt = 0 ;
while ( ! kthread_should_stop ( ) )
simple_thread_func_fn ( cnt + + ) ;
return 0 ;
}
static DEFINE_MUTEX ( thread_mutex ) ;
2017-10-28 06:35:31 +03:00
static int simple_thread_cnt ;
2015-02-10 00:32:19 +03:00
2016-11-28 21:03:21 +03:00
int foo_bar_reg ( void )
2015-02-10 00:32:19 +03:00
{
2017-10-17 21:55:24 +03:00
mutex_lock ( & thread_mutex ) ;
if ( simple_thread_cnt + + )
goto out ;
2015-02-10 00:32:19 +03:00
pr_info ( " Starting thread for foo_bar_fn \n " ) ;
/*
* We shouldn ' t be able to start a trace when the module is
* unloading ( there ' s other locks to prevent that ) . But
* for consistency sake , we still take the thread_mutex .
*/
simple_tsk_fn = kthread_run ( simple_thread_fn , NULL , " event-sample-fn " ) ;
2017-10-17 21:55:24 +03:00
out :
2015-02-10 00:32:19 +03:00
mutex_unlock ( & thread_mutex ) ;
2016-11-28 21:03:21 +03:00
return 0 ;
2015-02-10 00:32:19 +03:00
}
void foo_bar_unreg ( void )
{
mutex_lock ( & thread_mutex ) ;
2017-10-17 21:55:24 +03:00
if ( - - simple_thread_cnt )
goto out ;
pr_info ( " Killing thread for foo_bar_fn \n " ) ;
2015-02-10 00:32:19 +03:00
if ( simple_tsk_fn )
kthread_stop ( simple_tsk_fn ) ;
simple_tsk_fn = NULL ;
2017-10-17 21:55:24 +03:00
out :
2015-02-10 00:32:19 +03:00
mutex_unlock ( & thread_mutex ) ;
}
2009-04-15 05:37:03 +04:00
static int __init trace_event_init ( void )
{
simple_tsk = kthread_run ( simple_thread , NULL , " event-sample " ) ;
if ( IS_ERR ( simple_tsk ) )
return - 1 ;
return 0 ;
}
static void __exit trace_event_exit ( void )
{
kthread_stop ( simple_tsk ) ;
2015-02-10 00:32:19 +03:00
mutex_lock ( & thread_mutex ) ;
if ( simple_tsk_fn )
kthread_stop ( simple_tsk_fn ) ;
simple_tsk_fn = NULL ;
mutex_unlock ( & thread_mutex ) ;
2009-04-15 05:37:03 +04:00
}
module_init ( trace_event_init ) ;
module_exit ( trace_event_exit ) ;
MODULE_AUTHOR ( " Steven Rostedt " ) ;
MODULE_DESCRIPTION ( " trace-events-sample " ) ;
MODULE_LICENSE ( " GPL " ) ;