Skip to contentSkip to conversation

sched: Remove finish_arch_switch()

RFC PATCH In review Peter Zijlstra 5 participants 14 messages Jul 29, 2015 – Aug 4, 2015

Subsystems (4)
lore
Share & tools
lore

Peter Zijlstra

author maintainer
#0 lore raw

cover sched: Remove finish_arch_switch()

Hi,

There were only a few architectures utilizing finish_arch_switch() and it looks like they can all do without.

This means we can remove finish_arch_switch(); partly to make up for introducing finish_arch_post_lock_switch(), partly to reduce the number of arch hooks to consider.

Much thanks to Ralf, Will and Chris for helping out with this!

author maintainer
#1 lore raw

RFC PATCH 1/7 arm: Remove finish_arch_switch

From: Will Deacon <[email protected]>

Fold finish_arch_switch() into switch_to().

---
 arch/arm/include/asm/switch_to.h |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/arm/include/asm/switch_to.h +4 -1
@@ -10,7 +10,9 @@
  * CPU.
  */
 #if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) && defined(CONFIG_CPU_V7)
-#define finish_arch_switch(prev)	dsb(ish)
+#define __complete_pending_tlbi()	dsb(ish)
+#else
+#define __complete_pending_tlbi()
 #endif
 
 /*
@@ -22,6 +24,7 @@ extern struct task_struct *__switch_to(s
 
 #define switch_to(prev,next,last)					\
 do {									\
+	__complete_pending_tlbi();					\
 	last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));	\
 } while (0)
 
#3 lore raw

Re: [RFC][PATCH 1/7] arm: Remove finish_arch_switch

Quoted 5 lines · Ingo Molnar
Quoted 2 lines · Peter Zijlstra

From: Will Deacon <[email protected]>

Quoted 7 lines
Quoted 3 lines

Fold finish_arch_switch() into switch_to().

Will, can I add your:

I've already merged this patch as Will had submitted it to me for merging. Peter's S-o-b should be an acked-by though in that case...

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#4 lore raw

Re: [RFC][PATCH 1/7] arm: Remove finish_arch_switch

Quoted 8 lines · Russell King - ARM Linux
Quoted 7 lines · Ingo Molnar
Quoted 4 lines · Peter Zijlstra

From: Will Deacon <[email protected]>

Fold finish_arch_switch() into switch_to().

Quoted 7 lines
Quoted 5 lines
Quoted 1 line

Will, can I add your:

I've already merged this patch as Will had submitted it to me for merging.

Yup. Peter said he would pick up what's left after the merge window, so arch maintainers can pick up the patches now for 4.3 (I think Ralf had picked up the mips part already).

Quoted 1 line

Peter's S-o-b should be an acked-by though in that case...

I guess, although he turned my diff into a patch (i.e. wrote the commit message) and posted it, so I just left it there. Not fussed either way.

Will

author maintainer
#5 lore raw

RFC PATCH 2/7 MIPS: Get rid of finish_arch_switch().

In reply to Peter Zijlstra

From: Ralf Baechle <[email protected]>

MIPS was using finish_arch_switch() as a hook to restore and initialize CPU context for all threads, even newly created kernel and user threads. This is however entirely solvable within switch_to() so get rid of finish_arch_switch() which is in the way of scheduler cleanups.

---
 arch/mips/include/asm/switch_to.h | 48 +++++++++++++++++++--------------------
 1 file changed, 23 insertions(+), 25 deletions(-)
arch/mips/include/asm/switch_to.h +23 -25
index 7163cd7..9733cd0 100644
@@ -83,45 +83,43 @@ do {	if (cpu_has_rw_llb) {						\
 	}								\
 } while (0)
 
+/*
+ * For newly created kernel threads switch_to() will return to
+ * ret_from_kernel_thread, newly created user threads to ret_from_fork.
+ * That is, everything following resume() will be skipped for new threads.
+ * So everything that matters to new threads should be placed before resume().
+ */
 #define switch_to(prev, next, last)					\
 do {									\
-	u32 __c0_stat;							\
 	s32 __fpsave = FP_SAVE_NONE;					\
 	__mips_mt_fpaff_switch_to(prev);				\
-	if (cpu_has_dsp)						\
+	if (cpu_has_dsp) {						\
 		__save_dsp(prev);					\
-	if (cop2_present && (KSTK_STATUS(prev) & ST0_CU2)) {		\
-		if (cop2_lazy_restore)					\
-			KSTK_STATUS(prev) &= ~ST0_CU2;			\
-		__c0_stat = read_c0_status();				\
-		write_c0_status(__c0_stat | ST0_CU2);			\
-		cop2_save(prev);					\
-		write_c0_status(__c0_stat & ~ST0_CU2);			\
+		__restore_dsp(next);					\
+	}								\
+	if (cop2_present) {						\
+		set_c0_status(ST0_CU2);					\
+		if ((KSTK_STATUS(prev) & ST0_CU2)) {			\
+			if (cop2_lazy_restore)				\
+				KSTK_STATUS(prev) &= ~ST0_CU2;		\
+			cop2_save(prev);				\
+		}							\
+		if (KSTK_STATUS(next) & ST0_CU2 &&			\
+		    !cop2_lazy_restore) {				\
+			cop2_restore(next);				\
+		}							\
+		clear_c0_status(ST0_CU2);				\
 	}								\
 	__clear_software_ll_bit();					\
 	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU))		\
 		__fpsave = FP_SAVE_SCALAR;				\
 	if (test_and_clear_tsk_thread_flag(prev, TIF_USEDMSA))		\
 		__fpsave = FP_SAVE_VECTOR;				\
