public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low
@ 2004-06-14  7:29 Andrew Morton
  2004-06-21 23:57 ` Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel Peter Chubb
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Andrew Morton @ 2004-06-14  7:29 UTC (permalink / raw)
  To: linux-ia64


This would appear to indicate that CONFIG_PREEMPT isn't working
correctly on ia64.


Begin forwarded message:

Date: Mon, 14 Jun 2004 00:25:22 -0700
From: bugme-daemon@osdl.org
To: bugme-new@lists.osdl.org
Subject: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel


http://bugme.osdl.org/show_bug.cgi?id(85

           Summary: realtime process can't preempt low priority process in
                    kernel
    Kernel Version: 2.6.5
            Status: NEW
          Severity: normal
             Owner: rml@tech9.net
         Submitter: hong.liu@intel.com
                CC: yi.zhu@intel.com


Distribution:
Hardware Environment: 4 Itanium2 1.4G processors-tiger4
Software Environment: gcc-3.3.3
Problem Description:

After turning on the CONFIG_PREEMPT option and recompile the kernel source 
code, the realtime process still can't preempt the low priority process which 
is doing busy loop in kernel. 
The test case does pass both on a pentium 4 PC and a Xeon 2.4G smp machine.

Steps to reproduce:
in the directory of the test case, 
#make
#insmod ./modules/hog.ko
#mknod /dev/hog c 126 0
#./do_hog

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel
  2004-06-14  7:29 Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low Andrew Morton
@ 2004-06-21 23:57 ` Peter Chubb
  2004-06-24  1:48 ` Zhu, Yi
  2004-06-29 18:42 ` David Mosberger
  2 siblings, 0 replies; 4+ messages in thread
From: Peter Chubb @ 2004-06-21 23:57 UTC (permalink / raw)
  To: linux-ia64


Here's a patch to fix OSDL BugMe 2885: IA64 preemption support.

There is one small change in semantics: when returning from a
preemption, the preemption flag will *not* be rechecked.  Otherwise, I
found that it was easy to get into a livelock situation where no
forward progress was made.

Signed-off-by: Peter Chubb <peterc@gelato.unsw.edu.au>

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/06/22 09:08:06+10:00 peterc@gelato.unsw.edu.au 
#   [IA64] [Bug 2885]New: realtime process can't preempt low priority process in kernel 
#   
#   Rearranged code to make it work. There were two problems:
#   
#   	1.  The preempt flag was being tested only if code was 
#               leaving for user space
#   	   (the logic should be: test for RESCHEDULE if we're 
#   	    switching to a kernel thread, test everything
#               if switching to a user thread)
#       
#           2.  The check of the user space flags was being repeated 
#               even if the work had been done.
#   
#    
# 
# arch/ia64/kernel/entry.S
#   2004/06/22 09:07:57+10:00 peterc@gelato.unsw.edu.au +20 -7
#   [IA64] [Bug 2885]New: realtime process can't preempt low priority process in kernel 
#   
#   Rearranged code to make it work. There were two problems:
#   
#   	1.  The preempt flag was being tested only if code was 
#               leaving for user space
#   	   (the logic should be: test for RESCHEDULE if we're 
#   	    switching to a kernel thread, test everything
#               if switching to a user thread)
#       
#           2.  The check of the user space flags was being repeated 
#               even if the work had been done.
#   
#    
# 
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Tue Jun 22 09:22:03 2004
+++ b/arch/ia64/kernel/entry.S	Tue Jun 22 09:22:03 2004
@@ -662,6 +662,11 @@
 	/*
 	 * work.need_resched etc. mustn't get changed by this CPU before it returns to
 	 * user- or fsys-mode, hence we disable interrupts early on:
+	 *
+	 * p6 means to check the threadinfo_flags for work to do, including
+	 * preemption if we're returning to kernel mode.
+	 * This code is reentered at .work_processed_syscall
+	 * with p6 = 0 so we don't recheck
 	 */
 #ifdef CONFIG_PREEMPT
 	rsm psr.i				// disable interrupts
@@ -669,8 +674,6 @@
 (pUStk)	rsm psr.i
 #endif
 	cmp.eq pLvSys,p0=r0,r0			// pLvSys=1: leave from syscall
