linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] 2.5.39 s390 (13/26): preemption.
@ 2002-09-30 12:56 Martin Schwidefsky
  0 siblings, 0 replies; only message in thread
From: Martin Schwidefsky @ 2002-09-30 12:56 UTC (permalink / raw)
  To: linux-kernel, torvalds

Add support for kernel preemption on s390/s390x.

diff -urN linux-2.5.39/arch/s390/config.in linux-2.5.39-s390/arch/s390/config.in
--- linux-2.5.39/arch/s390/config.in	Mon Sep 30 13:25:48 2002
+++ linux-2.5.39-s390/arch/s390/config.in	Mon Sep 30 13:32:33 2002
@@ -30,6 +30,7 @@
 fi
 
 comment 'Misc'
+bool 'Preemptible Kernel' CONFIG_PREEMPT
 bool 'Builtin IPL record support' CONFIG_IPL
 if [ "$CONFIG_IPL" = "y" ]; then
   choice 'IPL method generated into head.S' \
diff -urN linux-2.5.39/arch/s390/defconfig linux-2.5.39-s390/arch/s390/defconfig
--- linux-2.5.39/arch/s390/defconfig	Mon Sep 30 13:25:48 2002
+++ linux-2.5.39-s390/arch/s390/defconfig	Mon Sep 30 13:32:33 2002
@@ -50,6 +50,7 @@
 #
 # Misc
 #
+# CONFIG_PREEMPT is not set
 CONFIG_IPL=y
 # CONFIG_IPL_TAPE is not set
 CONFIG_IPL_VM=y
diff -urN linux-2.5.39/arch/s390/kernel/entry.S linux-2.5.39-s390/arch/s390/kernel/entry.S
--- linux-2.5.39/arch/s390/kernel/entry.S	Mon Sep 30 13:25:30 2002
+++ linux-2.5.39-s390/arch/s390/kernel/entry.S	Mon Sep 30 13:32:33 2002
@@ -49,7 +49,7 @@
 SP_TRAP      =  (SP_ORIG_R2+GPR_SIZE)
 SP_SIZE      =  (SP_TRAP+4)
 
