summaryrefslogtreecommitdiffstats
path: root/driver
diff options
context:
space:
mode:
authorWade Cherry2012-07-12 10:29:16 -0500
committerJon Medhurst2012-07-13 04:56:57 -0500
commit2ccfda6ba471ba1722fe48d23767d9d024bd0750 (patch)
treec0c548d22ba3f8264d9d958aca29fd52c8ff0863 /driver
parentf7e8a3d4bed65fb0fdb846f53aad7b0a763767c7 (diff)
downloadarm-ds5-gator-2ccfda6ba471ba1722fe48d23767d9d024bd0750.tar.gz
arm-ds5-gator-2ccfda6ba471ba1722fe48d23767d9d024bd0750.tar.xz
arm-ds5-gator-2ccfda6ba471ba1722fe48d23767d9d024bd0750.zip
gator-driver: Move work scheduling to timers
... in order to work around deadlocks in kernel >= 3.5... Signed-off-by: Wade Cherry <wade.cherry@arm.com> Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Diffstat (limited to 'driver')
-rw-r--r--driver/gator_cookies.c15
-rw-r--r--driver/gator_events_meminfo.c19
-rw-r--r--driver/gator_events_net.c18
-rw-r--r--driver/gator_main.c13
4 files changed, 51 insertions, 14 deletions
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index 7b50916..df14d09 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -25,6 +25,10 @@ static DEFINE_PER_CPU(unsigned int *, translate_buffer);
25static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt); 25static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
26static void wq_cookie_handler(struct work_struct *unused); 26static void wq_cookie_handler(struct work_struct *unused);
27DECLARE_WORK(cookie_work, wq_cookie_handler); 27DECLARE_WORK(cookie_work, wq_cookie_handler);
28static struct timer_list app_process_wake_up_timer;
29static void app_process_wake_up_handler(unsigned long unused_data);
30static struct timer_list app_process_wake_up_timer;
31static void app_process_wake_up_handler(unsigned long unused_data);
28 32
29static uint32_t cookiemap_code(uint64_t value64) { 33static uint32_t cookiemap_code(uint64_t value64) {
30 uint32_t value = (uint32_t)((value64 >> 32) + value64); 34 uint32_t value = (uint32_t)((value64 >> 32) + value64);
@@ -136,6 +140,12 @@ static void wq_cookie_handler(struct work_struct *unused)
136 mutex_unlock(&start_mutex); 140 mutex_unlock(&start_mutex);
137} 141}
138 142
143static void app_process_wake_up_handler(unsigned long unused_data)
144{
145 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
146 schedule_work(&cookie_work);
147}
148
139// Retrieve full name from proc/pid/cmdline for java processes on Android 149// Retrieve full name from proc/pid/cmdline for java processes on Android
140static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt) 150static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt)
141{ 151{
@@ -162,7 +172,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
162 172
163 translate_buffer_write_int(cpu, (unsigned int)task); 173 translate_buffer_write_int(cpu, (unsigned int)task);
164 translate_buffer_write_int(cpu, (unsigned int)vma); 174 translate_buffer_write_int(cpu, (unsigned int)vma);
165 schedule_work(&cookie_work); 175 mod_timer(&app_process_wake_up_timer, jiffies + 1);
166 goto out; 176 goto out;
167 } 177 }
168 178
@@ -372,6 +382,8 @@ static int cookies_initialize(void)
372 gator_crc32_table[i] = crc; 382 gator_crc32_table[i] = crc;
373 } 383 }
374 384
385 setup_timer(&app_process_wake_up_timer, app_process_wake_up_handler, 0);
386
375cookie_setup_error: 387cookie_setup_error:
376 return err; 388 return err;
377} 389}
@@ -396,6 +408,7 @@ static void cookies_release(void)
396 per_cpu(translate_text, cpu) = NULL; 408 per_cpu(translate_text, cpu) = NULL;
397 } 409 }
398 410
411 del_timer_sync(&app_process_wake_up_timer);
399 kfree(gator_crc32_table); 412 kfree(gator_crc32_table);
400 gator_crc32_table = NULL; 413 gator_crc32_table = NULL;
401} 414}
diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c
index ad552ef..f9dfa9a 100644
--- a/driver/gator_events_meminfo.c
+++ b/driver/gator_events_meminfo.c
@@ -28,6 +28,8 @@ static bool new_data_avail;
28static void wq_sched_handler(struct work_struct *wsptr); 28static void wq_sched_handler(struct work_struct *wsptr);
29 29
30DECLARE_WORK(work, wq_sched_handler); 30DECLARE_WORK(work, wq_sched_handler);
31static struct timer_list meminfo_wake_up_timer;
32static void meminfo_wake_up_handler(unsigned long unused_data);
31 33
32#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 34#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
33GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) { 35GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) {
@@ -107,6 +109,7 @@ static int gator_events_meminfo_start(void)
107 if (GATOR_REGISTER_TRACE(mm_page_alloc)) 109 if (GATOR_REGISTER_TRACE(mm_page_alloc))
108 goto mm_page_alloc_exit; 110 goto mm_page_alloc_exit;
109 111
112 setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0);
110 return 0; 113 return 0;
111 114
112mm_page_alloc_exit: 115mm_page_alloc_exit:
@@ -140,13 +143,15 @@ static void gator_events_meminfo_stop(void)
140 GATOR_UNREGISTER_TRACE(mm_page_alloc); 143 GATOR_UNREGISTER_TRACE(mm_page_alloc);
141 } 144 }
142 145
146 del_timer_sync(&meminfo_wake_up_timer);
147
143 meminfo_global_enabled = 0; 148 meminfo_global_enabled = 0;
144 for (i = 0; i < MEMINFO_TOTAL; i++) { 149 for (i = 0; i < MEMINFO_TOTAL; i++) {
145 meminfo_enabled[i] = 0; 150 meminfo_enabled[i] = 0;
146 } 151 }
147} 152}
148 153
149// Must be run in process context (work queue) as the kernel function si_meminfo() can sleep 154// Must be run in process context as the kernel function si_meminfo() can sleep
150static void wq_sched_handler(struct work_struct *wsptr) 155static void wq_sched_handler(struct work_struct *wsptr)
151{ 156{
152 struct sysinfo info; 157 struct sysinfo info;
@@ -181,6 +186,12 @@ static void wq_sched_handler(struct work_struct *wsptr)
181 new_data_avail = true; 186 new_data_avail = true;
182} 187}
183 188
189static void meminfo_wake_up_handler(unsigned long unused_data)
190{
191 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
192 schedule_work(&work);
193}
194
184static int gator_events_meminfo_read(long long **buffer) 195static int gator_events_meminfo_read(long long **buffer)
185{ 196{
186 static unsigned int last_mem_event = 0; 197 static unsigned int last_mem_event = 0;
@@ -190,11 +201,7 @@ static int gator_events_meminfo_read(long long **buffer)
190 201
191 if (last_mem_event != mem_event) { 202 if (last_mem_event != mem_event) {
192 last_mem_event = mem_event; 203 last_mem_event = mem_event;
193 if (in_interrupt()) { 204 mod_timer(&meminfo_wake_up_timer, jiffies + 1);
194 schedule_work(&work);
195 } else {
196 wq_sched_handler(NULL);
197 }
198 } 205 }
199 206
200 if (!new_data_avail) 207 if (!new_data_avail)
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index 9298905..a3ae3f0 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -23,6 +23,8 @@ static int rx_total, tx_total;
23static ulong netPrev[TOTALNET]; 23static ulong netPrev[TOTALNET];
24static int netGet[TOTALNET * 4]; 24static int netGet[TOTALNET * 4];
25 25
26static struct timer_list net_wake_up_timer;
27
26static void get_network_stats(struct work_struct *wsptr) { 28static void get_network_stats(struct work_struct *wsptr) {
27 int rx = 0, tx = 0; 29 int rx = 0, tx = 0;
28 struct net_device *dev; 30 struct net_device *dev;
@@ -42,6 +44,12 @@ static void get_network_stats(struct work_struct *wsptr) {
42} 44}
43DECLARE_WORK(wq_get_stats, get_network_stats); 45DECLARE_WORK(wq_get_stats, get_network_stats);
44 46
47static void net_wake_up_handler(unsigned long unused_data)
48{
49 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
50 schedule_work(&wq_get_stats);
51}
52
45static void calculate_delta(int *rx, int *tx) 53static void calculate_delta(int *rx, int *tx)
46{ 54{
47 int rx_calc, tx_calc; 55 int rx_calc, tx_calc;
@@ -83,14 +91,16 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
83 91
84static int gator_events_net_start(void) 92static int gator_events_net_start(void)
85{ 93{
86 get_network_stats(NULL); 94 get_network_stats(0);
87 netPrev[NETRX] = rx_total; 95 netPrev[NETRX] = rx_total;
88 netPrev[NETTX] = tx_total; 96 netPrev[NETTX] = tx_total;
97 setup_timer(&net_wake_up_timer, net_wake_up_handler, 0);
89 return 0; 98 return 0;
90} 99}
91 100
92static void gator_events_net_stop(void) 101static void gator_events_net_stop(void)
93{ 102{
103 del_timer_sync(&net_wake_up_timer);
94 netrx_enabled = 0; 104 netrx_enabled = 0;
95 nettx_enabled = 0; 105 nettx_enabled = 0;
96} 106}
@@ -106,11 +116,7 @@ static int gator_events_net_read(int **buffer)
106 if (!netrx_enabled && !nettx_enabled) 116 if (!netrx_enabled && !nettx_enabled)
107 return 0; 117 return 0;
108 118
109 if (in_interrupt()){ 119 mod_timer(&net_wake_up_timer, jiffies + 1);
110 schedule_work(&wq_get_stats);
111 } else {
112 get_network_stats(NULL);
113 }
114 120
115 calculate_delta(&rx_delta, &tx_delta); 121 calculate_delta(&rx_delta, &tx_delta);
116 122
diff --git a/driver/gator_main.c b/driver/gator_main.c
index 988045f..994e35d 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -110,6 +110,7 @@ static DEFINE_MUTEX(gator_buffer_mutex);
110bool event_based_sampling; 110bool event_based_sampling;
111 111
112static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); 112static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
113static struct timer_list gator_buffer_wake_up_timer;
113static LIST_HEAD(gator_events); 114static LIST_HEAD(gator_events);
114 115
115/****************************************************************************** 116/******************************************************************************
@@ -163,6 +164,11 @@ u32 gator_cpuid(void)
163} 164}
164#endif 165#endif
165 166
167static void gator_buffer_wake_up(unsigned long data)
168{
169 wake_up(&gator_buffer_wait);
170}
171
166/****************************************************************************** 172/******************************************************************************
167 * Commit interface 173 * Commit interface
168 ******************************************************************************/ 174 ******************************************************************************/
@@ -283,7 +289,9 @@ static void gator_commit_buffer(int cpu, int buftype)
283 289
284 per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype]; 290 per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
285 gator_buffer_header(cpu, buftype); 291 gator_buffer_header(cpu, buftype);
286 wake_up(&gator_buffer_wait); 292
293 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
294 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
287} 295}
288 296
289static void buffer_check(int cpu, int buftype) 297static void buffer_check(int cpu, int buftype)
@@ -1069,11 +1077,14 @@ static int __init gator_module_init(void)
1069 return -1; 1077 return -1;
1070 } 1078 }
1071 1079
1080 setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0);
1081
1072 return 0; 1082 return 0;
1073} 1083}
1074 1084
1075static void __exit gator_module_exit(void) 1085static void __exit gator_module_exit(void)
1076{ 1086{
1087 del_timer_sync(&gator_buffer_wake_up_timer);
1077 tracepoint_synchronize_unregister(); 1088 tracepoint_synchronize_unregister();
1078 gatorfs_unregister(); 1089 gatorfs_unregister();
1079} 1090}