Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1270243

[RFC PATCH 2/4] MIPS: Factor out FP context preemption

From "Maciej W. Rozycki" <macro@imgtec.com>
Newsgroups linux.kernel
Subject [RFC PATCH 2/4] MIPS: Factor out FP context preemption
Date 2015-11-16 15:40 +0100
Message-ID <qvt6O-8uH-43@gated-at.bofh.it> (permalink)
References <qvt6N-8uH-7@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
Following the discussion around commit 9791554b [MIPS,prctl: add 
PR_[GS]ET_FP_MODE prctl options for MIPS] or 
<http://patchwork.linux-mips.org/patch/8899/> and Leonid's observation 
<http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=54B02115.7090609%40imgtec.com> 
in particular, I agree this would best be done with an IPI, however such 
an improvement is independent of the changes made as a part of this series 
so I took the minimal approach and left the solution implemented so far 
unchanged.  Especially as Leonid says he's got a patch already available.

linux-mips-process-fp-context.diff
Index: linux-sfr-test/arch/mips/kernel/process.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/process.c	2015-11-13 00:36:09.885716000 +0000
+++ linux-sfr-test/arch/mips/kernel/process.c	2015-11-16 13:50:18.962058000 +0000
@@ -570,6 +570,60 @@ void arch_trigger_all_cpu_backtrace(bool
 	smp_call_function(arch_dump_stack, NULL, 1);
 }
 
+/*
+ * Make the FP context available for mode changes.
+ */
+static void mips_get_fp_context(struct task_struct *task)
+{
+	unsigned long switch_count;
+	struct task_struct *t;
+
+	/* Save FP & vector context, then disable FPU & MSA.  */
+	if (task->signal == current->signal)
+		lose_fpu(1);
+
+	/* Prevent any threads from obtaining live FP context.  */
+	atomic_set(&task->mm->context.fp_mode_switching, 1);
+	smp_mb__after_atomic();
+
+	/*
+	 * If there are multiple online CPUs then wait until all threads
+	 * whose FP mode is about to change have been context switched.
+	 * This approach allows us to only worry about whether an FP mode
+	 * switch is in progress when FP is first used in a tasks time
+	 * slice.  Pretty much all of the mode switch overhead can thus
+	 * be confined to cases where mode switches are actually occurring.
+	 * That is, to here.  However for the thread performing the mode
+	 * switch it may take a while...
+	 */
+	if (num_online_cpus() > 1) {
+		spin_lock_irq(&task->sighand->siglock);
+
+		for_each_thread(task, t) {
+			if (t == current)
+				continue;
+
+			switch_count = t->nvcsw + t->nivcsw;
+
+			do {
+				spin_unlock_irq(&task->sighand->siglock);
+				cond_resched();
+				spin_lock_irq(&task->sighand->siglock);
+			} while ((t->nvcsw + t->nivcsw) == switch_count);
+		}
+
+		spin_unlock_irq(&task->sighand->siglock);
+	}
+}
+
+/*
+ * Allow threads to use FP again.
+ */
+static void mips_put_fp_context(struct task_struct *task)
+{
+	atomic_set(&task->mm->context.fp_mode_switching, 0);
+}
+
 int mips_get_process_fp_mode(struct task_struct *task)
 {
 	int value = 0;
@@ -585,7 +639,6 @@ int mips_get_process_fp_mode(struct task
 int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 {
 	const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
-	unsigned long switch_count;
 	struct task_struct *t;
 
 	/* Check the value is valid */
@@ -603,41 +656,7 @@ int mips_set_process_fp_mode(struct task
 	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
 		return -EOPNOTSUPP;
 
-	/* Save FP & vector context, then disable FPU & MSA */
-	if (task->signal == current->signal)
-		lose_fpu(1);
-
-	/* Prevent any threads from obtaining live FP context */
-	atomic_set(&task->mm->context.fp_mode_switching, 1);
-	smp_mb__after_atomic();
-
-	/*
-	 * If there are multiple online CPUs then wait until all threads whose
-	 * FP mode is about to change have been context switched. This approach
-	 * allows us to only worry about whether an FP mode switch is in
-	 * progress when FP is first used in a tasks time slice. Pretty much all
-	 * of the mode switch overhead can thus be confined to cases where mode
-	 * switches are actually occuring. That is, to here. However for the
-	 * thread performing the mode switch it may take a while...
-	 */
-	if (num_online_cpus() > 1) {
-		spin_lock_irq(&task->sighand->siglock);
-
-		for_each_thread(task, t) {
-			if (t == current)
-				continue;
-
-			switch_count = t->nvcsw + t->nivcsw;
-
-			do {
-				spin_unlock_irq(&task->sighand->siglock);
-				cond_resched();
-				spin_lock_irq(&task->sighand->siglock);
-			} while ((t->nvcsw + t->nivcsw) == switch_count);
-		}
-
-		spin_unlock_irq(&task->sighand->siglock);
-	}
+	mips_get_fp_context(task);
 
 	/*
 	 * There are now no threads of the process with live FP context, so it
@@ -659,8 +678,7 @@ int mips_set_process_fp_mode(struct task
 			clear_tsk_thread_flag(t, TIF_HYBRID_FPREGS);
 	}
 
-	/* Allow threads to use FP again */
-	atomic_set(&task->mm->context.fp_mode_switching, 0);
+	mips_put_fp_context(task);
 
 	return 0;
 }
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Back to linux.kernel | Previous | Next — Previous in thread | Find similar | Unroll thread


Thread

[RFC PATCH 0/4] MIPS: IEEE Std 754 NaN interlinking support "Maciej W. Rozycki" <macro@imgtec.com> - 2015-11-16 15:40 +0100
  [RFC PATCH 1/4] ELF: Add platform-specific AT_FLAGS initialisation  support "Maciej W. Rozycki" <macro@imgtec.com> - 2015-11-16 15:40 +0100
  [RFC PATCH 2/4] MIPS: Factor out FP context preemption "Maciej W. Rozycki" <macro@imgtec.com> - 2015-11-16 15:40 +0100

csiph-web