-(pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
-.work_processed_syscall:
 #ifdef CONFIG_PREEMPT
 (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
@@ -678,8 +681,11 @@
 (pKStk) ld4 r21=[r20]			// r21 <- preempt_count
 (pUStk)	mov r21=0			// r21 <- 0
 	;;
-(p6)	cmp.eq.unc p6,p0=r21,r0		// p6 <- p6 && (r21 = 0)
+	cmp.eq.unc p6,p0=r21,r0		// p6 <- pUStk || (preempt_count = 0)
+#else
+(pUStk) cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
 #endif /* CONFIG_PREEMPT */
+.work_processed_syscall:
 	adds r16=PT(LOADRS)+16,r12
 	adds r17=PT(AR_BSPSTORE)+16,r12
 	adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
@@ -775,6 +781,11 @@
 	/*
 	 * work.need_resched etc. mustn't get changed by this CPU before it returns to
 	 * user- or fsys-mode, hence we disable interrupts early on:
+	 *
+	 * p6 means to check the threadinfo_flags for work to do, including
+	 * preemption if we're returning to kernel mode.
+	 * This code is reentered at .work_processed_kernel
+	 * with p6 = 0 so we don't recheck
 	 */
 #ifdef CONFIG_PREEMPT
 	rsm psr.i				// disable interrupts
@@ -782,18 +793,20 @@
 (pUStk)	rsm psr.i
 #endif
 	cmp.eq p0,pLvSys=r0,r0			// pLvSys=0: leave from kernel
-(pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
 	;;
-.work_processed_kernel:
 #ifdef CONFIG_PREEMPT
 	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
 	.pred.rel.mutex pUStk,pKStk
 (pKStk)	ld4 r21=[r20]			// r21 <- preempt_count
-(pUStk)	mov r21=0			// r21 <- 0
+(pUStk)	mov r21=0
 	;;
-(p6)	cmp.eq.unc p6,p0=r21,r0		// p6 <- p6 && (r21 = 0)
+	cmp.eq p6,p0=r21,r0		// p6 <- pUStk || (preempt_count = 0)
+#else
+(pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
 #endif /* CONFIG_PREEMPT */
+
+.work_processed_kernel:
 	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
 	;;
 (p6)	ld4 r31=[r17]				// load current_thread_info()->flags


-- 
Dr Peter Chubb  http://www.gelato.unsw.edu.au  peterc AT gelato.unsw.edu.au
The technical we do immediately,  the political takes *forever*

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel
  2004-06-14  7:29 Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low Andrew Morton
  2004-06-21 23:57 ` Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel Peter Chubb
@ 2004-06-24  1:48 ` Zhu, Yi
  2004-06-29 18:42 ` David Mosberger
  2 siblings, 0 replies; 4+ messages in thread
From: Zhu, Yi @ 2004-06-24  1:48 UTC (permalink / raw)
  To: linux-ia64

Peter Chubb wrote:
> Here's a patch to fix OSDL BugMe 2885: IA64 preemption support.
> 
> There is one small change in semantics: when returning from a
> preemption, the preemption flag will *not* be rechecked.
> Otherwise, I found that it was easy to get into a livelock
> situation where no forward progress was made.

Thank you Peter, the patch works perfectly.

-yi

> 
> Signed-off-by: Peter Chubb <peterc@gelato.unsw.edu.au>
> 
> # This is a BitKeeper generated diff -Nru style patch. #
> # ChangeSet
> #   2004/06/22 09:08:06+10:00 peterc@gelato.unsw.edu.au
> #   [IA64] [Bug 2885]New: realtime process can't preempt low priority
> process in kernel #
> #   Rearranged code to make it work. There were two problems: #
> #   	1.  The preempt flag was being tested only if code was
> #               leaving for user space
> #   	   (the logic should be: test for RESCHEDULE if we're
> #   	    switching to a kernel thread, test everything
> #               if switching to a user thread)
> #
> #           2.  The check of the user space flags was being repeated
> #               even if the work had been done.
> #
> #
> #
> # arch/ia64/kernel/entry.S
> #   2004/06/22 09:07:57+10:00 peterc@gelato.unsw.edu.au +20 -7
> #   [IA64] [Bug 2885]New: realtime process can't preempt low priority
> process in kernel #
> #   Rearranged code to make it work. There were two problems: #
> #   	1.  The preempt flag was being tested only if code was
> #               leaving for user space
> #   	   (the logic should be: test for RESCHEDULE if we're
> #   	    switching to a kernel thread, test everything
> #               if switching to a user thread)
> #
> #           2.  The check of the user space flags was being repeated
> #               even if the work had been done.
> #
> #
> #
> diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
> --- a/arch/ia64/kernel/entry.S	Tue Jun 22 09:22:03 2004
> +++ b/arch/ia64/kernel/entry.S	Tue Jun 22 09:22:03 2004 @@
-662,6
>  	+662,11 @@ /*
>  	 * work.need_resched etc. mustn't get changed by this
> CPU before it returns to
>  	 * user- or fsys-mode, hence we disable interrupts early on: +
*
> +	 * p6 means to check the threadinfo_flags for work to
> do, including
> +	 * preemption if we're returning to kernel mode.
> +	 * This code is reentered at .work_processed_syscall
> +	 * with p6 = 0 so we don't recheck
>  	 */
>  #ifdef CONFIG_PREEMPT
>  	rsm psr.i				// disable interrupts
> @@ -669,8 +674,6 @@
>  (pUStk)	rsm psr.i
>  #endif
>  	cmp.eq pLvSys,p0=r0,r0			// pLvSys=1:
> leave from syscall
> -(pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
> -.work_processed_syscall:
>  #ifdef CONFIG_PREEMPT
>  (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
>  	;;
> @@ -678,8 +681,11 @@
>  (pKStk) ld4 r21=[r20]			// r21 <- preempt_count
>  (pUStk)	mov r21=0			// r21 <- 0
>  	;;
> -(p6)	cmp.eq.unc p6,p0=r21,r0		// p6 <- p6 && (r21 = 0)
> +	cmp.eq.unc p6,p0=r21,r0		// p6 <- pUStk ||
> (preempt_count = 0)
> +#else
> +(pUStk) cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
>  #endif /* CONFIG_PREEMPT */
> +.work_processed_syscall:
>  	adds r16=PT(LOADRS)+16,r12
>  	adds r17=PT(AR_BSPSTORE)+16,r12
>  	adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
> @@ -775,6 +781,11 @@
>  	/*
>  	 * work.need_resched etc. mustn't get changed by this
> CPU before it returns to
>  	 * user- or fsys-mode, hence we disable interrupts early on: +
*
> +	 * p6 means to check the threadinfo_flags for work to
> do, including
> +	 * preemption if we're returning to kernel mode.
> +	 * This code is reentered at .work_processed_kernel
> +	 * with p6 = 0 so we don't recheck
>  	 */
>  #ifdef CONFIG_PREEMPT
>  	rsm psr.i				// disable interrupts
> @@ -782,18 +793,20 @@
>  (pUStk)	rsm psr.i
>  #endif
>  	cmp.eq p0,pLvSys=r0,r0			// pLvSys=0:
> leave from kernel
> -(pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
>  	;;
> -.work_processed_kernel:
>  #ifdef CONFIG_PREEMPT
>  	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
>  	;;
>  	.pred.rel.mutex pUStk,pKStk
>  (pKStk)	ld4 r21=[r20]			// r21 <- preempt_count
> -(pUStk)	mov r21=0			// r21 <- 0
> +(pUStk)	mov r21=0
>  	;;
> -(p6)	cmp.eq.unc p6,p0=r21,r0		// p6 <- p6 && (r21 = 0)
> +	cmp.eq p6,p0=r21,r0		// p6 <- pUStk ||
> (preempt_count = 0)
> +#else
> +(pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
>  #endif /* CONFIG_PREEMPT */
> +
> +.work_processed_kernel:
>  	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
>  	;;
>  (p6)	ld4 r31=[r17]				// load
> current_thread_info()->flags



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel
  2004-06-14  7:29 Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low Andrew Morton
  2004-06-21 23:57 ` Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel Peter Chubb
  2004-06-24  1:48 ` Zhu, Yi
@ 2004-06-29 18:42 ` David Mosberger
  2 siblings, 0 replies; 4+ messages in thread
From: David Mosberger @ 2004-06-29 18:42 UTC (permalink / raw)
  To: linux-ia64

Peter,

Can you confirm that this patch also works for you?  It's your patch with
the following changes:

 o Consolidate code into a single #ifdef CONFIG_PREEMPT.
 o Replace unconditional "cmp.eq.unc" with "cmp.eq".
 o Cleanup/correct comment.
 o Sync up code in ia64_leave_kernel with ia64_leave_syscall.

Rest should be the same.

Two questions though: first, the code will call notify_resume_user
when returning to kernel-level execution if preempt_count is 0 and
current_thread_info()->need_resched() is 0.  Is this really what you
had in mind?

Second, isn't preempt_count necessarily 0 when returning to
user-level?  If so, it should be possible to simplify the
CONFIG_PREEMPT code a bit more.

Thanks,

	--david

>>>>> On Tue, 22 Jun 2004 09:57:43 +1000, Peter Chubb <peterc@gelato.unsw.edu.au> said:

  Peter> Here's a patch to fix OSDL BugMe 2885: IA64 preemption
  Peter> support.

  Peter> There is one small change in semantics: when returning from a
  Peter> preemption, the preemption flag will *not* be rechecked.
  Peter> Otherwise, I found that it was easy to get into a livelock
  Peter> situation where no forward progress was made.

---------------------------------------------------------------------------
ia64: Fix OSDL BugMe report 2885: realtime process can't preempt low priority process in kernel

Rearranged code to make it work. There were two problems:

 1. The preempt flag was being tested only if code was leaving for
    user space (the logic should be: test for RESCHEDULE if we're
    switching to a kernel thread, test everything if switching to a
    user thread)

 2. The check of the user space flags was being repeated even if the
    work had been done.

There is one small change in semantics: when returning from a
preemption, the preemption flag will *not* be rechecked.  Otherwise, I
found that it was easy to get into a livelock situation where no
forward progress was made.

=== arch/ia64/kernel/entry.S 1.60 vs edited ==--- 1.60/arch/ia64/kernel/entry.S	Wed Jun 16 21:12:18 2004
+++ edited/arch/ia64/kernel/entry.S	Tue Jun 29 11:17:02 2004
@@ -663,25 +663,31 @@
 	PT_REGS_UNWIND_INFO(0)
 	/*
 	 * work.need_resched etc. mustn't get changed by this CPU before it returns to
-	 * user- or fsys-mode, hence we disable interrupts early on:
+	 * user- or fsys-mode, hence we disable interrupts early on.
+	 *
+	 * p6 controls whether current_thread_info()->flags needs to be check for
+	 * extra work.  We always check for extra work when returning to user-level.
+	 * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+	 * is 0.  After extra work processing has been completed, execution
+	 * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+	 * needs to be redone.
 	 */
 #ifdef CONFIG_PREEMPT
 	rsm psr.i				// disable interrupts
-#else
-(pUStk)	rsm psr.i
-#endif
 	cmp.eq pLvSys,p0=r0,r0			// pLvSys=1: leave from syscall
-(pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
-.work_processed_syscall:
-#ifdef CONFIG_PREEMPT
 (pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
 	.pred.rel.mutex pUStk,pKStk
 (pKStk) ld4 r21=[r20]			// r21 <- preempt_count
 (pUStk)	mov r21=0			// r21 <- 0
 	;;
-(p6)	cmp.eq.unc p6,p0=r21,r0		// p6 <- p6 && (r21 = 0)
-#endif /* CONFIG_PREEMPT */
+	cmp.eq p6,p0=r21,r0		// p6 <- pUStk || (preempt_count = 0)
+#else /* !CONFIG_PREEMPT */
+(pUStk)	rsm psr.i
+	cmp.eq pLvSys,p0=r0,r0		// pLvSys=1: leave from syscall
+(pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
+#endif
+.work_processed_syscall:
 	adds r16=PT(LOADRS)+16,r12
 	adds r17=PT(AR_BSPSTORE)+16,r12
 	adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
@@ -776,26 +782,31 @@
 	PT_REGS_UNWIND_INFO(0)
 	/*
 	 * work.need_resched etc. mustn't get changed by this CPU before it returns to
-	 * user- or fsys-mode, hence we disable interrupts early on:
+	 * user- or fsys-mode, hence we disable interrupts early on.
+	 *
+	 * p6 controls whether current_thread_info()->flags needs to be check for
+	 * extra work.  We always check for extra work when returning to user-level.
+	 * With CONFIG_PREEMPT, we also check for extra work when the preempt_count
+	 * is 0.  After extra work processing has been completed, execution
+	 * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check
+	 * needs to be redone.
 	 */
 #ifdef CONFIG_PREEMPT
 	rsm psr.i				// disable interrupts
-#else
-(pUStk)	rsm psr.i
-#endif
 	cmp.eq p0,pLvSys=r0,r0			// pLvSys=0: leave from kernel
-(pUStk)	cmp.eq.unc p6,p0=r0,r0			// p6 <- pUStk
-	;;
-.work_processed_kernel:
-#ifdef CONFIG_PREEMPT
-	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+(pKStk)	adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
 	;;
 	.pred.rel.mutex pUStk,pKStk
 (pKStk)	ld4 r21=[r20]			// r21 <- preempt_count
 (pUStk)	mov r21=0			// r21 <- 0
 	;;
-(p6)	cmp.eq.unc p6,p0=r21,r0		// p6 <- p6 && (r21 = 0)
-#endif /* CONFIG_PREEMPT */
+	cmp.eq p6,p0=r21,r0		// p6 <- pUStk || (preempt_count = 0)
+#else
+(pUStk)	rsm psr.i
+	cmp.eq p0,pLvSys=r0,r0		// pLvSys=0: leave from kernel
+(pUStk)	cmp.eq.unc p6,p0=r0,r0		// p6 <- pUStk
+#endif
+.work_processed_kernel:
 	adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
 	;;
 (p6)	ld4 r31=[r17]				// load current_thread_info()->flags

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2004-06-29 18:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-14  7:29 Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low Andrew Morton
2004-06-21 23:57 ` Fw: [Bugme-new] [Bug 2885] New: realtime process can't preempt low priority process in kernel Peter Chubb
2004-06-24  1:48 ` Zhu, Yi
2004-06-29 18:42 ` David Mosberger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox