Commit a610260d authored by Linus Torvalds's avatar Linus Torvalds

Add "restart" system call, allowing system calls to restart after signal

handling.

Update x86 to use the new infrastructure.
parent 99b4fa86
...@@ -3,8 +3,9 @@ ...@@ -3,8 +3,9 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/thread_info.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
......
...@@ -7,9 +7,10 @@ ...@@ -7,9 +7,10 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/thread_info.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/thread_info.h>
#include "mce.h" #include "mce.h"
......
...@@ -484,7 +484,7 @@ ENTRY(spurious_interrupt_bug) ...@@ -484,7 +484,7 @@ ENTRY(spurious_interrupt_bug)
.data .data
ENTRY(sys_call_table) 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_exit
.long sys_fork .long sys_fork
.long sys_read .long sys_read
......
...@@ -506,6 +506,8 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -506,6 +506,8 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (regs->orig_eax >= 0) { if (regs->orig_eax >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
switch (regs->eax) { switch (regs->eax) {
case -ERESTART_RESTARTBLOCK:
current_thread_info()->restart_block.fn = do_no_restart_syscall;
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
regs->eax = -EINTR; regs->eax = -EINTR;
break; break;
...@@ -591,6 +593,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -591,6 +593,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->eax = regs->orig_eax; regs->eax = regs->orig_eax;
regs->eip -= 2; regs->eip -= 2;
} }
if (regs->eax == -ERESTART_RESTARTBLOCK){
regs->eax = __NR_restart_syscall;
regs->eip -= 2;
}
} }
return 0; return 0;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/oprofile.h> #include <linux/oprofile.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <asm/thread_info.h> #include <linux/thread_info.h>
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/msr.h> #include <asm/msr.h>
......
#ifndef _I386_CURRENT_H #ifndef _I386_CURRENT_H
#define _I386_CURRENT_H #define _I386_CURRENT_H
#include <asm/thread_info.h> #include <linux/thread_info.h>
struct task_struct; struct task_struct;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
* - if the contents of this structure are changed, the assembly constants must also be changed * - if the contents of this structure are changed, the assembly constants must also be changed
*/ */
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
struct thread_info { struct thread_info {
struct task_struct *task; /* main task structure */ struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */ struct exec_domain *exec_domain; /* execution domain */
...@@ -31,6 +32,7 @@ struct thread_info { ...@@ -31,6 +32,7 @@ struct thread_info {
0-0xBFFFFFFF for user-thead 0-0xBFFFFFFF for user-thead
0-0xFFFFFFFF for kernel-thread 0-0xFFFFFFFF for kernel-thread
*/ */
struct restart_block restart_block;
__u8 supervisor_stack[0]; __u8 supervisor_stack[0];
}; };
...@@ -44,6 +46,7 @@ struct thread_info { ...@@ -44,6 +46,7 @@ struct thread_info {
#define TI_CPU 0x0000000C #define TI_CPU 0x0000000C
#define TI_PRE_COUNT 0x00000010 #define TI_PRE_COUNT 0x00000010
#define TI_ADDR_LIMIT 0x00000014 #define TI_ADDR_LIMIT 0x00000014
#define TI_RESTART_BLOCK 0x0000018
#endif #endif
...@@ -55,6 +58,7 @@ struct thread_info { ...@@ -55,6 +58,7 @@ struct thread_info {
* preempt_count needs to be 1 initially, until the scheduler is functional. * preempt_count needs to be 1 initially, until the scheduler is functional.
*/ */
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define INIT_THREAD_INFO(tsk) \ #define INIT_THREAD_INFO(tsk) \
{ \ { \
.task = &tsk, \ .task = &tsk, \
...@@ -63,6 +67,9 @@ struct thread_info { ...@@ -63,6 +67,9 @@ struct thread_info {
.cpu = 0, \ .cpu = 0, \
.preempt_count = 1, \ .preempt_count = 1, \
.addr_limit = KERNEL_DS, \ .addr_limit = KERNEL_DS, \
.restart_block = { \
.fn = do_no_restart_syscall, \
}, \
} }
#define init_thread_info (init_thread_union.thread_info) #define init_thread_info (init_thread_union.thread_info)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* This file contains the system call numbers. * This file contains the system call numbers.
*/ */
#define __NR_restart_syscall 0
#define __NR_exit 1 #define __NR_exit 1
#define __NR_fork 2 #define __NR_fork 2
#define __NR_read 3 #define __NR_read 3
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define ERESTARTNOINTR 513 #define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514 /* restart if no handler.. */ #define ERESTARTNOHAND 514 /* restart if no handler.. */
#define ENOIOCTLCMD 515 /* No ioctl command */ #define ENOIOCTLCMD 515 /* No ioctl command */
#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
/* Defined for the NFSv3 protocol */ /* Defined for the NFSv3 protocol */
#define EBADHANDLE 521 /* Illegal NFS file handle */ #define EBADHANDLE 521 /* Illegal NFS file handle */
......
...@@ -7,6 +7,16 @@ ...@@ -7,6 +7,16 @@
#ifndef _LINUX_THREAD_INFO_H #ifndef _LINUX_THREAD_INFO_H
#define _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 <linux/bitops.h>
#include <asm/thread_info.h> #include <asm/thread_info.h>
......
...@@ -1351,6 +1351,18 @@ EXPORT_SYMBOL(unblock_all_signals); ...@@ -1351,6 +1351,18 @@ EXPORT_SYMBOL(unblock_all_signals);
* System call entry points. * 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 * 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_ * particular thread.. (and that's good, because this is _heavily_
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment