18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci#include <linux/module.h> 38c2ecf20Sopenharmony_ci#include <linux/kthread.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * Any file that uses trace points, must include the header. 78c2ecf20Sopenharmony_ci * But only one file, must include the header by defining 88c2ecf20Sopenharmony_ci * CREATE_TRACE_POINTS first. This will make the C code that 98c2ecf20Sopenharmony_ci * creates the handles for the trace points. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS 128c2ecf20Sopenharmony_ci#include "trace-events-sample.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistatic const char *random_strings[] = { 158c2ecf20Sopenharmony_ci "Mother Goose", 168c2ecf20Sopenharmony_ci "Snoopy", 178c2ecf20Sopenharmony_ci "Gandalf", 188c2ecf20Sopenharmony_ci "Frodo", 198c2ecf20Sopenharmony_ci "One ring to rule them all" 208c2ecf20Sopenharmony_ci}; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic void simple_thread_func(int cnt) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci int array[6]; 258c2ecf20Sopenharmony_ci int len = cnt % 5; 268c2ecf20Sopenharmony_ci int i; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 298c2ecf20Sopenharmony_ci schedule_timeout(HZ); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) 328c2ecf20Sopenharmony_ci array[i] = i + 1; 338c2ecf20Sopenharmony_ci array[i] = 0; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* Silly tracepoints */ 368c2ecf20Sopenharmony_ci trace_foo_bar("hello", cnt, array, random_strings[len], 378c2ecf20Sopenharmony_ci current->cpus_ptr); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci trace_foo_with_template_simple("HELLO", cnt); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci trace_foo_bar_with_cond("Some times print", cnt); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci trace_foo_with_template_cond("prints other times", cnt); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci trace_foo_with_template_print("I have to be different", cnt); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic int simple_thread(void *arg) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci int cnt = 0; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci while (!kthread_should_stop()) 538c2ecf20Sopenharmony_ci simple_thread_func(cnt++); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic struct task_struct *simple_tsk; 598c2ecf20Sopenharmony_cistatic struct task_struct *simple_tsk_fn; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic void simple_thread_func_fn(int cnt) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 648c2ecf20Sopenharmony_ci schedule_timeout(HZ); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* More silly tracepoints */ 678c2ecf20Sopenharmony_ci trace_foo_bar_with_fn("Look at me", cnt); 688c2ecf20Sopenharmony_ci trace_foo_with_template_fn("Look at me too", cnt); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic int simple_thread_fn(void *arg) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci int cnt = 0; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci while (!kthread_should_stop()) 768c2ecf20Sopenharmony_ci simple_thread_func_fn(cnt++); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(thread_mutex); 828c2ecf20Sopenharmony_cistatic int simple_thread_cnt; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ciint foo_bar_reg(void) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci mutex_lock(&thread_mutex); 878c2ecf20Sopenharmony_ci if (simple_thread_cnt++) 888c2ecf20Sopenharmony_ci goto out; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci pr_info("Starting thread for foo_bar_fn\n"); 918c2ecf20Sopenharmony_ci /* 928c2ecf20Sopenharmony_ci * We shouldn't be able to start a trace when the module is 938c2ecf20Sopenharmony_ci * unloading (there's other locks to prevent that). But 948c2ecf20Sopenharmony_ci * for consistency sake, we still take the thread_mutex. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); 978c2ecf20Sopenharmony_ci out: 988c2ecf20Sopenharmony_ci mutex_unlock(&thread_mutex); 998c2ecf20Sopenharmony_ci return 0; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_civoid foo_bar_unreg(void) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci mutex_lock(&thread_mutex); 1058c2ecf20Sopenharmony_ci if (--simple_thread_cnt) 1068c2ecf20Sopenharmony_ci goto out; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci pr_info("Killing thread for foo_bar_fn\n"); 1098c2ecf20Sopenharmony_ci if (simple_tsk_fn) 1108c2ecf20Sopenharmony_ci kthread_stop(simple_tsk_fn); 1118c2ecf20Sopenharmony_ci simple_tsk_fn = NULL; 1128c2ecf20Sopenharmony_ci out: 1138c2ecf20Sopenharmony_ci mutex_unlock(&thread_mutex); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic int __init trace_event_init(void) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci simple_tsk = kthread_run(simple_thread, NULL, "event-sample"); 1198c2ecf20Sopenharmony_ci if (IS_ERR(simple_tsk)) 1208c2ecf20Sopenharmony_ci return -1; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return 0; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void __exit trace_event_exit(void) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci kthread_stop(simple_tsk); 1288c2ecf20Sopenharmony_ci mutex_lock(&thread_mutex); 1298c2ecf20Sopenharmony_ci if (simple_tsk_fn) 1308c2ecf20Sopenharmony_ci kthread_stop(simple_tsk_fn); 1318c2ecf20Sopenharmony_ci simple_tsk_fn = NULL; 1328c2ecf20Sopenharmony_ci mutex_unlock(&thread_mutex); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cimodule_init(trace_event_init); 1368c2ecf20Sopenharmony_cimodule_exit(trace_event_exit); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ciMODULE_AUTHOR("Steven Rostedt"); 1398c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("trace-events-sample"); 1408c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 141