]> git.hungrycats.org Git - linux/commitdiff
[PATCH] s390: nanosleep restarting.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Sun, 15 Dec 2002 04:02:32 +0000 (20:02 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sun, 15 Dec 2002 04:02:32 +0000 (20:02 -0800)
sys_restart_syscall for nanosleep restarting.

arch/s390/kernel/entry.S
arch/s390/kernel/signal.c
arch/s390x/kernel/entry.S
arch/s390x/kernel/signal.c
include/asm-s390/current.h
include/asm-s390/thread_info.h
include/asm-s390/unistd.h
include/asm-s390x/current.h
include/asm-s390x/thread_info.h
include/asm-s390x/unistd.h

index 27f685256cfaf2f500778cb297fa940b852fe644..f7a4fd107b855d2cf0385bca0eb83d3b002901d6 100644 (file)
@@ -47,7 +47,8 @@ SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + PT_ORIGGPR2
 SP_TRAP      =  (SP_ORIG_R2+GPR_SIZE)
 SP_SIZE      =  (SP_TRAP+4)
 
-_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
 /*
  * Base Address of this Module --- saved in __LC_ENTRY_BASE
@@ -181,6 +182,7 @@ system_call:
         GET_THREAD_INFO           # load pointer to task_struct to R9
        sll     %r7,2
         stosm   24(%r15),0x03     # reenable interrupts
+sysc_do_restart:
         l       %r8,sys_call_table-entry_base(%r7,%r13) # get system call addr.
        tm      __TI_flags+3(%r9),_TIF_SYSCALL_TRACE
         bo      BASED(sysc_tracesys)
@@ -191,7 +193,7 @@ system_call:
 
 sysc_return:
        stnsm   24(%r15),0xfc     # disable I/O and ext. interrupts
-       tm      __TI_flags+3(%r9),_TIF_WORK_MASK
+       tm      __TI_flags+3(%r9),_TIF_WORK_SVC
        bnz     BASED(sysc_work)  # there is work to do (signals etc.)
 sysc_leave:
         RESTORE_ALL 1
@@ -202,7 +204,7 @@ sysc_leave:
 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
+       tm      __TI_flags+3(%r9),_TIF_WORK_SVC
        bz      BASED(sysc_leave)      # there is no work to do
 #
 # One of the work bits is on. Find out which one.
@@ -213,6 +215,8 @@ sysc_work:
        bo      BASED(sysc_reschedule)
        tm      __TI_flags+3(%r9),_TIF_SIGPENDING
        bo      BASED(sysc_sigpending)
+       tm      __TI_flags+3(%r9),_TIF_RESTART_SVC
+       bo      BASED(sysc_restart)
        b       BASED(sysc_leave)
 
 #
@@ -236,15 +240,27 @@ sysc_sigpending:
         stnsm   24(%r15),0xfc          # disable I/O and ext. interrupts
        b       BASED(sysc_leave)      # out of here, do NOT recheck
 
+#
+# _TIF_RESTART_SVC is set, set up registers and restart svc
+#
+sysc_restart:
+       ni      __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
+       stosm   24(%r15),0x03          # reenable interrupts
+       l       %r7,SP_R2(%r15)        # load new svc number
+       sll     %r7,2
+       mvc     SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument
+       lm      %r2,%r6,SP_R2(%r15)    # load svc arguments
+       b       BASED(sysc_do_restart) # restart svc
+
 #
 # call trace before and after sys_call
 #
 sysc_tracesys:
         l       %r1,BASED(.Ltrace)
        srl     %r7,2
-       st      %r7,SP_R2(4,%r15)
+       st      %r7,SP_R2(%r15)
        basr    %r14,%r1
-       l       %r7,SP_R2(4,%r15)      # strace might have changed the 
+       l       %r7,SP_R2(%r15)        # strace might have changed the 
        n       %r7,BASED(.Lc256)      #  system call
        sll     %r7,2
        l       %r8,sys_call_table-entry_base(%r7,%r13)
@@ -354,7 +370,7 @@ sys_call_table:
         .long  sys_write
         .long  sys_open                  /* 5 */
         .long  sys_close
-        .long  sys_ni_syscall           /* old waitpid syscall holder */
+        .long  sys_restart_syscall
         .long  sys_creat
         .long  sys_link
         .long  sys_unlink                /* 10 */
@@ -752,7 +768,7 @@ io_return:
 #else
         bno     BASED(io_leave)        # no-> skip resched & signal
 #endif
-       tm      __TI_flags+3(%r9),_TIF_WORK_MASK
+       tm      __TI_flags+3(%r9),_TIF_WORK_INT
        bnz     BASED(io_work)         # there is work to do (signals etc.)
 io_leave:
         RESTORE_ALL 0
@@ -788,7 +804,7 @@ io_resume_loop:
 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
+       tm      __TI_flags+3(%r9),_TIF_WORK_INT
        bz      BASED(io_leave)        # there is no work to do
 #
 # One of the work bits is on. Find out which one.
index 3f0eda04e9d80c701d1d747bee16e598b1751352..1f2b732fb96a3cc9b59bb214d5dcf950face50c0 100644 (file)
@@ -397,6 +397,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
        if (regs->trap == __LC_SVC_OLD_PSW) {
                /* If so, check system call restarting.. */
                switch (regs->gprs[2]) {
+                       case -ERESTART_RESTARTBLOCK:
+                               current_thread_info()->restart_block.fn =
+                                       do_no_restart_syscall;
+                               clear_thread_flag(TIF_RESTART_SVC);
                        case -ERESTARTNOHAND:
                                regs->gprs[2] = -EINTR;
                                break;
@@ -473,6 +477,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        regs->gprs[2] = regs->orig_gpr2;
                        regs->psw.addr -= 2;
                }
+               /* Restart the system call with a new system call number */
+               if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
+                       regs->gprs[2] = __NR_restart_syscall;
+                       set_thread_flag(TIF_RESTART_SVC);
+               }
        }
        return 0;
 }
