summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/syscall.c')
-rw-r--r--arch/mips/kernel/syscall.c70
1 files changed, 54 insertions, 16 deletions
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 3b595e05d..2faf604c7 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -17,6 +17,8 @@
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/unistd.h>
@@ -35,35 +37,49 @@ extern unsigned char sys_narg_table[];
asmlinkage int sys_pipe(struct pt_regs *regs)
{
int fd[2];
- int error;
+ int error, res;
+ lock_kernel();
error = do_pipe(fd);
- if (error)
- return error;
+ if (error) {
+ res = error;
+ goto out;
+ }
regs->regs[3] = fd[1];
- return fd[0];
+ res = fd[0];
+out:
+ unlock_kernel();
+ return res;
}
asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
int flags, int fd, off_t offset)
{
struct file * file = NULL;
+ unsigned long res;
+ lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- return do_mmap(file, addr, len, prot, flags, offset);
+ res = do_mmap(file, addr, len, prot, flags, offset);
+
+ unlock_kernel();
+ return res;
}
asmlinkage int sys_idle(void)
{
- if (current->pid != 0)
- return -EPERM;
+ int ret = -EPERM;
+ lock_kernel();
+ if (current->pid != 0)
+ goto out;
/* endless idle loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
for (;;) {
/*
@@ -76,25 +92,38 @@ asmlinkage int sys_idle(void)
__asm__(".set\tmips3\n\t"
"wait\n\t"
".set\tmips0\n\t");
+ run_task_queue(&tq_scheduler);
schedule();
}
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage int sys_fork(struct pt_regs *regs)
{
- return do_fork(SIGCHLD, regs->regs[29], regs);
+ int res;
+
+ lock_kernel();
+ res = do_fork(SIGCHLD, regs->regs[29], regs);
+ unlock_kernel();
+ return res;
}
asmlinkage int sys_clone(struct pt_regs *regs)
{
unsigned long clone_flags;
unsigned long newsp;
+ int res;
+ lock_kernel();
clone_flags = regs->regs[4];
newsp = regs->regs[5];
if (!newsp)
newsp = regs->regs[29];
- return do_fork(clone_flags, newsp, regs);
+ res = do_fork(clone_flags, newsp, regs);
+ unlock_kernel();
+ return res;
}
/*
@@ -102,20 +131,25 @@ asmlinkage int sys_clone(struct pt_regs *regs)
*/
asmlinkage int sys_execve(struct pt_regs *regs)
{
- int error;
+ int res;
char * filename;
- error = getname((char *) (long)regs->regs[4], &filename);
- if (error)
- return error;
- error = do_execve(filename, (char **) (long)regs->regs[5],
- (char **) (long)regs->regs[6], regs);
+ lock_kernel();
+ res = getname((char *) (long)regs->regs[4], &filename);
+ if (res)
+ goto out;
+ res = do_execve(filename, (char **) (long)regs->regs[5],
+ (char **) (long)regs->regs[6], regs);
putname(filename);
- return error;
+
+out:
+ unlock_kernel();
+ return res;
}
/*
* Do the indirect syscall syscall.
+ * Don't care about kernel locking; the actual syscall will do it.
*/
asmlinkage int sys_syscall(struct pt_regs *regs)
{
@@ -184,6 +218,7 @@ asmlinkage int sys_syscall(struct pt_regs *regs)
/*
* If we ever come here the user sp is bad. Zap the process right away.
* Due to the bad stack signaling wouldn't work.
+ * XXX kernel locking???
*/
asmlinkage void bad_stack(void)
{
@@ -204,6 +239,9 @@ static char *irix_sys_names[] = {
};
#endif
+/*
+ * This isn't entirely correct with respect to kernel locking ...
+ */
void do_sys(struct pt_regs *regs)
{
unsigned long syscallnr, usp;