diff options
-rw-r--r-- | kernel/console.c | 18 | ||||
-rw-r--r-- | kernel/date.h | 8 | ||||
-rw-r--r-- | kernel/defs.h | 4 | ||||
-rw-r--r-- | kernel/plic.c | 2 | ||||
-rw-r--r-- | kernel/proc.c | 35 | ||||
-rw-r--r-- | kernel/syscall.c | 46 | ||||
-rw-r--r-- | kernel/sysfile.c | 29 | ||||
-rw-r--r-- | kernel/sysproc.c | 18 | ||||
-rw-r--r-- | kernel/trampoline.S | 31 | ||||
-rw-r--r-- | kernel/trap.c | 6 | ||||
-rw-r--r-- | kernel/uart.c | 24 | ||||
-rw-r--r-- | user/grep.c | 3 | ||||
-rw-r--r-- | user/user.h | 3 |
13 files changed, 106 insertions, 121 deletions
diff --git a/kernel/console.c b/kernel/console.c index d6eb209..05dc526 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -27,7 +27,7 @@ // // send one character to the uart. -// called by printf, and to echo input characters, +// called by printf(), and to echo input characters, // but not from write(). // void @@ -45,8 +45,8 @@ struct { struct spinlock lock; // input -#define INPUT_BUF 128 - char buf[INPUT_BUF]; +#define INPUT_BUF_SIZE 128 + char buf[INPUT_BUF_SIZE]; uint r; // Read index uint w; // Write index uint e; // Edit index @@ -96,7 +96,7 @@ consoleread(int user_dst, uint64 dst, int n) sleep(&cons.r, &cons.lock); } - c = cons.buf[cons.r++ % INPUT_BUF]; + c = cons.buf[cons.r++ % INPUT_BUF_SIZE]; if(c == C('D')){ // end-of-file if(n < target){ @@ -143,29 +143,29 @@ consoleintr(int c) break; case C('U'): // Kill line. while(cons.e != cons.w && - cons.buf[(cons.e-1) % INPUT_BUF] != '\n'){ + cons.buf[(cons.e-1) % INPUT_BUF_SIZE] != '\n'){ cons.e--; consputc(BACKSPACE); } break; case C('H'): // Backspace - case '\x7f': + case '\x7f': // Delete key if(cons.e != cons.w){ cons.e--; consputc(BACKSPACE); } break; default: - if(c != 0 && cons.e-cons.r < INPUT_BUF){ + if(c != 0 && cons.e-cons.r < INPUT_BUF_SIZE){ c = (c == '\r') ? '\n' : c; // echo back to the user. consputc(c); // store for consumption by consoleread(). - cons.buf[cons.e++ % INPUT_BUF] = c; + cons.buf[cons.e++ % INPUT_BUF_SIZE] = c; - if(c == '\n' || c == C('D') || cons.e == cons.r+INPUT_BUF){ + if(c == '\n' || c == C('D') || cons.e-cons.r == INPUT_BUF_SIZE){ // wake up consoleread() if a whole line (or end-of-file) // has arrived. cons.w = cons.e; diff --git a/kernel/date.h b/kernel/date.h deleted file mode 100644 index 94aec4b..0000000 --- a/kernel/date.h +++ /dev/null @@ -1,8 +0,0 @@ -struct rtcdate { - uint second; - uint minute; - uint hour; - uint day; - uint month; - uint year; -}; diff --git a/kernel/defs.h b/kernel/defs.h index e38ec00..7457b66 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -134,9 +134,9 @@ int strncmp(const char*, const char*, uint); char* strncpy(char*, const char*, int); // syscall.c -int argint(int, int*); +void argint(int, int*); int argstr(int, char*, int); -int argaddr(int, uint64 *); +void argaddr(int, uint64 *); int fetchstr(uint64, char*, int); int fetchaddr(uint64, uint64*); void syscall(); diff --git a/kernel/plic.c b/kernel/plic.c index d4fd122..4175db9 100644 --- a/kernel/plic.c +++ b/kernel/plic.c @@ -23,7 +23,7 @@ plicinithart(void) // set enable bits for this hart's S-mode // for the uart and virtio disk. - *(uint32*)PLIC_SENABLE(hart)= (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ); + *(uint32*)PLIC_SENABLE(hart) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ); // set this hart's S-mode priority threshold to 0. *(uint32*)PLIC_SPRIORITY(hart) = 0; diff --git a/kernel/proc.c b/kernel/proc.c index 5e37cb7..8d0ca8c 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -53,6 +53,7 @@ procinit(void) initlock(&wait_lock, "wait_lock"); for(p = proc; p < &proc[NPROC]; p++) { initlock(&p->lock, "proc"); + p->state = UNUSED; p->kstack = KSTACK((int) (p - proc)); } } @@ -170,8 +171,8 @@ freeproc(struct proc *p) p->state = UNUSED; } -// Create a user page table for a given process, -// with no user memory, but with trampoline pages. +// Create a user page table for a given process, with no user memory, +// but with trampoline and trapframe pages. pagetable_t proc_pagetable(struct proc *p) { @@ -192,7 +193,8 @@ proc_pagetable(struct proc *p) return 0; } - // map the trapframe just below TRAMPOLINE, for trampoline.S. + // map the trapframe page just below the trampoline page, for + // trampoline.S. if(mappages(pagetable, TRAPFRAME, PGSIZE, (uint64)(p->trapframe), PTE_R | PTE_W) < 0){ uvmunmap(pagetable, TRAMPOLINE, 1, 0); @@ -257,7 +259,7 @@ userinit(void) int growproc(int n) { - uint sz; + uint64 sz; struct proc *p = myproc(); sz = p->sz; @@ -388,7 +390,7 @@ exit(int status) int wait(uint64 addr) { - struct proc *np; + struct proc *pp; int havekids, pid; struct proc *p = myproc(); @@ -397,27 +399,27 @@ wait(uint64 addr) for(;;){ // Scan through table looking for exited children. havekids = 0; - for(np = proc; np < &proc[NPROC]; np++){ - if(np->parent == p){ + for(pp = proc; pp < &proc[NPROC]; pp++){ + if(pp->parent == p){ // make sure the child isn't still in exit() or swtch(). - acquire(&np->lock); + acquire(&pp->lock); havekids = 1; - if(np->state == ZOMBIE){ + if(pp->state == ZOMBIE){ // Found one. - pid = np->pid; - if(addr != 0 && copyout(p->pagetable, addr, (char *)&np->xstate, - sizeof(np->xstate)) < 0) { - release(&np->lock); + pid = pp->pid; + if(addr != 0 && copyout(p->pagetable, addr, (char *)&pp->xstate, + sizeof(pp->xstate)) < 0) { + release(&pp->lock); release(&wait_lock); return -1; } - freeproc(np); - release(&np->lock); + freeproc(pp); + release(&pp->lock); release(&wait_lock); return pid; } - release(&np->lock); + release(&pp->lock); } } @@ -658,6 +660,7 @@ procdump(void) { static char *states[] = { [UNUSED] "unused", + [USED] "used", [SLEEPING] "sleep ", [RUNNABLE] "runble", [RUNNING] "run ", diff --git a/kernel/syscall.c b/kernel/syscall.c index c1b3670..ee94696 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -12,7 +12,7 @@ int fetchaddr(uint64 addr, uint64 *ip) { struct proc *p = myproc(); - if(addr >= p->sz || addr+sizeof(uint64) > p->sz) + if(addr >= p->sz || addr+sizeof(uint64) > p->sz) // both tests needed, in case of overflow return -1; if(copyin(p->pagetable, (char *)ip, addr, sizeof(*ip)) != 0) return -1; @@ -25,9 +25,8 @@ int fetchstr(uint64 addr, char *buf, int max) { struct proc *p = myproc(); - int err = copyinstr(p->pagetable, buf, addr, max); - if(err < 0) - return err; + if(copyinstr(p->pagetable, buf, addr, max) < 0) + return -1; return strlen(buf); } @@ -54,21 +53,19 @@ argraw(int n) } // Fetch the nth 32-bit system call argument. -int +void argint(int n, int *ip) { *ip = argraw(n); - return 0; } // Retrieve an argument as a pointer. // Doesn't check for legality, since // copyin/copyout will do that. -int +void argaddr(int n, uint64 *ip) { *ip = argraw(n); - return 0; } // Fetch the nth word-sized system call argument as a null-terminated string. @@ -78,32 +75,31 @@ int argstr(int n, char *buf, int max) { uint64 addr; - if(argaddr(n, &addr) < 0) - return -1; + argaddr(n, &addr); return fetchstr(addr, buf, max); } -extern uint64 sys_chdir(void); -extern uint64 sys_close(void); -extern uint64 sys_dup(void); -extern uint64 sys_exec(void); -extern uint64 sys_exit(void); extern uint64 sys_fork(void); -extern uint64 sys_fstat(void); -extern uint64 sys_getpid(void); -extern uint64 sys_kill(void); -extern uint64 sys_link(void); -extern uint64 sys_mkdir(void); -extern uint64 sys_mknod(void); -extern uint64 sys_open(void); +extern uint64 sys_exit(void); +extern uint64 sys_wait(void); extern uint64 sys_pipe(void); extern uint64 sys_read(void); +extern uint64 sys_kill(void); +extern uint64 sys_exec(void); +extern uint64 sys_fstat(void); +extern uint64 sys_chdir(void); +extern uint64 sys_dup(void); +extern uint64 sys_getpid(void); extern uint64 sys_sbrk(void); extern uint64 sys_sleep(void); -extern uint64 sys_unlink(void); -extern uint64 sys_wait(void); -extern uint64 sys_write(void); extern uint64 sys_uptime(void); +extern uint64 sys_open(void); +extern uint64 sys_write(void); +extern uint64 sys_mknod(void); +extern uint64 sys_unlink(void); +extern uint64 sys_link(void); +extern uint64 sys_mkdir(void); +extern uint64 sys_close(void); static uint64 (*syscalls[])(void) = { [SYS_fork] sys_fork, diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 5dc453b..970a72a 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -24,8 +24,7 @@ argfd(int n, int *pfd, struct file **pf) int fd; struct file *f; - if(argint(n, &fd) < 0) - return -1; + argint(n, &fd); if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) return -1; if(pfd) @@ -73,7 +72,9 @@ sys_read(void) int n; uint64 p; - if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argaddr(1, &p) < 0) + argaddr(1, &p); + argint(2, &n); + if(argfd(0, 0, &f) < 0) return -1; return fileread(f, p, n); } @@ -84,8 +85,10 @@ sys_write(void) struct file *f; int n; uint64 p; - - if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argaddr(1, &p) < 0) + + argaddr(1, &p); + argint(2, &n); + if(argfd(0, 0, &f) < 0) return -1; return filewrite(f, p, n); @@ -110,7 +113,8 @@ sys_fstat(void) struct file *f; uint64 st; // user pointer to struct stat - if(argfd(0, 0, &f) < 0 || argaddr(1, &st) < 0) + argaddr(1, &st); + if(argfd(0, 0, &f) < 0) return -1; return filestat(f, st); } @@ -292,7 +296,8 @@ sys_open(void) struct inode *ip; int n; - if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0) + argint(1, &omode); + if((n = argstr(0, path, MAXPATH)) < 0) return -1; begin_op(); @@ -375,9 +380,9 @@ sys_mknod(void) int major, minor; begin_op(); + argint(1, &major); + argint(2, &minor); if((argstr(0, path, MAXPATH)) < 0 || - argint(1, &major) < 0 || - argint(2, &minor) < 0 || (ip = create(path, T_DEVICE, major, minor)) == 0){ end_op(); return -1; @@ -419,7 +424,8 @@ sys_exec(void) int i; uint64 uargv, uarg; - if(argstr(0, path, MAXPATH) < 0 || argaddr(1, &uargv) < 0){ + argaddr(1, &uargv); + if(argstr(0, path, MAXPATH) < 0) { return -1; } memset(argv, 0, sizeof(argv)); @@ -462,8 +468,7 @@ sys_pipe(void) int fd0, fd1; struct proc *p = myproc(); - if(argaddr(0, &fdarray) < 0) - return -1; + argaddr(0, &fdarray); if(pipealloc(&rf, &wf) < 0) return -1; fd0 = -1; diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 99a36a7..1de184e 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -1,7 +1,6 @@ #include "types.h" #include "riscv.h" #include "defs.h" -#include "date.h" #include "param.h" #include "memlayout.h" #include "spinlock.h" @@ -11,8 +10,7 @@ uint64 sys_exit(void) { int n; - if(argint(0, &n) < 0) - return -1; + argint(0, &n); exit(n); return 0; // not reached } @@ -33,19 +31,17 @@ uint64 sys_wait(void) { uint64 p; - if(argaddr(0, &p) < 0) - return -1; + argaddr(0, &p); return wait(p); } uint64 sys_sbrk(void) { - int addr; + uint64 addr; int n; - if(argint(0, &n) < 0) - return -1; + argint(0, &n); addr = myproc()->sz; if(growproc(n) < 0) return -1; @@ -58,8 +54,7 @@ sys_sleep(void) int n; uint ticks0; - if(argint(0, &n) < 0) - return -1; + argint(0, &n); acquire(&tickslock); ticks0 = ticks; while(ticks - ticks0 < n){ @@ -78,8 +73,7 @@ sys_kill(void) { int pid; - if(argint(0, &pid) < 0) - return -1; + argint(0, &pid); return kill(pid); } diff --git a/kernel/trampoline.S b/kernel/trampoline.S index 2ce4886..0aaa413 100644 --- a/kernel/trampoline.S +++ b/kernel/trampoline.S @@ -1,18 +1,19 @@ - # - # code to switch between user and kernel space. # - # this code is mapped at the same virtual address - # (TRAMPOLINE) in user and kernel space so that - # it continues to work when it switches page tables. - # - # kernel.ld causes this to be aligned - # to a page boundary. + # low-level code to handle traps from user space into + # the kernel, and returns from kernel to user. + # + # the kernel maps the page holding this code + # at the same virtual address (TRAMPOLINE) + # in user and kernel space so that it continues + # to work when it switches page tables. + # kernel.ld causes this code to start at + # a page boundary. # #include "riscv.h" #include "memlayout.h" - .section trampsec +.section trampsec .globl trampoline trampoline: .align 4 @@ -31,7 +32,7 @@ uservec: # each process has a separate p->trapframe memory area, # but it's mapped to the same virtual address - # (TRAPFRAME) in every process. + # (TRAPFRAME) in every process's user page table. li a0, TRAPFRAME # save the user registers in TRAPFRAME @@ -70,29 +71,27 @@ uservec: csrr t0, sscratch sd t0, 112(a0) - # restore kernel stack pointer from p->trapframe->kernel_sp + # initialize kernel stack pointer, from p->trapframe->kernel_sp ld sp, 8(a0) # make tp hold the current hartid, from p->trapframe->kernel_hartid ld tp, 32(a0) - # load the address of usertrap(), p->trapframe->kernel_trap + # load the address of usertrap(), from p->trapframe->kernel_trap ld t0, 16(a0) - # restore kernel page table from p->trapframe->kernel_satp + # load the kernel page table, from p->trapframe->kernel_satp ld t1, 0(a0) csrw satp, t1 sfence.vma zero, zero - # a0 is no longer valid, since the kernel page - # table does not specially map p->tf. - # jump to usertrap(), which does not return jr t0 .globl userret userret: # userret(pagetable) + # called by usertrapret() in trap.c to # switch from kernel to user. # a0: user page table, for satp. diff --git a/kernel/trap.c b/kernel/trap.c index 44c9cdc..512c850 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -60,8 +60,8 @@ usertrap(void) // but we want to return to the next instruction. p->trapframe->epc += 4; - // an interrupt will change sstatus &c registers, - // so don't enable until done with those registers. + // an interrupt will change sepc, scause, and sstatus, + // so enable only now that we're done with those registers. intr_on(); syscall(); @@ -101,7 +101,7 @@ usertrapret(void) w_stvec(trampoline_uservec); // set up trapframe values that uservec will need when - // the process next re-enters the kernel. + // the process next traps into the kernel. p->trapframe->kernel_satp = r_satp(); // kernel page table p->trapframe->kernel_sp = p->kstack + PGSIZE; // process's kernel stack p->trapframe->kernel_trap = (uint64)usertrap; diff --git a/kernel/uart.c b/kernel/uart.c index f75fb3c..e3b3b8a 100644 --- a/kernel/uart.c +++ b/kernel/uart.c @@ -92,22 +92,18 @@ uartputc(int c) for(;;) ; } - - while(1){ - if(uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE){ - // buffer is full. - // wait for uartstart() to open up space in the buffer. - sleep(&uart_tx_r, &uart_tx_lock); - } else { - uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c; - uart_tx_w += 1; - uartstart(); - release(&uart_tx_lock); - return; - } + while(uart_tx_w == uart_tx_r + UART_TX_BUF_SIZE){ + // buffer is full. + // wait for uartstart() to open up space in the buffer. + sleep(&uart_tx_r, &uart_tx_lock); } + uart_tx_buf[uart_tx_w % UART_TX_BUF_SIZE] = c; + uart_tx_w += 1; + uartstart(); + release(&uart_tx_lock); } + // alternate version of uartputc() that doesn't // use interrupts, for use by kernel printf() and // to echo characters. it spins waiting for the uart's @@ -175,7 +171,7 @@ uartgetc(void) // handle a uart interrupt, raised because input has // arrived, or the uart is ready for more output, or -// both. called from trap.c. +// both. called from devintr(). void uartintr(void) { diff --git a/user/grep.c b/user/grep.c index 19882b9..2315a0c 100644 --- a/user/grep.c +++ b/user/grep.c @@ -62,7 +62,8 @@ main(int argc, char *argv[]) } // Regexp matcher from Kernighan & Pike, -// The Practice of Programming, Chapter 9. +// The Practice of Programming, Chapter 9, or +// https://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html int matchhere(char*, char*); int matchstar(int, char*, char*); diff --git a/user/user.h b/user/user.h index b71ecda..4d398d5 100644 --- a/user/user.h +++ b/user/user.h @@ -1,5 +1,4 @@ struct stat; -struct rtcdate; // system calls int fork(void); @@ -10,7 +9,7 @@ int write(int, const void*, int); int read(int, void*, int); int close(int); int kill(int); -int exec(char*, char**); +int exec(const char*, char**); int open(const char*, int); int mknod(const char*, short, short); int unlink(const char*); |