index 47029c59d85affcb3a19ac66b8339536be6dc48d..539be43e4ecccbb0e4abd542818330e906fe917a 100644 (file)
@@ -47,7 +47,8 @@ SP_ORIG_R2   =  STACK_FRAME_OVERHEAD + PT_ORIGGPR2
 SP_TRAP      =  (SP_ORIG_R2+GPR_SIZE)
 SP_SIZE      =  (SP_TRAP+4)
 
-_TIF_WORK_MASK = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_RESTART_SVC)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
 /*
  * Register usage in interrupt handlers:
@@ -161,6 +162,7 @@ system_call:
        llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
         GET_THREAD_INFO           # load pointer to task_struct to R9
        stosm   48(%r15),0x03     # reenable interrupts
+sysc_do_restart:
        larl    %r10,sys_call_table
         sll     %r7,3
         tm      SP_PSW+3(%r15),0x01  # are we running in 31 bit mode ?
@@ -177,7 +179,7 @@ sysc_noemu:
 
 sysc_return:
        stnsm   48(%r15),0xfc     # disable I/O and ext. interrupts
-       tm      __TI_flags+7(%r9),_TIF_WORK_MASK
+       tm      __TI_flags+7(%r9),_TIF_WORK_SVC
        jnz     sysc_work         # there is work to do (signals etc.)
 sysc_leave:
         RESTORE_ALL 1
@@ -188,7 +190,7 @@ sysc_leave:
 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
+       tm      __TI_flags+7(%r9),_TIF_WORK_SVC
        jz      sysc_leave        # there is no work to do
 #
 # One of the work bits is on. Find out which one.
@@ -199,6 +201,8 @@ sysc_work:
        jo      sysc_reschedule
        tm      __TI_flags+7(%r9),_TIF_SIGPENDING
        jo      sysc_sigpending
+       tm      __TI_flags+7(%r9),_TIF_RESTART_SVC
+       jo      sysc_restart
        j       sysc_leave
 
 #
@@ -220,6 +224,17 @@ sysc_sigpending:
        stnsm   48(%r15),0xfc     # disable I/O and ext. interrupts
        j       sysc_leave        # out of here, do NOT recheck
 
+#
+# _TIF_RESTART_SVC is set, set up registers and restart svc
+#
+sysc_restart:
+       ni      __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC
+       stosm   48(%r15),0x03          # reenable interrupts
+       lg      %r7,SP_R2(%r15)        # load new svc number
+       mvc     SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument
+       lmg     %r2,%r6,SP_R2(%r15)    # load svc arguments
+       j       sysc_do_restart        # restart svc
+
 #
 # call syscall_trace before and after system call
 # special linkage: %r12 contains the return address for trace_svc
@@ -383,7 +398,7 @@ sys_call_table:
         .long  SYSCALL(sys_write,sys32_write_wrapper)
         .long  SYSCALL(sys_open,sys32_open_wrapper)             /* 5 */
         .long  SYSCALL(sys_close,sys32_close_wrapper)
-        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old waitpid syscall */
+        .long  SYSCALL(sys_restart_syscall,sys_ni_syscall)
         .long  SYSCALL(sys_creat,sys32_creat_wrapper)
         .long  SYSCALL(sys_link,sys32_link_wrapper)
         .long  SYSCALL(sys_unlink,sys32_unlink_wrapper)         /* 10 */
@@ -777,7 +792,7 @@ io_return:
 #else
         jno     io_leave               # no-> skip resched & signal
 #endif
-       tm      __TI_flags+7(%r9),_TIF_WORK_MASK
+       tm      __TI_flags+7(%r9),_TIF_WORK_INT
        jnz     io_work                # there is work to do (signals etc.)
 io_leave:
         RESTORE_ALL 0
@@ -813,7 +828,7 @@ io_resume_loop:
 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
+       tm      __TI_flags+7(%r9),_TIF_WORK_INT
        jz      io_leave               # there is no work to do
 #
 # One of the work bits is on. Find out which one.