-	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
-} while (0)
-
-#define finish_arch_switch(prev)					\
-do {									\
-	u32 __c0_stat;							\
-	if (cop2_present && !cop2_lazy_restore &&			\
-			(KSTK_STATUS(current) & ST0_CU2)) {		\
-		__c0_stat = read_c0_status();				\
-		write_c0_status(__c0_stat | ST0_CU2);			\
-		cop2_restore(current);					\
-		write_c0_status(__c0_stat & ~ST0_CU2);			\
-	}								\
-	if (cpu_has_dsp)						\
-		__restore_dsp(current);					\
 	if (cpu_has_userlocal)						\
-		write_c0_userlocal(current_thread_info()->tp_value);	\
+		write_c0_userlocal(task_thread_info(next)->tp_value);	\
 	__restore_watch();						\
 	disable_msa();							\
+	(last) = resume(prev, next, task_thread_info(next), __fpsave);	\
 } while (0)
 
 #endif /* _ASM_SWITCH_TO_H */
Signature · 1 line
cgit v0.11.2
author maintainer
#6 lore raw

RFC PATCH 3/7 avr32: Remove finish_arch_switch()

In reply to Peter Zijlstra

Fold the tracing hook into switch_to() in order to remove finish_arch_switch().

Cc Hans-Christian Egtvedt <[email protected]>
---
 arch/avr32/include/asm/switch_to.h |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
arch/avr32/include/asm/switch_to.h +5 -2
@@ -15,11 +15,13 @@
  */
 #ifdef CONFIG_OWNERSHIP_TRACE
 #include <asm/ocd.h>
-#define finish_arch_switch(prev)			\
+#define ocd_switch(prev, next)				\
 	do {						\
 		ocd_write(PID, prev->pid);		\
-		ocd_write(PID, current->pid);		\
+		ocd_write(PID, next->pid);		\
 	} while(0)
+#else
+#define ocd_switch(prev, next)
 #endif
 
 /*
@@ -38,6 +40,7 @@ extern struct task_struct *__switch_to(s
 				       struct cpu_context *);
 #define switch_to(prev, next, last)					\
 	do {								\
+		ocd_switch(prev, next);					\
 		last = __switch_to(prev, &prev->thread.cpu_context + 1,	\
 				   &next->thread.cpu_context);		\
 	} while (0)
Acked-by on v1 3/7
#7 lore raw

Re: [RFC][PATCH 3/7] avr32: Remove finish_arch_switch()

Quoted 2 lines · Peter Zijlstra

Fold the tracing hook into switch_to() in order to remove finish_arch_switch().

AFAICT this should work, I do not have a nexus debugger to verify behavior.

Quoted 2 lines
Cc Hans-Christian Egtvedt <[email protected]>
Quoted 30 lines
---
 arch/avr32/include/asm/switch_to.h |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
arch/avr32/include/asm/switch_to.h +5 -2
@@ -15,11 +15,13 @@
  */
 #ifdef CONFIG_OWNERSHIP_TRACE
 #include <asm/ocd.h>
