refactor syscall code

This commit is contained in:
rsc 2006-09-07 14:13:26 +00:00
parent 31085bb416
commit 224f6598c1
6 changed files with 198 additions and 248 deletions

11
defs.h
View file

@ -16,7 +16,7 @@ struct jmpbuf;
void setupsegs(struct proc*); void setupsegs(struct proc*);
struct proc* copyproc(struct proc*); struct proc* copyproc(struct proc*);
struct spinlock; struct spinlock;
uint growproc(int); int growproc(int);
void sleep(void*, struct spinlock*); void sleep(void*, struct spinlock*);
void wakeup(void*); void wakeup(void*);
void scheduler(void); void scheduler(void);
@ -43,10 +43,10 @@ int strncmp(const char*, const char*, uint);
// syscall.c // syscall.c
void syscall(void); void syscall(void);
int fetchint(struct proc*, uint, int*); int fetchint(struct proc*, uint, int*);
int fetchbyte(struct proc*, uint, char*); int fetchstr(struct proc*, uint, char**);
int fetcharg(int, void*); int argint(int, int*);
int checkstring(uint); int argptr(int, char**, int);
int putint(struct proc*, uint, int); int argstr(int, char**);
// picirq.c // picirq.c
extern ushort irq_mask_8259A; extern ushort irq_mask_8259A;
@ -99,7 +99,6 @@ int pipe_read(struct pipe*, char*, int);
// file.c // file.c
struct stat; struct stat;
void fileinit(void); void fileinit(void);
int fdalloc(void);
struct file* filealloc(void); struct file* filealloc(void);
void fileclose(struct file*); void fileclose(struct file*);
int fileread(struct file*, char*, int n); int fileread(struct file*, char*, int n);

14
file.c
View file