-_TIF_WORK_MASK = (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
 /*
  * Base Address of this Module --- saved in __LC_ENTRY_BASE
@@ -199,33 +199,44 @@
         RESTORE_ALL 1
 
 #
-# One of the work bits _TIF_NOTIFY_RESUME, _TIF_SIGPENDING or
-# _TIF_NEED_RESCHED is on. Find out which one.
+# recheck if there is more work to do
+#
+sysc_work_loop:
+	stnsm   24(%r15),0xfc     # disable I/O and ext. interrupts
+        GET_THREAD_INFO           # load pointer to task_struct to R9
+	tm	__TI_flags+3(%r9),_TIF_WORK_MASK
+	bz	BASED(sysc_leave)      # there is no work to do
+#
+# One of the work bits is on. Find out which one.
+# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
 #
 sysc_work:
-        tm      SP_PSW+1(%r15),0x01 # returning to user ?
-        bno     BASED(sysc_leave) # no-> skip resched & signal
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(sysc_reschedule)
-	# add a test for TIF_NOTIFY_RESUME here when it is used.
-	# _TIF_SIGPENDING is the only flag left
-#
-# call do_signal before return
-#
-sysc_signal_return:     
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-        sr      %r3,%r3           # clear *oldset
-        l       %r1,BASED(.Ldo_signal)
-	la      %r14,BASED(sysc_return)
-        br      %r1               # return point is sysc_return
+	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
+	bo	BASED(sysc_sigpending)
+	b	BASED(sysc_leave)
 
 #
-# call schedule with sysc_return as return-address
-#
+# _TIF_NEED_RESCHED is set, call schedule
+#	
 sysc_reschedule:        
+        stosm   24(%r15),0x03          # reenable interrupts
         l       %r1,BASED(.Lschedule)
-	la      %r14,BASED(sysc_return)
-        br      %r1               # call scheduler, return to sysc_return
+	la      %r14,BASED(sysc_work_loop)
+	br      %r1		       # call scheduler
+
+#
+# _TIF_SIGPENDING is set, call do_signal
+#
+sysc_sigpending:     
+        stosm   24(%r15),0x03          # reenable interrupts
+        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+        sr      %r3,%r3                # clear *oldset
+        l       %r1,BASED(.Ldo_signal)
+	basr	%r14,%r1               # call do_signal
+        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+	b	BASED(sysc_leave)      # out of here, do NOT recheck
 
 #
 # call trace before and after sys_call
@@ -258,9 +269,7 @@
         basr    %r13,0
         l       %r13,.Lentry_base-.(%r13)  # setup base pointer to &entry_base
         GET_THREAD_INFO           # load pointer to task_struct to R9
-        sr      %r0,%r0           # child returns 0
-        st      %r0,SP_R2(%r15)   # store return value (change R2 on stack)
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
         l       %r1,BASED(.Lschedtail)
 	la      %r14,BASED(sysc_return)
         br      %r1               # call schedule_tail, return to sysc_return
@@ -616,13 +625,15 @@
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
         bnz     BASED(pgm_per)           # got per exception -> special case
 	SAVE_ALL __LC_PGM_OLD_PSW,1
+	la	%r8,0x7f
+        l       %r3,__LC_PGM_ILC         # load program interruption code
         l       %r7,BASED(.Ljump_table)
-        lh      %r8,__LC_PGM_INT_CODE
+	nr	%r8,%r3
         sll     %r8,2
 	GET_THREAD_INFO
+        stosm   24(%r15),0x03            # reenable interrupts
         l       %r7,0(%r8,%r7)		 # load address of handler routine
         la      %r2,SP_PTREGS(%r15)	 # address of register-save area
-        l       %r3,__LC_PGM_ILC         # load program interruption code
 	la      %r14,BASED(sysc_return)
 	br      %r7			 # branch to interrupt-handler
 
@@ -647,6 +658,7 @@
 	GET_THREAD_INFO
 	la	%r4,0x7f
 	l	%r3,__LC_PGM_ILC	 # load program interruption code
+        stosm   24(%r15),0x03            # reenable interrupts
         nr      %r4,%r3                  # clear per-event-bit and ilc
         be      BASED(pgm_per_only)      # only per or per+check ?
         l       %r1,BASED(.Ljump_table)
@@ -666,9 +678,9 @@
 pgm_svcper:
 	SAVE_ALL __LC_SVC_OLD_PSW,1
         GET_THREAD_INFO           # load pointer to task_struct to R9
+        stosm   24(%r15),0x03     # reenable interrupts
 	lh	%r8,0x8a	  # get svc number from lowcore
         sll     %r8,2
-        stosm   24(%r15),0x03     # reenable interrupts
         l       %r8,sys_call_table-entry_base(%r8,%r13) # get system call addr.
 	tm	__TI_flags+3(%r9),_TIF_SYSCALL_TRACE
         bo      BASED(pgm_tracesys)
@@ -732,59 +744,81 @@
         basr    %r14,%r1          # branch to standard irq handler
 
 io_return:
-#	
-# check, if bottom-half has to be done
-#
-        l       %r1,__TI_cpu(%r9)
-        sll     %r1,L1_CACHE_SHIFT
-        al      %r1,BASED(.Lirq_stat)  # get address of irq_stat
-        icm     %r0,15,0(%r1)          # test irq_stat[#cpu].__softirq_pending
-        bnz     BASED(io_handle_bottom_half)
-io_return_bh:
+        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+#ifdef CONFIG_PREEMPT
+	bno     BASED(io_preempt)      # no -> check for preemptive scheduling
+#else
+        bno     BASED(io_leave)        # no-> skip resched & signal
+#endif
 	tm	__TI_flags+3(%r9),_TIF_WORK_MASK
 	bnz	BASED(io_work)         # there is work to do (signals etc.)
 io_leave:
-        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
         RESTORE_ALL 0
 
+#ifdef CONFIG_PREEMPT
+io_preempt:
+	icm	%r0,15,__TI_precount(%r9)
+	bnz     BASED(io_leave)
+io_resume_loop:
+	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
+	bno	BASED(io_leave)
+	mvc     __TI_precount(4,%r9),.Lc_pactive
+	# hmpf, we are on the async. stack but to call schedule
+	# we have to move the interrupt frame to the process stack
+	l	%r1,SP_R15(%r15)
+	s	%r1,BASED(.Lc_spsize)
+	n	%r1,BASED(.Lc0xfffffff8)
+	mvc	SP_PTREGS(SP_SIZE-SP_PTREGS,%r1),SP_PTREGS(%r15)
+        xc      0(4,%r1),0(%r1)        # clear back chain
+	lr	%r15,%r1
+        stosm   24(%r15),0x03          # reenable interrupts
+        l       %r1,BASED(.Lschedule)
+	basr	%r14,%r1	       # call schedule
+        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        GET_THREAD_INFO                # load pointer to task_struct to R9
+	xc      __TI_precount(4,%r9),__TI_precount(%r9)
+	b	BASED(io_resume_loop)
+#endif
+
 #
-# call do_softirq
+# recheck if there is more work to do
 #
-io_handle_bottom_half:
-        l       %r1,BASED(.Ldo_softirq)
-        la      %r14,BASED(io_return_bh)
-        br      %r1               # call do_softirq
-
+io_work_loop:
+        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+        GET_THREAD_INFO                # load pointer to task_struct to R9
+	tm	__TI_flags+3(%r9),_TIF_WORK_MASK
+	bz	BASED(io_leave)        # there is no work to do
 #
-# One of the work bits _TIF_NOTIFY_RESUME, _TIF_SIGPENDING or
-# _TIF_NEED_RESCHED is on. Find out which one.
+# One of the work bits is on. Find out which one.
+# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
 #
 io_work:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
-        bno     BASED(io_leave)        # no-> skip resched & signal
-        stosm   24(%r15),0x03          # reenable interrupts
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(io_reschedule)
-	# add a test for TIF_NOTIFY_RESUME here when it is used.
-	# _TIF_SIGPENDING is the only flag left
+	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
+	bo	BASED(io_sigpending)
+	b	BASED(io_leave)
 
 #
-# call do_signal before return
-#
-io_signal_return:     
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-        sr      %r3,%r3           # clear *oldset
-        l       %r1,BASED(.Ldo_signal)
-	la      %r14,BASED(io_leave)
-        br      %r1               # return point is io_leave
+# _TIF_NEED_RESCHED is set, call schedule
+#	
+io_reschedule:        
+        stosm   24(%r15),0x03          # reenable interrupts
+        l       %r1,BASED(.Lschedule)
+	la      %r14,BASED(io_work_loop)
+	br      %r1		       # call scheduler
 
 #
-# call schedule with io_return as return-address
+# _TIF_SIGPENDING is set, call do_signal
 #
-io_reschedule:        
-        l       %r1,BASED(.Lschedule)
-	la      %r14,BASED(io_return)
-        br      %r1               # call scheduler, return to io_return
+io_sigpending:     
+        stosm   24(%r15),0x03          # reenable interrupts
+        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+        sr      %r3,%r3                # clear *oldset
+        l       %r1,BASED(.Ldo_signal)
+	basr    %r14,%r1	       # call do_signal
+        stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
+	b	BASED(io_leave)        # out of here, do NOT recheck
 
 /*
  * External interrupt handler routine
@@ -865,19 +899,12 @@
                .align 4
 .Lc0xfffffff8: .long  -8           # to align stack pointer to 8
 .Lc0xffffe000: .long  -8192        # to round stack pointer to &task_struct
-.Lc8191:       .long  8191
 .Lc_spsize:    .long  SP_SIZE
 .Lc_overhead:  .long  STACK_FRAME_OVERHEAD
 .Lc_ac:        .long  0,0,1
 .Lc_ENOSYS:    .long  -ENOSYS
-.Lc4:          .long  4
-.Lc20:         .long  20
-.Lc0x1202:     .long  0x1202
-.Lc0x1004:     .long  0x1004
-.Lc0x2401:     .long  0x2401
-.Lc0x4000:     .long  0x4000
+.Lc_pactive:   .long  PREEMPT_ACTIVE
 .Lc0xff:       .long  0xff
-.Lc128:        .long  128
 .Lc256:        .long  256
 
 /*
@@ -890,7 +917,6 @@
 .Lentry_base:  .long  entry_base
 .Lext_hash:    .long  ext_int_hash
 .Lhandle_per:  .long  handle_per_exception
-.Lirq_stat:    .long  irq_stat
 .Ljump_table:  .long  pgm_check_table
 .Lschedule:    .long  schedule
 .Lclone:       .long  sys_clone
@@ -904,7 +930,7 @@
 .Lsigaltstack: .long  sys_sigaltstack
 .Ltrace:       .long  syscall_trace
 .Lvfork:       .long  sys_vfork
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
 .Lschedtail:   .long  schedule_tail
 #endif
 
diff -urN linux-2.5.39/arch/s390x/config.in linux-2.5.39-s390/arch/s390x/config.in
--- linux-2.5.39/arch/s390x/config.in	Mon Sep 30 13:25:48 2002
+++ linux-2.5.39-s390/arch/s390x/config.in	Mon Sep 30 13:32:33 2002
@@ -33,6 +33,7 @@
 fi
 
 comment 'Misc'
+bool 'Preemptible Kernel' CONFIG_PREEMPT
 bool 'Builtin IPL record support' CONFIG_IPL
 if [ "$CONFIG_IPL" = "y" ]; then
   choice 'IPL method generated into head.S' \
diff -urN linux-2.5.39/arch/s390x/defconfig linux-2.5.39-s390/arch/s390x/defconfig
--- linux-2.5.39/arch/s390x/defconfig	Mon Sep 30 13:25:48 2002
+++ linux-2.5.39-s390/arch/s390x/defconfig	Mon Sep 30 13:32:33 2002
@@ -51,6 +51,7 @@
 #
 # Misc
 #
+# CONFIG_PREEMPT is not set
 CONFIG_IPL=y
 # CONFIG_IPL_TAPE is not set
 CONFIG_IPL_VM=y
diff -urN linux-2.5.39/arch/s390x/kernel/entry.S linux-2.5.39-s390/arch/s390x/kernel/entry.S
--- linux-2.5.39/arch/s390x/kernel/entry.S	Mon Sep 30 13:25:30 2002
+++ linux-2.5.39-s390/arch/s390x/kernel/entry.S	Mon Sep 30 13:32:33 2002
@@ -49,7 +49,7 @@
 SP_TRAP      =  (SP_ORIG_R2+GPR_SIZE)
 SP_SIZE      =  (SP_TRAP+4)
 
-_TIF_WORK_MASK = (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
 /*
  * Register usage in interrupt handlers:
@@ -185,32 +185,42 @@
         RESTORE_ALL 1
 
 #
-# One of the work bits _TIF_NOTIFY_RESUME, _TIF_SIGPENDING or
-# _TIF_NEED_RESCHED is on. Find out which one.
+# recheck if there is more work to do
+#
+sysc_work_loop:
+	stnsm   48(%r15),0xfc     # disable I/O and ext. interrupts
+        GET_THREAD_INFO           # load pointer to task_struct to R9
+	tm	__TI_flags+7(%r9),_TIF_WORK_MASK
+	jz	sysc_leave        # there is no work to do
+#
+# One of the work bits is on. Find out which one.
+# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
 #
 sysc_work:
-        tm      SP_PSW+1(%r15),0x01 # returning to user ?
-        jno     sysc_leave        # no-> skip resched & signal
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	sysc_reschedule
-	# add a test for TIF_NOTIFY_RESUME here when it is used.
-	# _TIF_SIGPENDING is the only flag left
+	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
+	jo	sysc_sigpending
+	j	sysc_leave
 
 #
-# call do_signal before return
-#
-sysc_signal_return:     
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-        sgr     %r3,%r3             # clear *oldset
-	larl    %r14,sysc_return
-	jg      do_signal           # return point is sysc_return
+# _TIF_NEED_RESCHED is set, call schedule
+#	
+sysc_reschedule:        
+	stosm   48(%r15),0x03     # reenable interrupts
+	larl    %r14,sysc_work_loop
+        jg      schedule            # return point is sysc_return
 
 #
-# call schedule with sysc_return as return-address
+# _TIF_SIGPENDING is set, call do_signal
 #
-sysc_reschedule:        
-	larl    %r14,sysc_return
-        jg      schedule            # return point is sysc_return
+sysc_sigpending:     
+	stosm   48(%r15),0x03     # reenable interrupts
+        la      %r2,SP_PTREGS(%r15) # load pt_regs
+        sgr     %r3,%r3           # clear *oldset
+	brasl	%r14,do_signal    # call do_signal
+	stnsm   48(%r15),0xfc     # disable I/O and ext. interrupts
+	j	sysc_leave        # out of here, do NOT recheck
 
 #
 # call syscall_trace before and after system call
@@ -242,8 +252,7 @@
         .globl  ret_from_fork
 ret_from_fork:  
         GET_THREAD_INFO           # load pointer to task_struct to R9
-	xc      SP_R2(8,%r15),SP_R2(%r15) # child returns 0
-#ifdef CONFIG_SMP
+#if CONFIG_SMP || CONFIG_PREEMPT
 	larl    %r14,sysc_return
         jg      schedule_tail     # return to sysc_return
 #else
@@ -551,8 +560,8 @@
         .long  SYSCALL(sys_rt_sigtimedwait,sys32_rt_sigtimedwait_wrapper)
         .long  SYSCALL(sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
         .long  SYSCALL(sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
-        .long  SYSCALL(sys_pread64,sys32_pread_wrapper)           /* 180 */
-        .long  SYSCALL(sys_pwrite64,sys32_pwrite_wrapper)
+        .long  SYSCALL(sys_pread64,sys32_pread64_wrapper)           /* 180 */
+        .long  SYSCALL(sys_pwrite64,sys32_pwrite64_wrapper)
         .long  SYSCALL(sys_ni_syscall,sys32_chown16_wrapper)    /* old chown16 syscall */
         .long  SYSCALL(sys_getcwd,sys32_getcwd_wrapper)
         .long  SYSCALL(sys_capget,sys32_capget_wrapper)
@@ -646,13 +655,15 @@
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
         jnz     pgm_per                  # got per exception -> special case
 	SAVE_ALL __LC_PGM_OLD_PSW,1
-	llgh    %r8,__LC_PGM_INT_CODE
+	lghi	%r8,0x7f
+	lgf     %r3,__LC_PGM_ILC	 # load program interruption code
+	ngr	%r8,%r3
         sll     %r8,3
 	GET_THREAD_INFO
+	stosm   48(%r15),0x03            # reenable interrupts
         larl    %r1,pgm_check_table
         lg      %r1,0(%r8,%r1)		 # load address of handler routine
         la      %r2,SP_PTREGS(%r15)	 # address of register-save area
-	lgf     %r3,__LC_PGM_ILC	 # load program interruption code
 	larl	%r14,sysc_return
         br      %r1			 # branch to interrupt-handler
 
@@ -676,6 +687,7 @@
 	GET_THREAD_INFO
 	lghi    %r4,0x7f
 	lgf     %r3,__LC_PGM_ILC	 # load program interruption code
+	stosm   48(%r15),0x03            # reenable interrupts
         nr      %r4,%r3			 # clear per-event-bit and ilc
         je      pgm_per_only		 # only per of per+check ?
         sll     %r4,3
@@ -759,57 +771,79 @@
 	brasl   %r14,do_IRQ            # call standard irq handler
 
 io_return:
-#
-# check, if bottom-half has to be done
-#
-        lgf     %r1,__TI_cpu(%r9)
-	larl    %r2,irq_stat
-	sll     %r1,L1_CACHE_SHIFT
-	la      %r1,0(%r1,%r2)
-	icm     %r0,15,0(%r1)          # test irq_stat[#cpu].__softirq_pending
-        jnz     io_handle_bottom_half
-io_return_bh:	
+        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+#ifdef CONFIG_PREEMPT
+	jno     io_preempt             # no -> check for preemptive scheduling
+#else
+        jno     io_leave               # no-> skip resched & signal
+#endif
 	tm	__TI_flags+7(%r9),_TIF_WORK_MASK
 	jnz	io_work                # there is work to do (signals etc.)
 io_leave:
-        stnsm   48(%r15),0xfc          # disable I/O and ext. interrupts
         RESTORE_ALL 0
 
+#ifdef CONFIG_PREEMPT
+io_preempt:
+	icm	%r0,15,__TI_precount(%r9)	
+	jnz     io_leave
+io_resume_loop:
+	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
+	jno	io_leave
+	larl    %r1,.Lc_pactive
+	mvc     __TI_precount(4,%r9),0(%r1)
+	# hmpf, we are on the async. stack but to call schedule
+	# we have to move the interrupt frame to the process stack
+	lg	%r1,SP_R15(%r15)
+	aghi	%r1,-SP_SIZE
+	nill	%r1,0xfff8
+	mvc	SP_PTREGS(SP_SIZE-SP_PTREGS,%r1),SP_PTREGS(%r15)
+        xc      0(8,%r1),0(%r1)        # clear back chain
+	lgr	%r15,%r1
+        stosm   48(%r15),0x03          # reenable interrupts
+	brasl   %r14,schedule          # call schedule
+        stnsm   48(%r15),0xfc          # disable I/O and ext. interrupts
+        GET_THREAD_INFO                # load pointer to task_struct to R9
+	xc      __TI_precount(4,%r9),__TI_precount(%r9)
+	j	io_resume_loop
+#endif
+
 #
-# call do_softirq
+# recheck if there is more work to do
 #
-io_handle_bottom_half:        
-	larl    %r14,io_return_bh
-        jg      do_softirq             # return point is io_return_bh
-
+io_work_loop:
+        stnsm   48(%r15),0xfc          # disable I/O and ext. interrupts
+        GET_THREAD_INFO                # load pointer to task_struct to R9
+	tm	__TI_flags+7(%r9),_TIF_WORK_MASK
+	jz	io_leave               # there is no work to do
 #
-# One of the work bits _TIF_NOTIFY_RESUME, _TIF_SIGPENDING or
-# _TIF_NEED_RESCHED is on. Find out which one.
+# One of the work bits is on. Find out which one.
+# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
 #
 io_work:
-        tm      SP_PSW+1(%r15),0x01    # returning to user ?
-        jno     io_leave               # no-> skip resched & signal
-        stosm   48(%r15),0x03          # reenable interrupts
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	io_reschedule
-	# add a test for TIF_NOTIFY_RESUME here when it is used.
-	# _TIF_SIGPENDING is the only flag left
+	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
+	jo	io_sigpending
+	j	io_leave
 
 #
-# call do_signal before return
-#
-io_signal_return:     
-        la      %r2,SP_PTREGS(%r15) # load pt_regs
-        slgr    %r3,%r3             # clear *oldset
-	larl    %r14,io_leave
-        jg      do_signal           # return point is io_leave
+# _TIF_NEED_RESCHED is set, call schedule
+#	
+io_reschedule:        
+        stosm   48(%r15),0x03       # reenable interrupts
+	larl    %r14,io_work_loop
+        jg      schedule            # call scheduler
 
 #
-# call schedule with io_return as return-address
+# _TIF_SIGPENDING is set, call do_signal
 #
-io_reschedule:        
-	larl    %r14,io_return
-        jg      schedule            # call scheduler, return to io_return
+io_sigpending:     
+        stosm   48(%r15),0x03       # reenable interrupts
+        la      %r2,SP_PTREGS(%r15) # load pt_regs
+        slgr    %r3,%r3             # clear *oldset
+	brasl	%r14,do_signal      # call do_signal
+        stnsm   48(%r15),0xfc       # disable I/O and ext. interrupts
+	j	sysc_leave          # out of here, do NOT recheck
 
 /*
  * External interrupt handler routine
@@ -883,4 +917,5 @@
  */
                .align 4
 .Lc_ac:        .long  0,0,1
+.Lc_pactive:   .long  PREEMPT_ACTIVE
 .Lc256:        .quad  256
diff -urN linux-2.5.39/include/asm-s390/hardirq.h linux-2.5.39-s390/include/asm-s390/hardirq.h
--- linux-2.5.39/include/asm-s390/hardirq.h	Mon Sep 30 13:25:21 2002
+++ linux-2.5.39-s390/include/asm-s390/hardirq.h	Mon Sep 30 13:32:33 2002
@@ -80,15 +80,21 @@
 
 extern void do_call_softirq(void);
 
-#define in_atomic()	(preempt_count() != 0)
-#define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#if CONFIG_PREEMPT
+# define in_atomic()	(in_interrupt() || preempt_count() == PREEMPT_ACTIVE)
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic()	(preempt_count() != 0)
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
 
 #define irq_exit()							\
 do {									\
-	preempt_count() -= HARDIRQ_OFFSET;				\
+	preempt_count() -= IRQ_EXIT_OFFSET;				\
 	if (!in_interrupt() && softirq_pending(smp_processor_id()))	\
 		/* Use the async. stack for softirq */			\
 		do_call_softirq();					\
+	preempt_enable_no_resched();					\
 } while (0)
 
 #ifndef CONFIG_SMP
diff -urN linux-2.5.39/include/asm-s390/softirq.h linux-2.5.39-s390/include/asm-s390/softirq.h
--- linux-2.5.39/include/asm-s390/softirq.h	Mon Sep 30 13:25:21 2002
+++ linux-2.5.39-s390/include/asm-s390/softirq.h	Mon Sep 30 13:32:33 2002
@@ -10,6 +10,7 @@
 #define __ASM_SOFTIRQ_H
 
 #include <linux/smp.h>
+#include <linux/preempt.h>
 
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
@@ -28,6 +29,7 @@
 	if (!in_interrupt() && softirq_pending(smp_processor_id()))	\
 		/* Use the async. stack for softirq */			\
 		do_call_softirq();					\
+	preempt_check_resched();					\
 } while (0)
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -urN linux-2.5.39/include/asm-s390/thread_info.h linux-2.5.39-s390/include/asm-s390/thread_info.h
--- linux-2.5.39/include/asm-s390/thread_info.h	Fri Sep 27 23:50:23 2002
+++ linux-2.5.39-s390/include/asm-s390/thread_info.h	Mon Sep 30 13:32:33 2002
@@ -25,11 +25,9 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
-	int			preempt_count; /* 0 => preemptable, <0 => BUG */
+	unsigned int		preempt_count; /* 0 => preemptable */
 };
 
