summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/console.c18
-rw-r--r--kernel/date.h8
-rw-r--r--kernel/defs.h4
-rw-r--r--kernel/plic.c2
-rw-r--r--kernel/proc.c35
-rw-r--r--kernel/syscall.c46
-rw-r--r--kernel/sysfile.c29
-rw-r--r--kernel/sysproc.c18
-rw-r--r--kernel/trampoline.S31
-rw-r--r--kernel/trap.c6
-rw-r--r--kernel/uart.c24
-rw-r--r--user/grep.c3
-rw-r--r--user/user.h3
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*);