-#define finish_arch_switch(prev)			\
+#define ocd_switch(prev, next)				\
 	do {						\
 		ocd_write(PID, prev->pid);		\
-		ocd_write(PID, current->pid);		\
+		ocd_write(PID, next->pid);		\
 	} while(0)
+#else
+#define ocd_switch(prev, next)
 #endif
 
 /*
@@ -38,6 +40,7 @@ extern struct task_struct *__switch_to(s
 				       struct cpu_context *);
 #define switch_to(prev, next, last)					\
 	do {								\
+		ocd_switch(prev, next);					\
 		last = __switch_to(prev, &prev->thread.cpu_context + 1,	\
 				   &next->thread.cpu_context);		\
 	} while (0)
Signature · 2 lines
mvh
Hans-Christian Egtvedt
author maintainer
#8 lore raw

RFC PATCH 4/7 score: Remove finish_arch_switch()

In reply to Peter Zijlstra

An empty implementation, make it go away.

---
 arch/score/include/asm/switch_to.h |    2 --
 1 file changed, 2 deletions(-)
arch/score/include/asm/switch_to.h +0 -2
@@ -8,6 +8,4 @@ do {								\
 	(last) = resume(prev, next, task_thread_info(next));	\
 } while (0)
 
-#define finish_arch_switch(prev)	do {} while (0)
-
 #endif /* _ASM_SCORE_SWITCH_TO_H */
author maintainer
#9 lore raw

RFC PATCH 5/7 sh: Fold finish_arch_switch() into switch_to()

In reply to Peter Zijlstra

The code looks buggy; why would we be restoring the previous task's DSP state after we've switched to the next task?

Fix that and put the restore in switch_to(), removing the need for finish_arch_switch().

---
 arch/sh/include/asm/switch_to_32.h |    8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)
arch/sh/include/asm/switch_to_32.h +2 -6
@@ -78,6 +78,8 @@ do {								\
 								\
 	if (is_dsp_enabled(prev))				\
 		__save_dsp(prev);				\
+	if (is_dsp_enabled(next))				\
+		__restore_dsp(next);				\
 								\
 	__ts1 = (u32 *)&prev->thread.sp;			\
 	__ts2 = (u32 *)&prev->thread.pc;			\
@@ -125,10 +127,4 @@ do {								\
 	last = __last;						\
 } while (0)
 
-#define finish_arch_switch(prev)				\
-do {								\
-	if (is_dsp_enabled(prev))				\
-		__restore_dsp(prev);				\
-} while (0)
-
 #endif /* __ASM_SH_SWITCH_TO_32_H */
author maintainer
#10 lore raw

RFC PATCH 6/7 Remove finish_arch_switch

In reply to Peter Zijlstra

From: Chris Metcalf <[email protected]>

Move the simulator bits into switch_to() and use finish_arch_post_lock_switch() for the homecache migration bits.

---
 arch/tile/include/asm/switch_to.h |   10 +++-------
 arch/tile/kernel/process.c        |   17 +++++++++++++++--
 2 files changed, 18 insertions(+), 9 deletions(-)
arch/tile/include/asm/switch_to.h +3 -7
@@ -53,15 +53,11 @@ extern unsigned long get_switch_to_pc(vo
  * Kernel threads can check to see if they need to migrate their
  * stack whenever they return from a context switch; for user
  * threads, we defer until they are returning to user-space.
+ * We defer homecache migration until the runqueue lock is released.
  */
-#define finish_arch_switch(prev) do {                                     \
-	if (unlikely((prev)->state == TASK_DEAD))                         \
-		__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT |       \
-			((prev)->pid << _SIM_CONTROL_OPERATOR_BITS));     \
-	__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH |             \
-		(current->pid << _SIM_CONTROL_OPERATOR_BITS));            \
+#define finish_arch_post_lock_switch() do {                               \
 	if (current->mm == NULL && !kstack_hash &&                        \
-	    current_thread_info()->homecache_cpu != smp_processor_id())   \
+	    current_thread_info()->homecache_cpu != raw_smp_processor_id()) \
 		homecache_migrate_kthread();                              \
 } while (0)
 