index 725afe1738f817d68fde9b3a5a75275cc365de27..bb9291563f5ffdeaea3a33e0e5776e58fac5a2e2 100644 (file)
@@ -391,6 +391,10 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
        if (regs->trap == __LC_SVC_OLD_PSW) {
                /* If so, check system call restarting.. */
                switch (regs->gprs[2]) {
+                       case -ERESTART_RESTARTBLOCK:
+                               current_thread_info()->restart_block.fn =
+                                       do_no_restart_syscall;
+                               clear_thread_flag(TIF_RESTART_SVC);
                        case -ERESTARTNOHAND:
                                regs->gprs[2] = -EINTR;
                                break;
@@ -473,6 +477,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        regs->gprs[2] = regs->orig_gpr2;
                        regs->psw.addr -= 2;
                }
+               /* Restart the system call with a new system call number */
+               if (regs->gprs[2] == -ERESTART_RESTARTBLOCK) {
+                       regs->gprs[2] = __NR_restart_syscall;
+                       set_thread_flag(TIF_RESTART_SVC);
+               }
        }
        return 0;
 }
index 85eea9e06fafce34d5b9e93c90d5a39bba705316..ea88f10590ab222c7759226c730dc72eddd19f0b 100644 (file)
@@ -13,7 +13,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm/thread_info.h>
+#include <linux/thread_info.h>
 
 struct task_struct;
 
index 26a7c4d21be8425ccf0afe844490c8a812eade1e..eb131fa3a47040c36498c8e190933f0fc756421b 100644 (file)
@@ -26,6 +26,7 @@ struct thread_info {
        unsigned long           flags;          /* low level flags */
        unsigned int            cpu;            /* current CPU */
        unsigned int            preempt_count; /* 0 => preemptable */
+       struct restart_block    restart_block;
 };
 
 /*
@@ -33,10 +34,13 @@ struct thread_info {
  */
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
-       task:           &tsk,                   \
-       exec_domain:    &default_exec_domain,   \
-       flags:          0,                      \
-       cpu:            0,                      \
+       .task           = &tsk,                 \
+       .exec_domain    = &default_exec_domain, \
+       .flags          = 0,                    \
+       .cpu            = 0,                    \
+       .restart_block  = {                     \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
 }
 
 #define init_thread_info       (init_thread_union.thread_info)
@@ -69,6 +73,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_RESTART_SVC                4       /* restart svc with new svc number */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling 
                                           TIF_NEED_RESCHED */
@@ -77,6 +82,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTART_SVC       (1<<TIF_RESTART_SVC)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
index 82c80b2efdb94fa39eae8ee44f23e4e5664551a2..135e013c42bf9d9225ad0e8c5ff84d192b48163b 100644 (file)
@@ -19,6 +19,7 @@
 #define __NR_write                4
 #define __NR_open                 5
 #define __NR_close                6
+#define __NR_restart_syscall     7
 #define __NR_creat                8
 #define __NR_link                 9
 #define __NR_unlink              10
index 7e82e4d5b4d0cc5657d89678e6cb68c25c2adc72..b8b52049cf8fba8240e07fb1e291a74f39a0468f 100644 (file)
@@ -13,7 +13,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm/thread_info.h>
+#include <linux/thread_info.h>
 
 struct task_struct;
 
index 788c7e6654ce0b82cd21e4d3897710fa6c5a48b4..0bc09b5a2e9b7f6538cf90ff37d5f0ec95e9a00b 100644 (file)
@@ -26,6 +26,7 @@ struct thread_info {
        unsigned long           flags;          /* low level flags */
        unsigned int            cpu;            /* current CPU */
        unsigned int            preempt_count;  /* 0 => preemptable */
+       struct restart_block    restart_block;
 };
 
 /*
@@ -33,10 +34,13 @@ struct thread_info {
  */
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
-       task:           &tsk,                   \
-       exec_domain:    &default_exec_domain,   \
-       flags:          0,                      \
-       cpu:            0,                      \
+       .task           = &tsk,                 \
+       .exec_domain    = &default_exec_domain, \
+       .flags          = 0,                    \
+       .cpu            = 0,                    \
+       .restart_block  = {                     \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
 }
 
 #define init_thread_info       (init_thread_union.thread_info)
@@ -69,6 +73,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_RESTART_SVC                4       /* restart svc with new svc number */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling 
                                           TIF_NEED_RESCHED */
@@ -77,6 +82,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTART_SVC       (1<<TIF_RESTART_SVC)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
index 1a489a14c1ce0c0b2dad2db5beb1f80a7a3b6e7b..51fe320793d8344e2fff88892c98e2d0c2b912fc 100644 (file)
@@ -19,6 +19,7 @@
 #define __NR_write                4
 #define __NR_open                 5
 #define __NR_close                6
+#define __NR_restart_syscall     7
 #define __NR_creat                8
 #define __NR_link                 9
 #define __NR_unlink              10