summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f7e8a3d)
raw | patch | inline | side by side (parent: f7e8a3d)
author | Wade Cherry <wade.cherry@arm.com> | |
Thu, 12 Jul 2012 15:29:16 +0000 (16:29 +0100) | ||
committer | Jon Medhurst <tixy@linaro.org> | |
Fri, 13 Jul 2012 09:56:57 +0000 (10:56 +0100) |
... 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>
Signed-off-by: Wade Cherry <wade.cherry@arm.com>
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
driver/gator_cookies.c | patch | blob | history | |
driver/gator_events_meminfo.c | patch | blob | history | |
driver/gator_events_net.c | patch | blob | history | |
driver/gator_main.c | patch | blob | history |
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index 7b5091696bfaa2443b84cc50b875ccb2f3997617..df14d095107c2b5344ee5346c2aae7588450c717 100644 (file)
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
static inline uint32_t get_cookie(int cpu, int buftype, struct task_struct *task, struct vm_area_struct *vma, struct module *mod, bool in_interrupt);
static void wq_cookie_handler(struct work_struct *unused);
DECLARE_WORK(cookie_work, wq_cookie_handler);
+static struct timer_list app_process_wake_up_timer;
+static void app_process_wake_up_handler(unsigned long unused_data);
+static struct timer_list app_process_wake_up_timer;
+static void app_process_wake_up_handler(unsigned long unused_data);
static uint32_t cookiemap_code(uint64_t value64) {
uint32_t value = (uint32_t)((value64 >> 32) + value64);
mutex_unlock(&start_mutex);
}
+static void app_process_wake_up_handler(unsigned long unused_data)
+{
+ // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ schedule_work(&cookie_work);
+}
+
// Retrieve full name from proc/pid/cmdline for java processes on Android
static int translate_app_process(char** text, int cpu, struct task_struct * task, struct vm_area_struct *vma, bool in_interrupt)
{
@@ -162,7 +172,7 @@ static int translate_app_process(char** text, int cpu, struct task_struct * task
translate_buffer_write_int(cpu, (unsigned int)task);
translate_buffer_write_int(cpu, (unsigned int)vma);
- schedule_work(&cookie_work);
+ mod_timer(&app_process_wake_up_timer, jiffies + 1);
goto out;
}
gator_crc32_table[i] = crc;
}
+ setup_timer(&app_process_wake_up_timer, app_process_wake_up_handler, 0);
+
cookie_setup_error:
return err;
}
per_cpu(translate_text, cpu) = NULL;
}
+ del_timer_sync(&app_process_wake_up_timer);
kfree(gator_crc32_table);
gator_crc32_table = NULL;
}
index ad552ef6c6e5885217f92ca105ca369b1197eace..f9dfa9a04eb443594d793284b6aec793449cdb1d 100644 (file)
static void wq_sched_handler(struct work_struct *wsptr);
DECLARE_WORK(work, wq_sched_handler);
+static struct timer_list meminfo_wake_up_timer;
+static void meminfo_wake_up_handler(unsigned long unused_data);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) {
if (GATOR_REGISTER_TRACE(mm_page_alloc))
goto mm_page_alloc_exit;
+ setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0);
return 0;
mm_page_alloc_exit:
GATOR_UNREGISTER_TRACE(mm_page_alloc);
}
+ del_timer_sync(&meminfo_wake_up_timer);
+
meminfo_global_enabled = 0;
for (i = 0; i < MEMINFO_TOTAL; i++) {
meminfo_enabled[i] = 0;
}
}
-// Must be run in process context (work queue) as the kernel function si_meminfo() can sleep
+// Must be run in process context as the kernel function si_meminfo() can sleep
static void wq_sched_handler(struct work_struct *wsptr)
{
struct sysinfo info;
new_data_avail = true;
}
+static void meminfo_wake_up_handler(unsigned long unused_data)
+{
+ // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ schedule_work(&work);
+}
+
static int gator_events_meminfo_read(long long **buffer)
{
static unsigned int last_mem_event = 0;
if (last_mem_event != mem_event) {
last_mem_event = mem_event;
- if (in_interrupt()) {
- schedule_work(&work);
- } else {
- wq_sched_handler(NULL);
- }
+ mod_timer(&meminfo_wake_up_timer, jiffies + 1);
}
if (!new_data_avail)
index 9298905e626f0ac2579e07122df7040907b2b3d6..a3ae3f03e291005a34e089ebf1437ac2abca8821 100644 (file)
static ulong netPrev[TOTALNET];
static int netGet[TOTALNET * 4];
+static struct timer_list net_wake_up_timer;
+
static void get_network_stats(struct work_struct *wsptr) {
int rx = 0, tx = 0;
struct net_device *dev;
}
DECLARE_WORK(wq_get_stats, get_network_stats);
+static void net_wake_up_handler(unsigned long unused_data)
+{
+ // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ schedule_work(&wq_get_stats);
+}
+
static void calculate_delta(int *rx, int *tx)
{
int rx_calc, tx_calc;
@@ -83,14 +91,16 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
static int gator_events_net_start(void)
{
- get_network_stats(NULL);
+ get_network_stats(0);
netPrev[NETRX] = rx_total;
netPrev[NETTX] = tx_total;
+ setup_timer(&net_wake_up_timer, net_wake_up_handler, 0);
return 0;
}
static void gator_events_net_stop(void)
{
+ del_timer_sync(&net_wake_up_timer);
netrx_enabled = 0;
nettx_enabled = 0;
}
if (!netrx_enabled && !nettx_enabled)
return 0;
- if (in_interrupt()){
- schedule_work(&wq_get_stats);
- } else {
- get_network_stats(NULL);
- }
+ mod_timer(&net_wake_up_timer, jiffies + 1);
calculate_delta(&rx_delta, &tx_delta);
diff --git a/driver/gator_main.c b/driver/gator_main.c
index 988045f187db99901bc3c6bc169efbbdf5d7b6d6..994e35d67d82076baef2a9149e6876372a791da4 100644 (file)
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
bool event_based_sampling;
static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
+static struct timer_list gator_buffer_wake_up_timer;
static LIST_HEAD(gator_events);
/******************************************************************************
}
#endif
+static void gator_buffer_wake_up(unsigned long data)
+{
+ wake_up(&gator_buffer_wait);
+}
+
/******************************************************************************
* Commit interface
******************************************************************************/
per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
gator_buffer_header(cpu, buftype);
- wake_up(&gator_buffer_wait);
+
+ // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
+ mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
}
static void buffer_check(int cpu, int buftype)
return -1;
}
+ setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0);
+
return 0;
}
static void __exit gator_module_exit(void)
{
+ del_timer_sync(&gator_buffer_wake_up_timer);
tracepoint_synchronize_unregister();
gatorfs_unregister();
}