@ -22,19 +22,7 @@ fileinit(void)
initlock(&fd_table_lock, "fd_table"); initlock(&fd_table_lock, "fd_table");
} }
// Allocate a file descriptor number for curproc. // Allocate a file structure
int
fdalloc(void)
{
int fd;
struct proc *p = curproc[cpu()];
for(fd = 0; fd < NOFILE; fd++)
if(p->ofile[fd] == 0)
return fd;
return -1;
}
// Allocate a file descriptor structure
struct file* struct file*
filealloc(void) filealloc(void)
{ {

View file

@ -21,66 +21,73 @@
// library system call function. The saved user %esp points // library system call function. The saved user %esp points
// to a saved program counter, and then the first argument. // to a saved program counter, and then the first argument.
// Fetch 32 bits from a user-supplied pointer. // Fetch the int at addr from process p.
// Returns 0 if addr was OK, -1 if illegal.
int int
fetchint(struct proc *p, uint addr, int *ip) fetchint(struct proc *p, uint addr, int *ip)
{ {
*ip = 0; if(addr >= p->sz || addr+4 > p->sz)
if(addr > p->sz - 4)
return -1; return -1;
*ip = *(int*)(p->mem + addr); *ip = *(int*)(p->mem + addr);
return 0; return 0;
} }
// Fetch byte from a user-supplied pointer. // Fetch the nul-terminated string at addr from process p.
// Returns 0 on success, -1 if pointer is illegal. // Doesn't actually copy the string - just sets *pp to point at it.
// Returns length of string, not including nul.
int int
fetchbyte(struct proc *p, uint addr, char *c) fetchstr(struct proc *p, uint addr, char **pp)
{ {
char *cp, *ep;
if(addr >= p->sz) if(addr >= p->sz)
return -1; return -1;
*c = *(p->mem + addr); *pp = p->mem + addr;
return 0; ep = p->mem + p->sz;
for(cp = *pp; cp < ep; cp++)
if(*cp == 0)
return cp - *pp;
return -1;
} }
// Fetch the argno'th word-sized system call argument as an integer.
int int
fetcharg(int argno, void *ip) argint(int argno, int *ip)
{ {
uint esp; struct proc *p = curproc[cpu()];
esp = (uint) curproc[cpu()]->tf->esp; return fetchint(p, p->tf->esp + 4 + 4*argno, ip);
return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip);
} }
// Check that an entire string is valid in user space. // Fetch the nth word-sized system call argument as a pointer
// Returns the length, not including null, or -1. // to a block of memory of size n bytes. Check that the pointer
// lies within the process address space.
int int
checkstring(uint s) argptr(int argno, char **pp, int size)
{ {
char c; int i;
int len = 0; struct proc *p = curproc[cpu()];
for(;;){ if(argint(argno, &i) < 0)
if(fetchbyte(curproc[cpu()], s, &c) < 0)
return -1;
if(c == '\0')
return len;
len++;
s++;
}
}
int
putint(struct proc *p, uint addr, int x)
{
if(addr > p->sz - 4)
return -1; return -1;
memmove(p->mem + addr, &x, 4); if((uint)i >= p->sz || (uint)i+size >= p->sz)
return -1;
*pp = p->mem + i;
return 0; return 0;
} }
// Fetch the nth word-sized system call argument as a string pointer.
// Check that the pointer is valid and the string is nul-terminated.
// (There is no shared writable memory, so the string can't change
// between this check and being used by the kernel.)
int
argstr(int argno, char **pp)
{
int addr;
if(argint(argno, &addr) < 0)
return -1;
return fetchstr(curproc[cpu()], addr, pp);
}
extern int sys_chdir(void); extern int sys_chdir(void);
extern int sys_close(void); extern int sys_close(void);
extern int sys_dup(void); extern int sys_dup(void);

View file

@ -1,3 +1,4 @@
// System call numbers
#define SYS_fork 1 #define SYS_fork 1
#define SYS_exit 2 #define SYS_exit 2
#define SYS_wait 3 #define SYS_wait 3

318
sysfile.c
View file

@ -15,120 +15,117 @@
#include "file.h" #include "file.h"
#include "fcntl.h" #include "fcntl.h"
// Fetch the nth word-sized system call argument as a file descriptor
// and return both the descriptor and the corresponding struct file.
static int
argfd(int argno, int *pfd, struct file **pf)
{
int fd;
struct file *f;
struct proc *p = curproc[cpu()];
if(argint(argno, &fd) < 0)
return -1;
if(fd < 0 || fd >= NOFILE || (f=p->ofile[fd]) == 0)
return -1;
if(pfd)
*pfd = fd;
if(pf)
*pf = f;
return 0;
}
// Allocate a file descriptor for the given file.
// Takes over file reference from caller on success.
static int
fdalloc(struct file *f)
{
int fd;
struct proc *p = curproc[cpu()];
for(fd = 0; fd < NOFILE; fd++){
if(p->ofile[fd] == 0){
p->ofile[fd] = f;
return fd;
}
}
return -1;
}
int int
sys_pipe(void) sys_pipe(void)
{ {
struct file *rfd = 0, *wfd = 0; int *fd;
int f1 = -1, f2 = -1; struct file *rf = 0, *wf = 0;
int fd0, fd1;
struct proc *p = curproc[cpu()]; struct proc *p = curproc[cpu()];
uint fdp;
if(pipe_alloc(&rfd, &wfd) < 0) if(argptr(0, (void*)&fd, 2*sizeof fd[0]) < 0)
goto oops; return -1;
if((f1 = fdalloc()) < 0) if(pipe_alloc(&rf, &wf) < 0)
goto oops; return -1;
p->ofile[f1] = rfd; fd0 = -1;
if((f2 = fdalloc()) < 0) if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
goto oops; if(fd0 >= 0)
p->ofile[f2] = wfd; p->ofile[fd0] = 0;
if(fetcharg(0, &fdp) < 0) fileclose(rf);
goto oops; fileclose(wf);
if(putint(p, fdp, f1) < 0) return -1;
goto oops; }
if(putint(p, fdp+4, f2) < 0)
goto oops;
return 0; return 0;
oops:
if(rfd)
fileclose(rfd);
if(wfd)
fileclose(wfd);
if(f1 >= 0)
p->ofile[f1] = 0;
if(f2 >= 0)
p->ofile[f2] = 0;
return -1;
} }
int int
sys_write(void) sys_write(void)
{ {
int fd, n, ret; struct file *f;
uint addr; int n;
struct proc *p = curproc[cpu()]; char *cp;
if(fetcharg(0, &fd) < 0 || if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &cp, n) < 0)
fetcharg(1, &addr) < 0 ||
fetcharg(2, &n) < 0)
return -1; return -1;
if(fd < 0 || fd >= NOFILE) return filewrite(f, cp, n);
return -1;
if(p->ofile[fd] == 0)
return -1;
if(addr + n > p->sz)
return -1;
ret = filewrite(p->ofile[fd], p->mem + addr, n);
return ret;
} }
int int
sys_read(void) sys_read(void)
{ {
int fd, n, ret; struct file *f;
uint addr; int n;
struct proc *p = curproc[cpu()]; char *cp;
if(fetcharg(0, &fd) < 0 || if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &cp, n) < 0)
fetcharg(1, &addr) < 0 ||
fetcharg(2, &n) < 0)
return -1; return -1;
if(fd < 0 || fd >= NOFILE) return fileread(f, cp, n);
return -1;
if(p->ofile[fd] == 0)
return -1;
if(addr + n > p->sz)
return -1;
ret = fileread(p->ofile[fd], p->mem + addr, n);
return ret;
} }
int int
sys_close(void) sys_close(void)
{ {
int fd; int fd;
struct proc *p = curproc[cpu()]; struct file *f;
if(fetcharg(0, &fd) < 0) if(argfd(0, &fd, &f) < 0)
return -1; return -1;
if(fd < 0 || fd >= NOFILE) curproc[cpu()]->ofile[fd] = 0;
return -1; fileclose(f);
if(p->ofile[fd] == 0)
return -1;
fileclose(p->ofile[fd]);
p->ofile[fd] = 0;
return 0; return 0;
} }
int int
sys_open(void) sys_open(void)
{ {
struct proc *cp = curproc[cpu()];
struct inode *ip, *dp; struct inode *ip, *dp;
uint arg0, arg1; char *path;
int ufd; int omode;
struct file *fd; int fd;
int l; struct file *f;
char *last; char *last;
if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0) if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
return -1;
if((l = checkstring(arg0)) < 0)
return -1; return -1;
if(arg1 & O_CREATE){ if(omode & O_CREATE){
dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, &ip); dp = namei(path, NAMEI_CREATE, 0, &last, &ip);
if(dp){ if(dp){
ip = mknod1(dp, last, T_FILE, 0, 0); ip = mknod1(dp, last, T_FILE, 0, 0);
iput(dp); iput(dp);
@ -141,86 +138,77 @@ sys_open(void)
return -1; return -1;
} }
} else { } else {
ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0); ip = namei(path, NAMEI_LOOKUP, 0, 0, 0);
if(ip == 0) if(ip == 0)
return -1; return -1;
} }
if(ip->type == T_DIR && ((arg1 & O_RDWR) || (arg1 & O_WRONLY))){ if(ip->type == T_DIR && ((omode & O_RDWR) || (omode & O_WRONLY))){
iput(ip); iput(ip);
return -1; return -1;
} }
if((fd = filealloc()) == 0){ if((f = filealloc()) == 0){
iput(ip); iput(ip);
return -1; return -1;
} }
if((ufd = fdalloc()) < 0){ if((fd = fdalloc(f)) < 0){
iput(ip); iput(ip);
fileclose(fd); fileclose(f);
return -1; return -1;
} }
iunlock(ip); iunlock(ip);
fd->type = FD_FILE; f->type = FD_FILE;
if(arg1 & O_RDWR) { if(omode & O_RDWR) {
fd->readable = 1; f->readable = 1;
fd->writable = 1; f->writable = 1;
} else if(arg1 & O_WRONLY) { } else if(omode & O_WRONLY) {
fd->readable = 0; f->readable = 0;
fd->writable = 1; f->writable = 1;
} else { } else {
fd->readable = 1; f->readable = 1;
fd->writable = 0; f->writable = 0;
} }
fd->ip = ip; f->ip = ip;
fd->off = 0; f->off = 0;
cp->ofile[ufd] = fd;
return ufd; return fd;
} }
int int
sys_mknod(void) sys_mknod(void)
{ {
struct proc *cp = curproc[cpu()];
struct inode *nip; struct inode *nip;
uint arg0, arg1, arg2, arg3; char *path;
int l; int len;
int type, major, minor;
if(fetcharg(0, &arg0) < 0 || fetcharg(1, &arg1) < 0 || if((len=argstr(0, &path)) < 0 || argint(1, &type) < 0 ||
fetcharg(2, &arg2) < 0 || fetcharg(3, &arg3) < 0) argint(2, &major) < 0 || argint(3, &minor) < 0)
return -1; return -1;
if((l = checkstring(arg0)) < 0) if(len >= DIRSIZ)
return -1; return -1;
if(l >= DIRSIZ) if((nip = mknod(path, type, major, minor)) == 0)
return -1; return -1;
iput(nip);
nip = mknod(cp->mem + arg0, (short) arg1, (short) arg2, (short) arg3); return 0;
if(nip)
iput(nip);
return (nip == 0) ? -1 : 0;
} }
int int
sys_mkdir(void) sys_mkdir(void)
{ {
struct proc *cp = curproc[cpu()];
struct inode *nip; struct inode *nip;
struct inode *dp; struct inode *dp;
uint arg0; char *path;
int l;
struct dirent de; struct dirent de;
char *last; char *last;
if(fetcharg(0, &arg0) < 0) if(argstr(0, &path) < 0)
return -1; return -1;
if((l = checkstring(arg0)) < 0) dp = namei(path, NAMEI_CREATE, 0, &last, 0);
return -1;
dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, 0);
if(dp == 0) if(dp == 0)
return -1; return -1;
@ -248,25 +236,20 @@ sys_mkdir(void)
return 0; return 0;
} }
int int
sys_chdir(void) sys_chdir(void)
{ {
struct proc *cp = curproc[cpu()]; struct proc *p = curproc[cpu()];
struct inode *ip; struct inode *ip;
uint arg0; char *path;
int l;
if(fetcharg(0, &arg0) < 0) if(argstr(0, &path) < 0)
return -1; return -1;
if((l = checkstring(arg0)) < 0) if((ip = namei(path, NAMEI_LOOKUP, 0, 0, 0)) == 0)
return -1; return -1;
if((ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0)) == 0) if(ip == p->cwd) {
return -1;
if(ip == cp->cwd) {
iput(ip); iput(ip);
return 0; return 0;
} }
@ -276,100 +259,74 @@ sys_chdir(void)
return -1; return -1;
} }
idecref(cp->cwd); idecref(p->cwd);
cp->cwd = ip; p->cwd = ip;
iunlock(cp->cwd); iunlock(p->cwd);
return 0; return 0;
} }
int int
sys_unlink(void) sys_unlink(void)
{ {
struct proc *cp = curproc[cpu()]; char *path;
uint arg0;
int r;
if(fetcharg(0, &arg0) < 0) if(argstr(0, &path) < 0)
return -1; return -1;
if(checkstring(arg0) < 0) return unlink(path);
return -1;
r = unlink(cp->mem + arg0);
return r;
} }
int int
sys_fstat(void) sys_fstat(void)
{ {
struct proc *cp = curproc[cpu()]; struct file *f;
uint fd, addr; struct stat *st;
int r;
if(fetcharg(0, &fd) < 0) if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof *st) < 0)
return -1; return -1;
if(fetcharg(1, &addr) < 0) return filestat(f, st);
return -1;
if(fd < 0 || fd >= NOFILE)
return -1;
if(cp->ofile[fd] == 0)
return -1;
if(addr + sizeof(struct stat) > cp->sz)
return -1;
r = filestat(cp->ofile[fd], (struct stat*)(cp->mem + addr));
return r;
} }
int int
sys_dup(void) sys_dup(void)
{ {
struct proc *cp = curproc[cpu()]; struct file *f;
uint fd, ufd1; int fd;
if(fetcharg(0, &fd) < 0) if(argfd(0, 0, &f) < 0)
return -1; return -1;
if(fd < 0 || fd >= NOFILE) if((fd=fdalloc(f)) < 0)
return -1; return -1;
if(cp->ofile[fd] == 0) fileincref(f);
return -1; return fd;
if((ufd1 = fdalloc()) < 0)
return -1;
cp->ofile[ufd1] = cp->ofile[fd];
fileincref(cp->ofile[ufd1]);
return ufd1;
} }
int int
sys_link(void) sys_link(void)
{ {
struct proc *cp = curproc[cpu()]; char *old, *new;
uint name1, name2;
int r;
if(fetcharg(0, &name1) < 0 || checkstring(name1) < 0) if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
return -1; return -1;
if(fetcharg(1, &name2) < 0 || checkstring(name2) < 0) return link(old, new);
return -1;
r = link(cp->mem + name1, cp->mem + name2);
return r;
} }
int int
sys_exec(void) sys_exec(void)
{ {
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
uint arg0, arg1, sz=0, ap, sp, p1, p2; uint sz=0, ap, sp, p1, p2;
int i, nargs, argbytes, len; int i, nargs, argbytes, len;
struct inode *ip; struct inode *ip;
struct elfhdr elf; struct elfhdr elf;
struct proghdr ph; struct proghdr ph;
char *mem = 0; char *mem = 0;
char *path, *s;
uint argv;
if(fetcharg(0, &arg0) < 0) if(argstr(0, &path) < 0 || argint(1, (int*)&argv) < 0)
return -1; return -1;
if(fetcharg(1, &arg1) < 0)
return -1; ip = namei(path, NAMEI_LOOKUP, 0, 0, 0);
if(checkstring(arg0) < 0)
return -1;
ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0);
if(ip == 0) if(ip == 0)
return -1; return -1;
@ -399,15 +356,14 @@ sys_exec(void)
goto bad; goto bad;
memset(mem, 0, sz); memset(mem, 0, sz);
// arg1 is a pointer to an array of pointers to string.
nargs = 0; nargs = 0;
argbytes = 0; argbytes = 0;
for(i = 0; ; i++){ for(i = 0;; i++){
if(fetchint(cp, arg1 + 4*i, &ap) < 0) if(fetchint(cp, argv + 4*i, (int*)&ap) < 0)
goto bad; goto bad;
if(ap == 0) if(ap == 0)
break; break;
len = checkstring(ap); len = fetchstr(cp, ap, &s);
if(len < 0) if(len < 0)
goto bad; goto bad;
nargs++; nargs++;
@ -432,9 +388,9 @@ sys_exec(void)
p1 = sp + 12; p1 = sp + 12;
p2 = sp + 12 + (nargs + 1) * 4; p2 = sp + 12 + (nargs + 1) * 4;
for(i = 0; i < nargs; i++){ for(i = 0; i < nargs; i++){
fetchint(cp, arg1 + 4*i, &ap); fetchint(cp, argv + 4*i, (int*)&ap);
len = checkstring(ap); len = fetchstr(cp, ap, &s);
memmove(mem + p2, cp->mem + ap, len + 1); memmove(mem + p2, s, len + 1);
*(uint*)(mem + p1) = p2; *(uint*)(mem + p1) = p2;
p1 += 4; p1 += 4;
p2 += len + 1; p2 += len + 1;

View file

@ -44,7 +44,7 @@ sys_kill(void)
{ {
int pid; int pid;
if(fetcharg(0, &pid) < 0) if(argint(0, &pid) < 0)
return -1; return -1;
return proc_kill(pid); return proc_kill(pid);
} }
@ -52,20 +52,19 @@ sys_kill(void)
int int
sys_getpid(void) sys_getpid(void)
{ {
struct proc *cp = curproc[cpu()]; return curproc[cpu()]->pid;
return cp->pid;
} }
int int
sys_sbrk(void) sys_sbrk(void)
{ {
uint addr; int addr;
int n; int n;
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
if(fetcharg(0, &n) < 0) if(argint(0, &n) < 0)
return -1; return -1;
if((addr = growproc(n)) == 0xffffffff) if((addr = growproc(n)) < 0)
return -1; return -1;
setupsegs(cp); setupsegs(cp);
return addr; return addr;