From 1de4a819a058e09019bffbd51b26dffc13d81ee1 Mon Sep 17 00:00:00 2001 From: Drew Richardson Date: Tue, 17 Dec 2013 23:40:56 +0000 Subject: gator-driver: Handle task struct correctly Use put_task_struct/get_task_struct to ensure the task_struct pointer is still valid. Change translate_buffer to ensure that both arguments are written atomically. Drop additional requests if the translate_buffer is full. Signed-off-by: Drew Richardson Signed-off-by: Pawel Moll --- driver/gator_cookies.c | 74 ++++++++++++++++++++++++++++++++++---------------- driver/gator_iks.c | 2 ++ 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c index 91adfdd..eb9b946 100644 --- a/driver/gator_cookies.c +++ b/driver/gator_cookies.c @@ -15,13 +15,18 @@ static uint32_t *gator_crc32_table; static unsigned int translate_buffer_mask; +struct cookie_args { + struct task_struct *task; + const char *text; +}; + static DEFINE_PER_CPU(char *, translate_text); static DEFINE_PER_CPU(uint32_t, cookie_next_key); static DEFINE_PER_CPU(uint64_t *, cookie_keys); static DEFINE_PER_CPU(uint32_t *, cookie_values); static DEFINE_PER_CPU(int, translate_buffer_read); static DEFINE_PER_CPU(int, translate_buffer_write); -static DEFINE_PER_CPU(void **, translate_buffer); +static DEFINE_PER_CPU(struct cookie_args *, translate_buffer); static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); static void wq_cookie_handler(struct work_struct *unused); @@ -109,36 +114,58 @@ static void cookiemap_add(uint64_t key, uint32_t value) } #ifndef CONFIG_PREEMPT_RT_FULL -static void translate_buffer_write_ptr(int cpu, void *x) +static void translate_buffer_write_args(int cpu, struct task_struct *task, const char *text) { - per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; - per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; + unsigned long flags; + int write; + int next_write; + struct cookie_args *args; + + local_irq_save(flags); + + write = per_cpu(translate_buffer_write, cpu); + next_write = (write + 1) & translate_buffer_mask; + + // At least one entry must always remain available as when read == write, the queue is empty not full + if (next_write != per_cpu(translate_buffer_read, cpu)) { + args = &per_cpu(translate_buffer, cpu)[write]; + args->task = task; + args->text = text; + get_task_struct(task); + per_cpu(translate_buffer_write, cpu) = next_write; + } + + local_irq_restore(flags); } #endif -static void *translate_buffer_read_ptr(int cpu) +static void translate_buffer_read_args(int cpu, struct cookie_args *args) { - void *value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; - per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; - return value; + unsigned long flags; + int read; + + local_irq_save(flags); + + read = per_cpu(translate_buffer_read, cpu); + *args = per_cpu(translate_buffer, cpu)[read]; + per_cpu(translate_buffer_read, cpu) = (read + 1) & translate_buffer_mask; + + local_irq_restore(flags); } static void wq_cookie_handler(struct work_struct *unused) { - struct task_struct *task; - char *text; + struct cookie_args args; int cpu = get_physical_cpu(), cookie; - unsigned int commit; mutex_lock(&start_mutex); if (gator_started != 0) { - commit = per_cpu(translate_buffer_write, cpu); - while (per_cpu(translate_buffer_read, cpu) != commit) { - task = (struct task_struct *)translate_buffer_read_ptr(cpu); - text = (char *)translate_buffer_read_ptr(cpu); - cookie = get_cookie(cpu, task, text, true); - marshal_link(cookie, task->tgid, task->pid); + while (per_cpu(translate_buffer_read, cpu) != per_cpu(translate_buffer_write, cpu)) { + translate_buffer_read_args(cpu, &args); + cookie = get_cookie(cpu, args.task, args.text, true); + marshal_link(cookie, args.task->tgid, args.task->pid); + put_task_struct(args.task); } } @@ -169,15 +196,14 @@ static int translate_app_process(const char **text, int cpu, struct task_struct // inconsistent during a context switch between android/linux versions if (!from_wq) { // Check if already in buffer - int ptr = per_cpu(translate_buffer_read, cpu); - while (ptr != per_cpu(translate_buffer_write, cpu)) { - if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task) + int pos = per_cpu(translate_buffer_read, cpu); + while (pos != per_cpu(translate_buffer_write, cpu)) { + if (per_cpu(translate_buffer, cpu)[pos].task == task) goto out; - ptr = (ptr + 2) & translate_buffer_mask; + pos = (pos + 1) & translate_buffer_mask; } - translate_buffer_write_ptr(cpu, (void *)task); - translate_buffer_write_ptr(cpu, (void *)*text); + translate_buffer_write_args(cpu, task, *text); // Not safe to call in RT-Preempt full in schedule switch context mod_timer(&app_process_wake_up_timer, jiffies + 1); @@ -340,7 +366,7 @@ static int cookies_initialize(void) } memset(per_cpu(cookie_values, cpu), 0, size); - per_cpu(translate_buffer, cpu) = (void **)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); + per_cpu(translate_buffer, cpu) = (struct cookie_args *)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); if (!per_cpu(translate_buffer, cpu)) { err = -ENOMEM; goto cookie_setup_error; diff --git a/driver/gator_iks.c b/driver/gator_iks.c index 24233d7..0a90bdd 100644 --- a/driver/gator_iks.c +++ b/driver/gator_iks.c @@ -147,11 +147,13 @@ static void gator_send_iks_core_names(void) { int cpu; // Send the cpu names + preempt_disable(); for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { if (mpidr_cpus[cpu] != NULL) { gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]); } } + preempt_enable(); } static int gator_migrate_start(void) -- cgit v1.2.3-54-g00ecf