gator: ARM DS-5.3 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_events_sched.c
1 /**
2  * Copyright (C) ARM Limited 2010. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
10 #include <linux/version.h>
11 #include <linux/slab.h>
12 #include <linux/fs.h>
13 #include <linux/mm.h>
14 #include <linux/dcookies.h>
15 #include <trace/events/sched.h>
17 #include "gator.h"
18 #include "gator_trace.h"
20 #define SCHED_SWITCH    0
21 #define SCHED_TOTAL             (SCHED_SWITCH+1)
23 static ulong sched_switch_enabled;
24 static ulong sched_switch_key;
25 static DEFINE_PER_CPU(int[SCHED_TOTAL], schedCnt);
26 static DEFINE_PER_CPU(int[SCHED_TOTAL * 2], schedGet);
28 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
29 GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next))
30 #else
31 GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next))
32 #endif
33 {
34         unsigned long flags;
36         // disable interrupts to synchronize with gator_events_sched_read()
37         // spinlocks not needed since percpu buffers are used
38         local_irq_save(flags);
39         per_cpu(schedCnt, raw_smp_processor_id())[SCHED_SWITCH]++;
40         local_irq_restore(flags);
41 }
43 static int gator_events_sched_create_files(struct super_block *sb, struct dentry *root)
44 {
45         struct dentry *dir;
47         /* switch */
48         dir = gatorfs_mkdir(sb, root, "Linux_sched_switch");
49         if (!dir) {
50                 return -1;
51         }
52         gatorfs_create_ulong(sb, dir, "enabled", &sched_switch_enabled);
53         gatorfs_create_ro_ulong(sb, dir, "key", &sched_switch_key);
55         return 0;
56 }
58 static int gator_events_sched_init(int *key)
59 {
60         sched_switch_enabled = 0;
62         sched_switch_key = *key;
63         *key = *key + 1;
65         return 0;
66 }
68 static int gator_events_sched_start(void)
69 {
70         // register tracepoints
71         if (sched_switch_enabled)
72                 if (GATOR_REGISTER_TRACE(sched_switch))
73                         goto sched_switch_exit;
74         pr_debug("gator: registered scheduler event tracepoints\n");
76         return 0;
78         // unregister tracepoints on error
79 sched_switch_exit:
80         pr_err("gator: scheduler event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n");
82         return -1;
83 }
85 static void gator_events_sched_stop(void)
86 {
87         if (sched_switch_enabled)
88                 GATOR_UNREGISTER_TRACE(sched_switch);
89         pr_debug("gator: unregistered scheduler event tracepoints\n");
91         sched_switch_enabled = 0;
92 }
94 static int gator_events_sched_read(int **buffer)
95 {
96         unsigned long flags;
97         int len, value;
98         int cpu = raw_smp_processor_id();
100         len = 0;
101         if (sched_switch_enabled) {
102                 local_irq_save(flags);
103                 value = per_cpu(schedCnt, cpu)[SCHED_SWITCH];
104                 per_cpu(schedCnt, cpu)[SCHED_SWITCH] = 0;
105                 local_irq_restore(flags);
106                 per_cpu(schedGet, cpu)[len++] = sched_switch_key;
107                 per_cpu(schedGet, cpu)[len++] = value;
108         }
110         if (buffer)
111                 *buffer = per_cpu(schedGet, cpu);
113         return len;
116 int gator_events_sched_install(gator_interface *gi) {
117         gi->create_files = gator_events_sched_create_files;
118         gi->init = gator_events_sched_init;
119         gi->start = gator_events_sched_start;
120         gi->stop = gator_events_sched_stop;
121         gi->read = gator_events_sched_read;
122         return 0;