gator: Version 5.19
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_events_threads.c
1 /*
2  * Sample activity provider
3  *
4  * Copyright (C) ARM Limited 2014. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * See gator_events_mmapped.c for additional directions and
11  * troubleshooting.
12  *
13  * For this sample to work these entries must be present in the
14  * events.xml file. So create an events-threads.xml in the gator
15  * daemon source directory with the following contents and rebuild
16  * gatord:
17  *
18  * <category name="threads">
19  *   <event counter="Linux_threads" title="Linux" name="Threads" class="activity" activity1="odd" activity_color1="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="Linux syscall activity"/>
20  * </category>
21  */
22
23 #include <trace/events/sched.h>
24
25 #include "gator.h"
26
27 static ulong threads_enabled;
28 static ulong threads_key;
29 static ulong threads_cores;
30
31 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
32 GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next))
33 #else
34 GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next))
35 #endif
36 {
37         int cpu = get_physical_cpu();
38         int pid = next->pid;
39         if (pid == 0) {
40                 // idle
41                 gator_marshal_activity_switch(cpu, threads_key, 0, 0);
42         } else if (pid & 1) {
43                 // odd
44                 gator_marshal_activity_switch(cpu, threads_key, 1, pid);
45         } else {
46                 // even
47                 //gator_marshal_activity_switch(cpu, threads_key, 2, current->pid);
48                 // Multiple activities are not yet supported so emit idle
49                 gator_marshal_activity_switch(cpu, threads_key, 0, 0);
50         }
51 }
52
53 // Adds Linux_threads directory and enabled, key, and cores files to /dev/gator/events
54 static int gator_events_threads_create_files(struct super_block *sb, struct dentry *root)
55 {
56         struct dentry *dir;
57
58         dir = gatorfs_mkdir(sb, root, "Linux_threads");
59         if (!dir) {
60                 return -1;
61         }
62         gatorfs_create_ulong(sb, dir, "enabled", &threads_enabled);
63         gatorfs_create_ro_ulong(sb, dir, "key", &threads_key);
64         // Number of cores associated with this activity
65         gatorfs_create_ro_ulong(sb, dir, "cores", &threads_cores);
66
67         return 0;
68 }
69
70 static int gator_events_threads_start(void)
71 {
72         int cpu;
73
74         if (threads_enabled) {
75                 preempt_disable();
76                 for (cpu = 0; cpu < nr_cpu_ids; ++cpu) {
77                         gator_marshal_activity_switch(cpu, threads_key, 0, 0);
78                 }
79                 preempt_enable();
80
81                 if (GATOR_REGISTER_TRACE(sched_switch)) {
82                         goto fail_sched_switch;
83                 }
84         }
85
86         return 0;
87
88 fail_sched_switch:
89         return -1;
90 }
91
92 static void gator_events_threads_stop(void)
93 {
94         if (threads_enabled) {
95                 GATOR_UNREGISTER_TRACE(sched_switch);
96         }
97
98         threads_enabled = 0;
99 }
100
101 static struct gator_interface gator_events_threads_interface = {
102         .create_files = gator_events_threads_create_files,
103         .start = gator_events_threads_start,
104         .stop = gator_events_threads_stop,
105 };
106
107 // Must not be static. Ensure that this init function is added to GATOR_EVENTS_LIST in gator_main.c
108 int __init gator_events_threads_init(void)
109 {
110         threads_enabled = 0;
111         threads_key = gator_events_get_key();
112         threads_cores = nr_cpu_ids;
113
114         return gator_events_install(&gator_events_threads_interface);
115 }