diff --git a/Makefile b/Makefile index ded5bc2..2628613 100644 --- a/Makefile +++ b/Makefile @@ -188,6 +188,7 @@ UPROGS=\ $U/_grind\ $U/_wc\ $U/_zombie\ + $U/_alarmtest\ diff --git a/kernel/proc.c b/kernel/proc.c index 959b778..2f0feac 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -131,6 +131,11 @@ found: release(&p->lock); return 0; } + if((p->trapframe1 = (struct trapframe *)kalloc()) == 0){ + freeproc(p); + release(&p->lock); + return 0; + } // An empty user page table. p->pagetable = proc_pagetable(p); @@ -145,6 +150,8 @@ found: memset(&p->context, 0, sizeof(p->context)); p->context.ra = (uint64)forkret; p->context.sp = p->kstack + PGSIZE; + p->alarm_hdlr = 0; + p->alarm_intrv = p->alarm_ticks = 0; return p; } @@ -158,6 +165,9 @@ freeproc(struct proc *p) if(p->trapframe) kfree((void*)p->trapframe); p->trapframe = 0; + if(p->trapframe1) + kfree((void*)p->trapframe1); + p->trapframe1 = 0; if(p->pagetable) proc_freepagetable(p->pagetable, p->sz); p->pagetable = 0; diff --git a/kernel/proc.h b/kernel/proc.h index d021857..83da3f7 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -100,8 +100,12 @@ struct proc { uint64 sz; // Size of process memory (bytes) pagetable_t pagetable; // User page table struct trapframe *trapframe; // data page for trampoline.S + struct trapframe *trapframe1; // data page for trampoline.S struct context context; // swtch() here to run process struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory + int alarm_intrv; // alarm interval + uint64 alarm_hdlr; // alarm handler + int alarm_ticks; // ticks after last alarm char name[16]; // Process name (debugging) }; diff --git a/kernel/syscall.c b/kernel/syscall.c index ed65409..e4f006a 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -101,6 +101,8 @@ extern uint64 sys_unlink(void); extern uint64 sys_link(void); extern uint64 sys_mkdir(void); extern uint64 sys_close(void); +extern uint64 sys_sigalarm(void); +extern uint64 sys_sigreturn(void); // An array mapping syscall numbers from syscall.h // to the function that handles the system call. @@ -126,6 +128,8 @@ static uint64 (*syscalls[])(void) = { [SYS_link] sys_link, [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, +[SYS_sigalarm] sys_sigalarm, +[SYS_sigreturn] sys_sigreturn, }; void diff --git a/kernel/syscall.h b/kernel/syscall.h index bc5f356..349ed72 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,3 +20,5 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 +#define SYS_sigalarm 22 +#define SYS_sigreturn 23 diff --git a/kernel/sysproc.c b/kernel/sysproc.c index fe64ad3..3d845ea 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -92,3 +92,28 @@ sys_uptime(void) release(&tickslock); return xticks; } + +uint64 +sys_sigalarm(void) +{ + int interval; + uint64 hdlr; + argint(0, &interval); + argaddr(1, &hdlr); + struct proc* p = myproc(); + + p->alarm_ticks = 0; + p->alarm_intrv = interval; + p->alarm_hdlr = hdlr; + + return 0; +} + +uint64 +sys_sigreturn(void) +{ + struct proc* p = myproc(); + memmove(p->trapframe, p->trapframe1, sizeof(struct trapframe)); + p->alarm_ticks = 0; + return p->trapframe->a0; +} \ No newline at end of file diff --git a/kernel/trap.c b/kernel/trap.c index 512c850..518ee15 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -67,6 +67,18 @@ usertrap(void) syscall(); } else if((which_dev = devintr()) != 0){ // ok + if (which_dev == 2) { + acquire(&p->lock); + if (p->alarm_intrv) { + if (p->alarm_ticks <= p->alarm_intrv) + p->alarm_ticks ++; + if (p->alarm_intrv == p->alarm_ticks) { + memmove(p->trapframe1, p->trapframe, sizeof(struct trapframe)); + p->trapframe->epc = p->alarm_hdlr; + } + } + release(&p->lock); + } } else { printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid); printf(" sepc=%p stval=%p\n", r_sepc(), r_stval()); diff --git a/time.txt b/time.txt new file mode 100644 index 0000000..bf0d87a --- /dev/null +++ b/time.txt @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/user/user.h b/user/user.h index 4d398d5..9426153 100644 --- a/user/user.h +++ b/user/user.h @@ -22,6 +22,8 @@ int getpid(void); char* sbrk(int); int sleep(int); int uptime(void); +int sigalarm(int ticks, void (*handler)()); +int sigreturn(void); // ulib.c int stat(const char*, struct stat*); diff --git a/user/usys.pl b/user/usys.pl index 01e426e..fa548b0 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,3 +36,5 @@ entry("getpid"); entry("sbrk"); entry("sleep"); entry("uptime"); +entry("sigalarm"); +entry("sigreturn");