diff --git a/Makefile b/Makefile index c06447c..d827b03 100644 --- a/Makefile +++ b/Makefile @@ -104,6 +104,7 @@ UPROGS=\ _ln\ _ls\ _mkdir\ + _mytest\ _rm\ _sh\ _usertests\ diff --git a/defs.h b/defs.h index 661f761..7301e4e 100644 --- a/defs.h +++ b/defs.h @@ -7,6 +7,11 @@ struct proc; struct spinlock; struct stat; +#ifndef SIGACT +#define SIGACT +typedef void (*sigact)(void); +#endif + // bio.c void binit(void); struct buf* bread(uint, uint); @@ -96,11 +101,13 @@ struct proc* curproc(void); void exit(void); int growproc(int); int kill(int); +int kill_signal(int, int); void pinit(void); void procdump(void); void scheduler(void) __attribute__((noreturn)); void setupsegs(struct proc*); void sleep(void*, struct spinlock*); +int signal(int, sigact); void userinit(void); int wait(void); void wakeup(void*); @@ -130,10 +137,13 @@ char* strncpy(char*, const char*, int); // syscall.c int argint(int, int*); int argptr(int, char**, int); +int argfunc(int, sigact *); int argstr(int, char**); int fetchint(struct proc*, uint, int*); int fetchstr(struct proc*, uint, char**); +int fetchfunc(struct proc *, uint, sigact *); void syscall(void); +int storefunc(struct proc *, uint, sigact); // timer.c void timer_init(void); diff --git a/mytest.c b/mytest.c new file mode 100644 index 0000000..6fb0984 --- /dev/null +++ b/mytest.c @@ -0,0 +1,30 @@ +#include "types.h" +#include "stat.h" +#include "user.h" +#include "fcntl.h" + +int n = 0, done = 0; +char buf[1024]; + +void +aiofunc(void) { + printf(1, "AIO signal!\n"); + printf(1, "n: %d - buf: %s\n", n, buf); + done = 1; +} + +int +main(int argc, char **argv) { + int fd; + + memset(buf, 0, 1024); + fd = open("testfile", O_RDWR); + signal(7, aiofunc); + //n = aio_read(fd, buf, 1024); + printf(1, "read n: %d\n", n); + if (n > 0) + printf(1, "buf: %s\n", buf); + while(!done) { sleep(1); } + close(fd); + exit(); +} diff --git a/proc.c b/proc.c index 523b6d2..088e235 100644 --- a/proc.c +++ b/proc.c @@ -118,7 +118,8 @@ copyproc(struct proc *p) np->tf = (struct trapframe*)(np->kstack + KSTACKSIZE) - 1; if(p){ // Copy process state from p. - np->parent = p; + np->parent = p; + np->ppid = p->pid; memmove(np->tf, p->tf, sizeof(*np->tf)); np->sz = p->sz; @@ -141,6 +142,10 @@ copyproc(struct proc *p) np->context.eip = (uint)forkret; np->context.esp = (uint)np->tf; + // Init the signals table + for (i = 0; i < 15; i++) + np->signals[i] = -1; + // Clear %eax so that fork system call returns 0 in child. np->tf->eax = 0; return np; @@ -176,6 +181,9 @@ userinit(void) p->state = RUNNABLE; initproc = p; + + memset(p->signals, 0, sizeof(int *) * 16); + } // Return currently running process. @@ -355,6 +363,58 @@ kill(int pid) return -1; } +// Kill the process with the given pid. +// Process won't actually exit until it returns +// to user space (see trap in trap.c). +int +kill_signal(int pid, int signal) +{ + struct proc *p; + + cprintf("Inside mykill: pid %d signal %d\n", pid, signal); + + if ((signal < 0) || (signal > 15)) + return -1; + + acquire(&proc_table_lock); + for(p = proc; p < &proc[NPROC]; p++){ + if(p->pid == pid){ + cprintf("callee: pid %d signal[%d] = %p\n", p->pid, signal, p->signals[signal]); + cprintf("caller: pid %d signal[%d] = %p\n", cp->pid, signal, cp->signals[signal]); + if (p->signals[signal] == -1) { + p->killed = 1; + cprintf("Sigkill for pid: %d\n", pid); + } else { + // put signal handler on p's stack and increment sp + //storefunc(p, p->tf->esp - 4, p->signals[signal]); + storefunc(p, p->tf->esp - 4, p->tf->eip); + p->tf->esp -= 4; + p->tf->eip = p->signals[signal]; + cprintf("Signal set on p's (%d) stack: signum %d sigfunc %p\n", pid, signal, p->signals[signal]); + } + // Wake process from sleep if necessary. + if(p->state == SLEEPING) + p->state = RUNNABLE; + release(&proc_table_lock); + return 0; + } + } + release(&proc_table_lock); + return -1; +} + +// Implements the signal system call functionality +int +signal(int signal, sigact handler) +{ + if ((signal < 0) || (signal > 15)) + return -1; + + cp->signals[signal] = handler; + cprintf("Signal set for pid %d: %d %p\n", cp->pid, signal, handler); + return 0; +} + // Exit the current process. Does not return. // Exited processes remain in the zombie state // until their parent calls wait() to find out they exited. diff --git a/proc.h b/proc.h index 502361d..8ecd0a2 100644 --- a/proc.h +++ b/proc.h @@ -26,6 +26,11 @@ struct context { enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; +#ifndef SIGACT +#define SIGACT +typedef void (*sigact)(void); +#endif + // Per-process state struct proc { char *mem; // Start of process memory (kernel address) @@ -41,6 +46,8 @@ struct proc { struct context context; // Switch here to run process struct trapframe *tf; // Trap frame for current interrupt char name[16]; // Process name (debugging) + sigact signals[16]; + int ppid; }; // Process memory is laid out contiguously, low addresses first: diff --git a/syscall.c b/syscall.c index 2a037d1..7f8068a 100644 --- a/syscall.c +++ b/syscall.c @@ -30,6 +30,7 @@ fetchstr(struct proc *p, uint addr, char **pp) { char *s, *ep; + if(addr >= p->sz) return -1; *pp = p->mem + addr; @@ -40,6 +41,16 @@ fetchstr(struct proc *p, uint addr, char **pp) return -1; } +// Fetch the int at addr from process p. +int +fetchfunc(struct proc *p, uint addr, sigact *fp) +{ + if(addr >= p->sz || addr+4 > p->sz) + return -1; + *fp = *(sigact *)(p->mem + addr); + return 0; +} + // Fetch the nth 32-bit system call argument. int argint(int n, int *ip) @@ -47,6 +58,23 @@ argint(int n, int *ip) return fetchint(cp, cp->tf->esp + 4 + 4*n, ip); } +// Fetch the nth 32-bit system call argument. +int +argfunc(int n, sigact *fp) +{ + return fetchfunc(cp, cp->tf->esp + 4 + 4*n, fp); +} + +// Store the function pointer at addr from process p. +int +storefunc(struct proc *p, uint addr, sigact fp) +{ + if(addr >= p->sz) + return -1; + *(sigact *)(p->mem + addr) = fp; + return 0; +} + // Fetch the nth word-sized system call argument as a pointer // to a block of memory of size n bytes. Check that the pointer // lies within the process address space. @@ -96,6 +124,9 @@ extern int sys_sleep(void); extern int sys_unlink(void); extern int sys_wait(void); extern int sys_write(void); +extern int sys_kill_signal(void); +extern int sys_signal(void); +extern int sys_getppid(void); static int (*syscalls[])(void) = { [SYS_chdir] sys_chdir, @@ -118,6 +149,9 @@ static int (*syscalls[])(void) = { [SYS_unlink] sys_unlink, [SYS_wait] sys_wait, [SYS_write] sys_write, +[SYS_kill_signal] sys_kill_signal, +[SYS_signal] sys_signal, +[SYS_getppid] sys_getppid, }; void diff --git a/syscall.h b/syscall.h index f4b7807..c863c01 100644 --- a/syscall.h +++ b/syscall.h @@ -19,3 +19,6 @@ #define SYS_getpid 18 #define SYS_sbrk 19 #define SYS_sleep 20 +#define SYS_signal 21 +#define SYS_kill_signal 22 +#define SYS_getppid 23 diff --git a/sysproc.c b/sysproc.c index 990a426..59cd9d5 100644 --- a/sysproc.c +++ b/sysproc.c @@ -41,6 +41,34 @@ sys_kill(void) } int +sys_kill_signal(void) +{ + int pid; + int signal; + + if(argint(0, &pid) < 0) + return -1; + if(argint(1, &signal) < 0) + return -1; + cprintf("sys_kill_signal: %d %d\n", pid, signal); + return kill_signal(pid, signal); +} + +int +sys_signal(void) +{ + int signum; + sigact handler = 0; + + if(argint(0, &signum) < 0) + return -1; + if(argfunc(1, &handler) < 0) + return -1; + cprintf("sys_signal: %d %p\n", signum, handler); + return signal(signum, handler); +} + +int sys_getpid(void) { return cp->pid; @@ -78,3 +106,9 @@ sys_sleep(void) release(&tickslock); return 0; } + +int +sys_getppid(void) +{ + return cp->ppid; +} diff --git a/user.h b/user.h index 8280b2e..941f593 100644 --- a/user.h +++ b/user.h @@ -9,6 +9,8 @@ int write(int, void*, int); int read(int, void*, int); int close(int); int kill(int); +int kill_signal(int, int); +void signal(int signal, void(*handler)(void)); int exec(char*, char**); int open(char*, int); int mknod(char*, short, short); @@ -19,6 +21,7 @@ int mkdir(char*); int chdir(char*); int dup(int); int getpid(); +int getppid(); char* sbrk(int); int sleep(int); diff --git a/usys.S b/usys.S index 380cb91..665ea99 100644 --- a/usys.S +++ b/usys.S @@ -28,3 +28,6 @@ STUB(dup) STUB(getpid) STUB(sbrk) STUB(sleep) +STUB(kill_signal) +STUB(signal) +STUB(getppid) \ No newline at end of file