diff options
author | Drew Richardson | 2013-12-17 17:40:56 -0600 |
---|---|---|
committer | Jon Medhurst | 2013-12-18 13:03:26 -0600 |
commit | 1de4a819a058e09019bffbd51b26dffc13d81ee1 (patch) | |
tree | f2894cb297e9bb8e4d1f65d8c061eafdf84624fd | |
parent | c3fc2b13fd58f1f5db521a062f0bbf782874383c (diff) | |
download | arm-ds5-gator-1de4a819a058e09019bffbd51b26dffc13d81ee1.tar.gz arm-ds5-gator-1de4a819a058e09019bffbd51b26dffc13d81ee1.tar.xz arm-ds5-gator-1de4a819a058e09019bffbd51b26dffc13d81ee1.zip |
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 <drew.richardson@arm.com>
Signed-off-by: Pawel Moll <pawel.moll@arm.com>
-rw-r--r-- | driver/gator_cookies.c | 74 | ||||
-rw-r--r-- | 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 @@ | |||
15 | static uint32_t *gator_crc32_table; | 15 | static uint32_t *gator_crc32_table; |
16 | static unsigned int translate_buffer_mask; | 16 | static unsigned int translate_buffer_mask; |
17 | 17 | ||
18 | struct cookie_args { | ||
19 | struct task_struct *task; | ||
20 | const char *text; | ||
21 | }; | ||
22 | |||
18 | static DEFINE_PER_CPU(char *, translate_text); | 23 | static DEFINE_PER_CPU(char *, translate_text); |
19 | static DEFINE_PER_CPU(uint32_t, cookie_next_key); | 24 | static DEFINE_PER_CPU(uint32_t, cookie_next_key); |
20 | static DEFINE_PER_CPU(uint64_t *, cookie_keys); | 25 | static DEFINE_PER_CPU(uint64_t *, cookie_keys); |
21 | static DEFINE_PER_CPU(uint32_t *, cookie_values); | 26 | static DEFINE_PER_CPU(uint32_t *, cookie_values); |
22 | static DEFINE_PER_CPU(int, translate_buffer_read); | 27 | static DEFINE_PER_CPU(int, translate_buffer_read); |
23 | static DEFINE_PER_CPU(int, translate_buffer_write); | 28 | static DEFINE_PER_CPU(int, translate_buffer_write); |
24 | static DEFINE_PER_CPU(void **, translate_buffer); | 29 | static DEFINE_PER_CPU(struct cookie_args *, translate_buffer); |
25 | 30 | ||
26 | static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); | 31 | static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq); |
27 | static void wq_cookie_handler(struct work_struct *unused); | 32 | static void wq_cookie_handler(struct work_struct *unused); |
@@ -109,36 +114,58 @@ static void cookiemap_add(uint64_t key, uint32_t value) | |||
109 | } | 114 | } |
110 | 115 | ||
111 | #ifndef CONFIG_PREEMPT_RT_FULL | 116 | #ifndef CONFIG_PREEMPT_RT_FULL |
112 | static void translate_buffer_write_ptr(int cpu, void *x) | 117 | static void translate_buffer_write_args(int cpu, struct task_struct *task, const char *text) |
113 | { | 118 | { |
114 | per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_write, cpu)++] = x; | 119 | unsigned long flags; |
115 | per_cpu(translate_buffer_write, cpu) &= translate_buffer_mask; | 120 | int write; |
121 | int next_write; | ||
122 | struct cookie_args *args; | ||
123 | |||
124 | local_irq_save(flags); | ||
125 | |||
126 | write = per_cpu(translate_buffer_write, cpu); | ||
127 | next_write = (write + 1) & translate_buffer_mask; | ||
128 | |||
129 | // At least one entry must always remain available as when read == write, the queue is empty not full | ||
130 | if (next_write != per_cpu(translate_buffer_read, cpu)) { | ||
131 | args = &per_cpu(translate_buffer, cpu)[write]; | ||
132 | args->task = task; | ||
133 | args->text = text; | ||
134 | get_task_struct(task); | ||
135 | per_cpu(translate_buffer_write, cpu) = next_write; | ||
136 | } | ||
137 | |||
138 | local_irq_restore(flags); | ||
116 | } | 139 | } |
117 | #endif | 140 | #endif |
118 | 141 | ||
119 | static void *translate_buffer_read_ptr(int cpu) | 142 | static void translate_buffer_read_args(int cpu, struct cookie_args *args) |
120 | { | 143 | { |
121 | void *value = per_cpu(translate_buffer, cpu)[per_cpu(translate_buffer_read, cpu)++]; | 144 | unsigned long flags; |
122 | per_cpu(translate_buffer_read, cpu) &= translate_buffer_mask; | 145 | int read; |
123 | return value; | 146 | |
147 | local_irq_save(flags); | ||
148 | |||
149 | read = per_cpu(translate_buffer_read, cpu); | ||
150 | *args = per_cpu(translate_buffer, cpu)[read]; | ||
151 | per_cpu(translate_buffer_read, cpu) = (read + 1) & translate_buffer_mask; | ||
152 | |||
153 | local_irq_restore(flags); | ||
124 | } | 154 | } |
125 | 155 | ||
126 | static void wq_cookie_handler(struct work_struct *unused) | 156 | static void wq_cookie_handler(struct work_struct *unused) |
127 | { | 157 | { |
128 | struct task_struct *task; | 158 | struct cookie_args args; |
129 | char *text; | ||
130 | int cpu = get_physical_cpu(), cookie; | 159 | int cpu = get_physical_cpu(), cookie; |
131 | unsigned int commit; | ||
132 | 160 | ||
133 | mutex_lock(&start_mutex); | 161 | mutex_lock(&start_mutex); |
134 | 162 | ||
135 | if (gator_started != 0) { | 163 | if (gator_started != 0) { |
136 | commit = per_cpu(translate_buffer_write, cpu); | 164 | while (per_cpu(translate_buffer_read, cpu) != per_cpu(translate_buffer_write, cpu)) { |
137 | while (per_cpu(translate_buffer_read, cpu) != commit) { | 165 | translate_buffer_read_args(cpu, &args); |
138 | task = (struct task_struct *)translate_buffer_read_ptr(cpu); | 166 | cookie = get_cookie(cpu, args.task, args.text, true); |
139 | text = (char *)translate_buffer_read_ptr(cpu); | 167 | marshal_link(cookie, args.task->tgid, args.task->pid); |
140 | cookie = get_cookie(cpu, task, text, true); | 168 | put_task_struct(args.task); |
141 | marshal_link(cookie, task->tgid, task->pid); | ||
142 | } | 169 | } |
143 | } | 170 | } |
144 | 171 | ||
@@ -169,15 +196,14 @@ static int translate_app_process(const char **text, int cpu, struct task_struct | |||
169 | // inconsistent during a context switch between android/linux versions | 196 | // inconsistent during a context switch between android/linux versions |
170 | if (!from_wq) { | 197 | if (!from_wq) { |
171 | // Check if already in buffer | 198 | // Check if already in buffer |
172 | int ptr = per_cpu(translate_buffer_read, cpu); | 199 | int pos = per_cpu(translate_buffer_read, cpu); |
173 | while (ptr != per_cpu(translate_buffer_write, cpu)) { | 200 | while (pos != per_cpu(translate_buffer_write, cpu)) { |
174 | if (per_cpu(translate_buffer, cpu)[ptr] == (void *)task) | 201 | if (per_cpu(translate_buffer, cpu)[pos].task == task) |
175 | goto out; | 202 | goto out; |
176 | ptr = (ptr + 2) & translate_buffer_mask; | 203 | pos = (pos + 1) & translate_buffer_mask; |
177 | } | 204 | } |
178 | 205 | ||
179 | translate_buffer_write_ptr(cpu, (void *)task); | 206 | translate_buffer_write_args(cpu, task, *text); |
180 | translate_buffer_write_ptr(cpu, (void *)*text); | ||
181 | 207 | ||
182 | // Not safe to call in RT-Preempt full in schedule switch context | 208 | // Not safe to call in RT-Preempt full in schedule switch context |
183 | mod_timer(&app_process_wake_up_timer, jiffies + 1); | 209 | mod_timer(&app_process_wake_up_timer, jiffies + 1); |
@@ -340,7 +366,7 @@ static int cookies_initialize(void) | |||
340 | } | 366 | } |
341 | memset(per_cpu(cookie_values, cpu), 0, size); | 367 | memset(per_cpu(cookie_values, cpu), 0, size); |
342 | 368 | ||
343 | per_cpu(translate_buffer, cpu) = (void **)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); | 369 | per_cpu(translate_buffer, cpu) = (struct cookie_args *)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); |
344 | if (!per_cpu(translate_buffer, cpu)) { | 370 | if (!per_cpu(translate_buffer, cpu)) { |
345 | err = -ENOMEM; | 371 | err = -ENOMEM; |
346 | goto cookie_setup_error; | 372 | 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) | |||
147 | { | 147 | { |
148 | int cpu; | 148 | int cpu; |
149 | // Send the cpu names | 149 | // Send the cpu names |
150 | preempt_disable(); | ||
150 | for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { | 151 | for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { |
151 | if (mpidr_cpus[cpu] != NULL) { | 152 | if (mpidr_cpus[cpu] != NULL) { |
152 | gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]); | 153 | gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid, mpidr_cpus[cpu]); |
153 | } | 154 | } |
154 | } | 155 | } |
156 | preempt_enable(); | ||
155 | } | 157 | } |
156 | 158 | ||
157 | static int gator_migrate_start(void) | 159 | static int gator_migrate_start(void) |