summaryrefslogtreecommitdiff
path: root/arch/arm/vfp
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2009-12-18 14:34:43 +0000
committerGary King <gking@nvidia.com>2010-06-15 21:35:19 -0700
commit5648a3bbc09b7c4b404cbf52aab5fa7edbaffdf3 (patch)
tree55cd7f92e645a1921875672e251d10576ac097a2 /arch/arm/vfp
parent5023d4720e7d7690581a7e27ae82515606428b61 (diff)
ARM: Convert VFP/Crunch/XscaleCP thread_release() to exit_thread()
This avoids races in the VFP code where the dead thread may have state on another CPU. By moving this code to exit_thread(), we will be running as the thread, and therefore be running on the current CPU. This means that we can ensure that the only local state is accessed in the thread notifiers. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Change-Id: I195ea8ce8f5f438166b402411eaff3f33f4b2490 Reviewed-on: http://git-master/r/2731 Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Tested-by: Krishna Reddy <vdumpa@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r--arch/arm/vfp/vfpmodule.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index aed05bc3c2ea..f60a5400a25b 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -63,14 +63,15 @@ static void vfp_thread_flush(struct thread_info *thread)
put_cpu();
}
-static void vfp_thread_release(struct thread_info *thread)
+static void vfp_thread_exit(struct thread_info *thread)
{
/* release case: Per-thread VFP cleanup. */
union vfp_state *vfp = &thread->vfpstate;
- unsigned int cpu = thread->cpu;
+ unsigned int cpu = get_cpu();
if (last_VFP_context[cpu] == vfp)
last_VFP_context[cpu] = NULL;
+ put_cpu();
}
/*
@@ -88,11 +89,13 @@ static void vfp_thread_release(struct thread_info *thread)
* but may change at any time.
* - we could be preempted if tree preempt rcu is enabled, so
* it is unsafe to use thread->cpu.
- * THREAD_NOTIFY_RELEASE:
- * - the thread (v) will not be running on any CPU; it is a dead thread.
- * - thread->cpu will be the last CPU the thread ran on, which may not
- * be the current CPU.
- * - we could be preempted if tree preempt rcu is enabled.
+ * THREAD_NOTIFY_EXIT
+ * - the thread (v) will be running on the local CPU, so
+ * v === current_thread_info()
+ * - thread->cpu is the local CPU number at the time it is accessed,
+ * but may change at any time.
+ * - we could be preempted if tree preempt rcu is enabled, so
+ * it is unsafe to use thread->cpu.
*/
static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
{
@@ -133,7 +136,7 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
if (cmd == THREAD_NOTIFY_FLUSH)
vfp_thread_flush(thread);
else
- vfp_thread_release(thread);
+ vfp_thread_exit(thread);
return NOTIFY_DONE;
}