-#define PREEMPT_ACTIVE		0x4000000
-
 /*
  * macros/functions for gaining access to the thread information structure
  */
@@ -84,4 +82,6 @@
 
 #endif /* __KERNEL__ */
 
+#define PREEMPT_ACTIVE		0x4000000
+
 #endif /* _ASM_THREAD_INFO_H */
diff -urN linux-2.5.39/include/asm-s390x/hardirq.h linux-2.5.39-s390/include/asm-s390x/hardirq.h
--- linux-2.5.39/include/asm-s390x/hardirq.h	Mon Sep 30 13:25:21 2002
+++ linux-2.5.39-s390/include/asm-s390x/hardirq.h	Mon Sep 30 13:32:33 2002
@@ -81,15 +81,21 @@
 
 extern void do_call_softirq(void);
 
-#define in_atomic()	(preempt_count() != 0)
-#define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#if CONFIG_PREEMPT
+# define in_atomic()	(in_interrupt() || preempt_count() == PREEMPT_ACTIVE)
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic()	(preempt_count() != 0)
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
 
 #define irq_exit()							\
 do {									\
-	preempt_count() -= HARDIRQ_OFFSET;				\
+	preempt_count() -= IRQ_EXIT_OFFSET;				\
 	if (!in_interrupt() && softirq_pending(smp_processor_id()))	\
 		/* Use the async. stack for softirq */			\
 		do_call_softirq();					\
+	preempt_enable_no_resched();					\
 } while (0)
 
 #ifndef CONFIG_SMP
diff -urN linux-2.5.39/include/asm-s390x/thread_info.h linux-2.5.39-s390/include/asm-s390x/thread_info.h
--- linux-2.5.39/include/asm-s390x/thread_info.h	Fri Sep 27 23:50:26 2002
+++ linux-2.5.39-s390/include/asm-s390x/thread_info.h	Mon Sep 30 13:32:33 2002
@@ -25,11 +25,9 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
-	int 			preempt_count; /* 0 => preemptable, <0 => BUG */
+	unsigned int		preempt_count;  /* 0 => preemptable */
 };
 
-#define PREEMPT_ACTIVE		0x4000000
-
 /*
  * macros/functions for gaining access to the thread information structure
  */
@@ -84,4 +82,6 @@
 
 #endif /* __KERNEL__ */
 
+#define PREEMPT_ACTIVE		0x4000000
+
 #endif /* _ASM_THREAD_INFO_H */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-09-30 14:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-30 12:56 [PATCH] 2.5.39 s390 (13/26): preemption Martin Schwidefsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).