]> git.neil.brown.name Git - history.git/commitdiff
Add "restart" system call, allowing system calls to restart after signal
authorLinus Torvalds <torvalds@home.transmeta.com>
Fri, 6 Dec 2002 01:43:46 +0000 (17:43 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Fri, 6 Dec 2002 01:43:46 +0000 (17:43 -0800)
handling.

Update x86 to use the new infrastructure.

arch/i386/kernel/cpu/intel.c
arch/i386/kernel/cpu/mcheck/mce.c
arch/i386/kernel/entry.S
arch/i386/kernel/signal.c
arch/i386/oprofile/nmi_int.c
include/asm-i386/current.h
include/asm-i386/thread_info.h
include/asm-i386/unistd.h
include/linux/errno.h
include/linux/thread_info.h
kernel/signal.c

index 2c32abb679c1cb6ec3c51f34adf5ed2fd304ecb6..3e6e23c6f4e8685faadbca1c427e970bbdbdad30 100644 (file)
@@ -3,8 +3,9 @@
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/smp.h>
+#include <linux/thread_info.h>
+
 #include <asm/processor.h>
-#include <asm/thread_info.h>
 #include <asm/msr.h>
 #include <asm/uaccess.h>
 
index fe2aec704ae893571bdb5c0946f7f387a73cddd8..12174a5164d243efc9ba709b5fb296b74788fbd9 100644 (file)
@@ -7,9 +7,10 @@
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/smp.h>
+#include <linux/thread_info.h>
+
 #include <asm/processor.h> 
 #include <asm/system.h>
-#include <asm/thread_info.h>
 
 #include "mce.h"
 
index b5a112712793ea69fb76272a405c6e0cecbd2e35..2d2c5867817568d4a8900d4cb76b0cc6080d571b 100644 (file)
@@ -484,7 +484,7 @@ ENTRY(spurious_interrupt_bug)
 
 .data
 ENTRY(sys_call_table)
-       .long sys_ni_syscall    /* 0 - old "setup()" system call*/
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
        .long sys_exit
        .long sys_fork
        .long sys_read
index 78e64f0df07943f63a81a2983cf03da4fe51c399..3f70dab574bf64178315becb4d271b66ddde1537 100644 (file)
@@ -506,6 +506,8 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
        if (regs->orig_eax >= 0) {
                /* If so, check system call restarting.. */
                switch (regs->eax) {
+                       case -ERESTART_RESTARTBLOCK:
+                               current_thread_info()->restart_block.fn = do_no_restart_syscall;
                        case -ERESTARTNOHAND:
                                regs->eax = -EINTR;
                                break;
@@ -591,6 +593,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        regs->eax = regs->orig_eax;
                        regs->eip -= 2;
                }
+               if (regs->eax == -ERESTART_RESTARTBLOCK){
+                       regs->eax = __NR_restart_syscall;
+                       regs->eip -= 2;
+               }
        }
        return 0;
 }
index 97eec9e30a22f073e7659b72a475091978668766..c2b6c1159e11b74068d94cf1d23d1e8fd519e292 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/smp.h>
 #include <linux/oprofile.h>
 #include <linux/pm.h>
-#include <asm/thread_info.h>
+#include <linux/thread_info.h>
 #include <asm/nmi.h>
 #include <asm/ptrace.h>
 #include <asm/msr.h>
index 4385a95ced7cb353655dc0ef6c9c743ea0b34e11..d97328951f5f027b767c28cf44b44f1abfd52aff 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _I386_CURRENT_H
 #define _I386_CURRENT_H
 
-#include <asm/thread_info.h>
+#include <linux/thread_info.h>
 
 struct task_struct;
 
index 8fe5dd33d51e3a97b1da569a530cfc0aa81c676b..b0560dc4647ea919253e1b8e6622b55583389fc1 100644 (file)
@@ -20,6 +20,7 @@
  * - if the contents of this structure are changed, the assembly constants must also be changed
  */
 #ifndef __ASSEMBLY__
+
 struct thread_info {
        struct task_struct      *task;          /* main task structure */
        struct exec_domain      *exec_domain;   /* execution domain */
@@ -31,6 +32,7 @@ struct thread_info {
                                                   0-0xBFFFFFFF for user-thead
                                                   0-0xFFFFFFFF for kernel-thread
                                                */
+       struct restart_block    restart_block;
 
        __u8                    supervisor_stack[0];
 };
@@ -44,6 +46,7 @@ struct thread_info {
 #define TI_CPU         0x0000000C
 #define TI_PRE_COUNT   0x00000010
 #define TI_ADDR_LIMIT  0x00000014
+#define TI_RESTART_BLOCK 0x0000018
 
 #endif
 
@@ -55,6 +58,7 @@ struct thread_info {
  * preempt_count needs to be 1 initially, until the scheduler is functional.
  */
 #ifndef __ASSEMBLY__
+
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
        .task           = &tsk,                 \
@@ -63,6 +67,9 @@ struct thread_info {
        .cpu            = 0,                    \
        .preempt_count  = 1,                    \
        .addr_limit     = KERNEL_DS,            \
+       .restart_block = {                      \
+               .fn = do_no_restart_syscall,    \
+       },                                      \
 }
 
 #define init_thread_info       (init_thread_union.thread_info)
index ae43f6a52840ff78751e9ebd91ad19489c113f5e..1ccd31f31074e4910afc35a56080ad9e4dcf9a6b 100644 (file)
@@ -5,6 +5,7 @@
  * This file contains the system call numbers.
  */
 
+#define __NR_restart_syscall      0
 #define __NR_exit                1
 #define __NR_fork                2
 #define __NR_read                3
index d17a7bf67000072fdb57359765f480cca88c45f0..a1f948f0a2079b370bb4335d3e487c68ba4a2a72 100644 (file)
@@ -10,6 +10,7 @@
 #define ERESTARTNOINTR 513
 #define ERESTARTNOHAND 514     /* restart if no handler.. */
 #define ENOIOCTLCMD    515     /* No ioctl command */
+#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
 
 /* Defined for the NFSv3 protocol */
 #define EBADHANDLE     521     /* Illegal NFS file handle */
index 9beb0f922efc96e724398ed952cdbd0373c46bb4..8bacba8ed989272b15e410f39f56094f69af85a7 100644 (file)
@@ -7,6 +7,16 @@
 #ifndef _LINUX_THREAD_INFO_H
 #define _LINUX_THREAD_INFO_H
 
+/*
+ * System call restart block. 
+ */
+struct restart_block {
+       long (*fn)(struct restart_block *);
+       unsigned long arg0, arg1, arg2;
+};
+
+extern long do_no_restart_syscall(struct restart_block *parm);
+
 #include <linux/bitops.h>
 #include <asm/thread_info.h>
 
index 6aa968dde2bf7a5fe2efe2b8178a8dfce589b809..6e1de31ed84ca20a680873ec73da08372cf3a1c9 100644 (file)
@@ -1351,6 +1351,18 @@ EXPORT_SYMBOL(unblock_all_signals);
  * System call entry points.
  */
 
+asmlinkage long sys_restart_syscall(void)
+{
+       struct thread_info *thread = current_thread_info();
+       return thread->restart_block.fn(&thread->restart_block);
+}
+
+long do_no_restart_syscall(struct restart_block *param)
+{
+       return -EINTR;
+}
+
+
 /*
  * We don't need to get the kernel lock - this is all local to this
  * particular thread.. (and that's good, because this is _heavily_