arch/tile/kernel/process.c +15 -2
@@ -448,11 +448,24 @@ struct task_struct *__sched _switch_to(s
 
 	/*
 	 * Switch kernel SP, PC, and callee-saved registers.
+	 * Pass the value to use for SYSTEM_SAVE_K_0 when we reset our sp.
+	 * Once we return from this function we will have changed stacks
+	 * and be running with current == next.
+	 */
+	__switch_to(prev, next, next_current_ksp0(next));
+
+	/* Notify the simulator of task switch and task exit. */
+	if (unlikely(prev->state == TASK_DEAD))
+		__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_EXIT |
+			     (prev->pid << _SIM_CONTROL_OPERATOR_BITS));
+	__insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_OS_SWITCH |
+		(next->pid << _SIM_CONTROL_OPERATOR_BITS));
+
+	/*
 	 * In the context of the new task, return the old task pointer
 	 * (i.e. the task that actually called __switch_to).
-	 * Pass the value to use for SYSTEM_SAVE_K_0 when we reset our sp.
 	 */
-	return __switch_to(prev, next, next_current_ksp0(next));
+	return prev;
 }
 
 /*
author maintainer
#11 lore raw

RFC PATCH 7/7 sched: Remove finish_arch_switch()

In reply to Peter Zijlstra

One less arch hook..

---
 kernel/sched/core.c  |    1 -
 kernel/sched/sched.h |    3 ---
 2 files changed, 4 deletions(-)
kernel/sched/core.c +0 -1
@@ -2468,7 +2468,6 @@ static struct rq *finish_task_switch(str
 	 */
 	prev_state = prev->state;
 	vtime_task_switch(prev);
-	finish_arch_switch(prev);
 	perf_event_task_sched_in(prev, current);
 	finish_lock_switch(rq, prev);
 	finish_arch_post_lock_switch();
kernel/sched/sched.h +0 -3
@@ -1055,9 +1055,6 @@ static inline int task_on_rq_migrating(s
 #ifndef prepare_arch_switch
 # define prepare_arch_switch(next)	do { } while (0)
 #endif
-#ifndef finish_arch_switch
-# define finish_arch_switch(prev)	do { } while (0)
-#endif
 #ifndef finish_arch_post_lock_switch
 # define finish_arch_post_lock_switch()	do { } while (0)
 #endif
author maintainer
#12 lore raw
In reply to Peter Zijlstra
Quoted 10 lines · Peter Zijlstra

Hi,

There were only a few architectures utilizing finish_arch_switch() and it looks like they can all do without.

This means we can remove finish_arch_switch(); partly to make up for introducing finish_arch_post_lock_switch(), partly to reduce the number of arch hooks to consider.

Much thanks to Ralf, Will and Chris for helping out with this!

So the mips patch is already in Ralf's mips-next tree, which means I have to wait for that to his Linus' tree before I can commit the last patch in this series.

It also means that all the other patches can go through their respective arch tree.

So anybody who feels so inclined, go ahead, I'll check after the next merge window and commit everything that's left -- unless there's objections of course :-)

#13 lore raw
Quoted 16 lines · Peter Zijlstra
Quoted 10 lines · Peter Zijlstra

Hi,

There were only a few architectures utilizing finish_arch_switch() and it looks like they can all do without.

This means we can remove finish_arch_switch(); partly to make up for introducing finish_arch_post_lock_switch(), partly to reduce the number of arch hooks to consider.

Much thanks to Ralf, Will and Chris for helping out with this!

So the mips patch is already in Ralf's mips-next tree, which means I have to wait for that to his Linus' tree before I can commit the last patch in this series.

Quoted 6 lines

It also means that all the other patches can go through their respective arch tree.

So anybody who feels so inclined, go ahead, I'll check after the next merge window and commit everything that's left -- unless there's objections of course :-)

Sounds sensible to me!

Thanks,

Ingo