From 8102452c7fbab088e092a99945d2c0b48e5615a1 Mon Sep 17 00:00:00 2001 From: hheik <4469778+hheik@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:15:43 +0300 Subject: [PATCH] Formatted *.c files --- .clang-format | 4 + kernel/bio.c | 179 +- kernel/console.c | 228 +- kernel/exec.c | 259 ++- kernel/file.c | 245 +- kernel/fs.c | 789 +++---- kernel/kalloc.c | 74 +- kernel/log.c | 276 ++- kernel/main.c | 67 +- kernel/pipe.c | 198 +- kernel/plic.c | 46 +- kernel/printf.c | 174 +- kernel/proc.c | 881 ++++---- kernel/ramdisk.c | 43 +- kernel/sleeplock.c | 63 +- kernel/spinlock.c | 132 +- kernel/start.c | 98 +- kernel/string.c | 145 +- kernel/syscall.c | 144 +- kernel/sysfile.c | 749 +++---- kernel/sysproc.c | 116 +- kernel/trap.c | 280 ++- kernel/uart.c | 213 +- kernel/virtio_disk.c | 462 ++-- kernel/vm.c | 553 +++-- mkfs/mkfs.c | 406 ++-- user/cat.c | 58 +- user/echo.c | 24 +- user/forktest.c | 82 +- user/grep.c | 147 +- user/grind.c | 639 +++--- user/init.c | 74 +- user/kill.c | 20 +- user/ln.c | 18 +- user/ls.c | 132 +- user/mkdir.c | 28 +- user/printf.c | 171 +- user/rm.c | 28 +- user/sh.c | 739 +++--- user/stressfs.c | 48 +- user/ulib.c | 196 +- user/umalloc.c | 122 +- user/usertests.c | 5103 ++++++++++++++++++++---------------------- user/wc.c | 80 +- user/zombie.c | 10 +- 45 files changed, 6910 insertions(+), 7633 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..b9e081c --- /dev/null +++ b/.clang-format @@ -0,0 +1,4 @@ +SortIncludes: Never +UseTab: Always +IndentWidth: 4 +TabWidth: 4 diff --git a/kernel/bio.c b/kernel/bio.c index 60d91a6..36df05e 100644 --- a/kernel/bio.c +++ b/kernel/bio.c @@ -13,7 +13,6 @@ // * Only one process at a time can use a buffer, // so do not keep them longer than necessary. - #include "types.h" #include "param.h" #include "spinlock.h" @@ -24,130 +23,116 @@ #include "buf.h" struct { - struct spinlock lock; - struct buf buf[NBUF]; + struct spinlock lock; + struct buf buf[NBUF]; - // Linked list of all buffers, through prev/next. - // Sorted by how recently the buffer was used. - // head.next is most recent, head.prev is least. - struct buf head; + // Linked list of all buffers, through prev/next. + // Sorted by how recently the buffer was used. + // head.next is most recent, head.prev is least. + struct buf head; } bcache; -void -binit(void) -{ - struct buf *b; +void binit(void) { + struct buf *b; - initlock(&bcache.lock, "bcache"); + initlock(&bcache.lock, "bcache"); - // Create linked list of buffers - bcache.head.prev = &bcache.head; - bcache.head.next = &bcache.head; - for(b = bcache.buf; b < bcache.buf+NBUF; b++){ - b->next = bcache.head.next; - b->prev = &bcache.head; - initsleeplock(&b->lock, "buffer"); - bcache.head.next->prev = b; - bcache.head.next = b; - } + // Create linked list of buffers + bcache.head.prev = &bcache.head; + bcache.head.next = &bcache.head; + for (b = bcache.buf; b < bcache.buf + NBUF; b++) { + b->next = bcache.head.next; + b->prev = &bcache.head; + initsleeplock(&b->lock, "buffer"); + bcache.head.next->prev = b; + bcache.head.next = b; + } } // Look through buffer cache for block on device dev. // If not found, allocate a buffer. // In either case, return locked buffer. -static struct buf* -bget(uint dev, uint blockno) -{ - struct buf *b; +static struct buf *bget(uint dev, uint blockno) { + struct buf *b; - acquire(&bcache.lock); + acquire(&bcache.lock); - // Is the block already cached? - for(b = bcache.head.next; b != &bcache.head; b = b->next){ - if(b->dev == dev && b->blockno == blockno){ - b->refcnt++; - release(&bcache.lock); - acquiresleep(&b->lock); - return b; - } - } + // Is the block already cached? + for (b = bcache.head.next; b != &bcache.head; b = b->next) { + if (b->dev == dev && b->blockno == blockno) { + b->refcnt++; + release(&bcache.lock); + acquiresleep(&b->lock); + return b; + } + } - // Not cached. - // Recycle the least recently used (LRU) unused buffer. - for(b = bcache.head.prev; b != &bcache.head; b = b->prev){ - if(b->refcnt == 0) { - b->dev = dev; - b->blockno = blockno; - b->valid = 0; - b->refcnt = 1; - release(&bcache.lock); - acquiresleep(&b->lock); - return b; - } - } - panic("bget: no buffers"); + // Not cached. + // Recycle the least recently used (LRU) unused buffer. + for (b = bcache.head.prev; b != &bcache.head; b = b->prev) { + if (b->refcnt == 0) { + b->dev = dev; + b->blockno = blockno; + b->valid = 0; + b->refcnt = 1; + release(&bcache.lock); + acquiresleep(&b->lock); + return b; + } + } + panic("bget: no buffers"); } // Return a locked buf with the contents of the indicated block. -struct buf* -bread(uint dev, uint blockno) -{ - struct buf *b; +struct buf *bread(uint dev, uint blockno) { + struct buf *b; - b = bget(dev, blockno); - if(!b->valid) { - virtio_disk_rw(b, 0); - b->valid = 1; - } - return b; + b = bget(dev, blockno); + if (!b->valid) { + virtio_disk_rw(b, 0); + b->valid = 1; + } + return b; } // Write b's contents to disk. Must be locked. -void -bwrite(struct buf *b) -{ - if(!holdingsleep(&b->lock)) - panic("bwrite"); - virtio_disk_rw(b, 1); +void bwrite(struct buf *b) { + if (!holdingsleep(&b->lock)) + panic("bwrite"); + virtio_disk_rw(b, 1); } // Release a locked buffer. // Move to the head of the most-recently-used list. -void -brelse(struct buf *b) -{ - if(!holdingsleep(&b->lock)) - panic("brelse"); +void brelse(struct buf *b) { + if (!holdingsleep(&b->lock)) + panic("brelse"); - releasesleep(&b->lock); + releasesleep(&b->lock); - acquire(&bcache.lock); - b->refcnt--; - if (b->refcnt == 0) { - // no one is waiting for it. - b->next->prev = b->prev; - b->prev->next = b->next; - b->next = bcache.head.next; - b->prev = &bcache.head; - bcache.head.next->prev = b; - bcache.head.next = b; - } - - release(&bcache.lock); + acquire(&bcache.lock); + b->refcnt--; + if (b->refcnt == 0) { + // no one is waiting for it. + b->next->prev = b->prev; + b->prev->next = b->next; + b->next = bcache.head.next; + b->prev = &bcache.head; + bcache.head.next->prev = b; + bcache.head.next = b; + } + + release(&bcache.lock); } -void -bpin(struct buf *b) { - acquire(&bcache.lock); - b->refcnt++; - release(&bcache.lock); +void bpin(struct buf *b) { + acquire(&bcache.lock); + b->refcnt++; + release(&bcache.lock); } -void -bunpin(struct buf *b) { - acquire(&bcache.lock); - b->refcnt--; - release(&bcache.lock); +void bunpin(struct buf *b) { + acquire(&bcache.lock); + b->refcnt--; + release(&bcache.lock); } - - diff --git a/kernel/console.c b/kernel/console.c index 05dc526..0e94a21 100644 --- a/kernel/console.c +++ b/kernel/console.c @@ -23,51 +23,49 @@ #include "proc.h" #define BACKSPACE 0x100 -#define C(x) ((x)-'@') // Control-x +#define C(x) ((x) - '@') // Control-x // // send one character to the uart. // called by printf(), and to echo input characters, // but not from write(). // -void -consputc(int c) -{ - if(c == BACKSPACE){ - // if the user typed backspace, overwrite with a space. - uartputc_sync('\b'); uartputc_sync(' '); uartputc_sync('\b'); - } else { - uartputc_sync(c); - } +void consputc(int c) { + if (c == BACKSPACE) { + // if the user typed backspace, overwrite with a space. + uartputc_sync('\b'); + uartputc_sync(' '); + uartputc_sync('\b'); + } else { + uartputc_sync(c); + } } struct { - struct spinlock lock; - - // input + struct spinlock lock; + + // input #define INPUT_BUF_SIZE 128 - char buf[INPUT_BUF_SIZE]; - uint r; // Read index - uint w; // Write index - uint e; // Edit index + char buf[INPUT_BUF_SIZE]; + uint r; // Read index + uint w; // Write index + uint e; // Edit index } cons; // // user write()s to the console go here. // -int -consolewrite(int user_src, uint64 src, int n) -{ - int i; +int consolewrite(int user_src, uint64 src, int n) { + int i; - for(i = 0; i < n; i++){ - char c; - if(either_copyin(&c, user_src, src+i, 1) == -1) - break; - uartputc(c); - } + for (i = 0; i < n; i++) { + char c; + if (either_copyin(&c, user_src, src + i, 1) == -1) + break; + uartputc(c); + } - return i; + return i; } // @@ -76,54 +74,52 @@ consolewrite(int user_src, uint64 src, int n) // user_dist indicates whether dst is a user // or kernel address. // -int -consoleread(int user_dst, uint64 dst, int n) -{ - uint target; - int c; - char cbuf; +int consoleread(int user_dst, uint64 dst, int n) { + uint target; + int c; + char cbuf; - target = n; - acquire(&cons.lock); - while(n > 0){ - // wait until interrupt handler has put some - // input into cons.buffer. - while(cons.r == cons.w){ - if(killed(myproc())){ - release(&cons.lock); - return -1; - } - sleep(&cons.r, &cons.lock); - } + target = n; + acquire(&cons.lock); + while (n > 0) { + // wait until interrupt handler has put some + // input into cons.buffer. + while (cons.r == cons.w) { + if (killed(myproc())) { + release(&cons.lock); + return -1; + } + sleep(&cons.r, &cons.lock); + } - c = cons.buf[cons.r++ % INPUT_BUF_SIZE]; + c = cons.buf[cons.r++ % INPUT_BUF_SIZE]; - if(c == C('D')){ // end-of-file - if(n < target){ - // Save ^D for next time, to make sure - // caller gets a 0-byte result. - cons.r--; - } - break; - } + if (c == C('D')) { // end-of-file + if (n < target) { + // Save ^D for next time, to make sure + // caller gets a 0-byte result. + cons.r--; + } + break; + } - // copy the input byte to the user-space buffer. - cbuf = c; - if(either_copyout(user_dst, dst, &cbuf, 1) == -1) - break; + // copy the input byte to the user-space buffer. + cbuf = c; + if (either_copyout(user_dst, dst, &cbuf, 1) == -1) + break; - dst++; - --n; + dst++; + --n; - if(c == '\n'){ - // a whole line has arrived, return to - // the user-level read(). - break; - } - } - release(&cons.lock); + if (c == '\n') { + // a whole line has arrived, return to + // the user-level read(). + break; + } + } + release(&cons.lock); - return target - n; + return target - n; } // @@ -132,61 +128,57 @@ consoleread(int user_dst, uint64 dst, int n) // do erase/kill processing, append to cons.buf, // wake up consoleread() if a whole line has arrived. // -void -consoleintr(int c) -{ - acquire(&cons.lock); +void consoleintr(int c) { + acquire(&cons.lock); - switch(c){ - case C('P'): // Print process list. - procdump(); - break; - case C('U'): // Kill line. - while(cons.e != cons.w && - cons.buf[(cons.e-1) % INPUT_BUF_SIZE] != '\n'){ - cons.e--; - consputc(BACKSPACE); - } - break; - case C('H'): // Backspace - case '\x7f': // Delete key - if(cons.e != cons.w){ - cons.e--; - consputc(BACKSPACE); - } - break; - default: - if(c != 0 && cons.e-cons.r < INPUT_BUF_SIZE){ - c = (c == '\r') ? '\n' : c; + switch (c) { + case C('P'): // Print process list. + procdump(); + break; + case C('U'): // Kill line. + while (cons.e != cons.w && + cons.buf[(cons.e - 1) % INPUT_BUF_SIZE] != '\n') { + cons.e--; + consputc(BACKSPACE); + } + break; + case C('H'): // Backspace + case '\x7f': // Delete key + if (cons.e != cons.w) { + cons.e--; + consputc(BACKSPACE); + } + break; + default: + if (c != 0 && cons.e - cons.r < INPUT_BUF_SIZE) { + c = (c == '\r') ? '\n' : c; - // echo back to the user. - consputc(c); + // echo back to the user. + consputc(c); - // store for consumption by consoleread(). - cons.buf[cons.e++ % INPUT_BUF_SIZE] = c; + // store for consumption by consoleread(). + cons.buf[cons.e++ % INPUT_BUF_SIZE] = c; - 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; - wakeup(&cons.r); - } - } - break; - } - - release(&cons.lock); + 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; + wakeup(&cons.r); + } + } + break; + } + + release(&cons.lock); } -void -consoleinit(void) -{ - initlock(&cons.lock, "cons"); +void consoleinit(void) { + initlock(&cons.lock, "cons"); - uartinit(); + uartinit(); - // connect read and write system calls - // to consoleread and consolewrite. - devsw[CONSOLE].read = consoleread; - devsw[CONSOLE].write = consolewrite; + // connect read and write system calls + // to consoleread and consolewrite. + devsw[CONSOLE].read = consoleread; + devsw[CONSOLE].write = consolewrite; } diff --git a/kernel/exec.c b/kernel/exec.c index e18bbb6..8a79877 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -9,158 +9,155 @@ static int loadseg(pde_t *, uint64, struct inode *, uint, uint); -int flags2perm(int flags) -{ - int perm = 0; - if(flags & 0x1) - perm = PTE_X; - if(flags & 0x2) - perm |= PTE_W; - return perm; +int flags2perm(int flags) { + int perm = 0; + if (flags & 0x1) + perm = PTE_X; + if (flags & 0x2) + perm |= PTE_W; + return perm; } -int -exec(char *path, char **argv) -{ - char *s, *last; - int i, off; - uint64 argc, sz = 0, sp, ustack[MAXARG], stackbase; - struct elfhdr elf; - struct inode *ip; - struct proghdr ph; - pagetable_t pagetable = 0, oldpagetable; - struct proc *p = myproc(); +int exec(char *path, char **argv) { + char *s, *last; + int i, off; + uint64 argc, sz = 0, sp, ustack[MAXARG], stackbase; + struct elfhdr elf; + struct inode *ip; + struct proghdr ph; + pagetable_t pagetable = 0, oldpagetable; + struct proc *p = myproc(); - begin_op(); + begin_op(); - if((ip = namei(path)) == 0){ - end_op(); - return -1; - } - ilock(ip); + if ((ip = namei(path)) == 0) { + end_op(); + return -1; + } + ilock(ip); - // Check ELF header - if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)) - goto bad; + // Check ELF header + if (readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)) + goto bad; - if(elf.magic != ELF_MAGIC) - goto bad; + if (elf.magic != ELF_MAGIC) + goto bad; - if((pagetable = proc_pagetable(p)) == 0) - goto bad; + if ((pagetable = proc_pagetable(p)) == 0) + goto bad; - // Load program into memory. - for(i=0, off=elf.phoff; isz; + p = myproc(); + uint64 oldsz = p->sz; - // Allocate two pages at the next page boundary. - // Make the first inaccessible as a stack guard. - // Use the second as the user stack. - sz = PGROUNDUP(sz); - uint64 sz1; - if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE, PTE_W)) == 0) - goto bad; - sz = sz1; - uvmclear(pagetable, sz-2*PGSIZE); - sp = sz; - stackbase = sp - PGSIZE; + // Allocate two pages at the next page boundary. + // Make the first inaccessible as a stack guard. + // Use the second as the user stack. + sz = PGROUNDUP(sz); + uint64 sz1; + if ((sz1 = uvmalloc(pagetable, sz, sz + 2 * PGSIZE, PTE_W)) == 0) + goto bad; + sz = sz1; + uvmclear(pagetable, sz - 2 * PGSIZE); + sp = sz; + stackbase = sp - PGSIZE; - // Push argument strings, prepare rest of stack in ustack. - for(argc = 0; argv[argc]; argc++) { - if(argc >= MAXARG) - goto bad; - sp -= strlen(argv[argc]) + 1; - sp -= sp % 16; // riscv sp must be 16-byte aligned - if(sp < stackbase) - goto bad; - if(copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0) - goto bad; - ustack[argc] = sp; - } - ustack[argc] = 0; + // Push argument strings, prepare rest of stack in ustack. + for (argc = 0; argv[argc]; argc++) { + if (argc >= MAXARG) + goto bad; + sp -= strlen(argv[argc]) + 1; + sp -= sp % 16; // riscv sp must be 16-byte aligned + if (sp < stackbase) + goto bad; + if (copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0) + goto bad; + ustack[argc] = sp; + } + ustack[argc] = 0; - // push the array of argv[] pointers. - sp -= (argc+1) * sizeof(uint64); - sp -= sp % 16; - if(sp < stackbase) - goto bad; - if(copyout(pagetable, sp, (char *)ustack, (argc+1)*sizeof(uint64)) < 0) - goto bad; + // push the array of argv[] pointers. + sp -= (argc + 1) * sizeof(uint64); + sp -= sp % 16; + if (sp < stackbase) + goto bad; + if (copyout(pagetable, sp, (char *)ustack, (argc + 1) * sizeof(uint64)) < 0) + goto bad; - // arguments to user main(argc, argv) - // argc is returned via the system call return - // value, which goes in a0. - p->trapframe->a1 = sp; + // arguments to user main(argc, argv) + // argc is returned via the system call return + // value, which goes in a0. + p->trapframe->a1 = sp; - // Save program name for debugging. - for(last=s=path; *s; s++) - if(*s == '/') - last = s+1; - safestrcpy(p->name, last, sizeof(p->name)); - - // Commit to the user image. - oldpagetable = p->pagetable; - p->pagetable = pagetable; - p->sz = sz; - p->trapframe->epc = elf.entry; // initial program counter = main - p->trapframe->sp = sp; // initial stack pointer - proc_freepagetable(oldpagetable, oldsz); + // Save program name for debugging. + for (last = s = path; *s; s++) + if (*s == '/') + last = s + 1; + safestrcpy(p->name, last, sizeof(p->name)); - return argc; // this ends up in a0, the first argument to main(argc, argv) + // Commit to the user image. + oldpagetable = p->pagetable; + p->pagetable = pagetable; + p->sz = sz; + p->trapframe->epc = elf.entry; // initial program counter = main + p->trapframe->sp = sp; // initial stack pointer + proc_freepagetable(oldpagetable, oldsz); - bad: - if(pagetable) - proc_freepagetable(pagetable, sz); - if(ip){ - iunlockput(ip); - end_op(); - } - return -1; + return argc; // this ends up in a0, the first argument to main(argc, argv) + +bad: + if (pagetable) + proc_freepagetable(pagetable, sz); + if (ip) { + iunlockput(ip); + end_op(); + } + return -1; } // Load a program segment into pagetable at virtual address va. // va must be page-aligned // and the pages from va to va+sz must already be mapped. // Returns 0 on success, -1 on failure. -static int -loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset, uint sz) -{ - uint i, n; - uint64 pa; +static int loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, + uint offset, uint sz) { + uint i, n; + uint64 pa; - for(i = 0; i < sz; i += PGSIZE){ - pa = walkaddr(pagetable, va + i); - if(pa == 0) - panic("loadseg: address should exist"); - if(sz - i < PGSIZE) - n = sz - i; - else - n = PGSIZE; - if(readi(ip, 0, (uint64)pa, offset+i, n) != n) - return -1; - } - - return 0; + for (i = 0; i < sz; i += PGSIZE) { + pa = walkaddr(pagetable, va + i); + if (pa == 0) + panic("loadseg: address should exist"); + if (sz - i < PGSIZE) + n = sz - i; + else + n = PGSIZE; + if (readi(ip, 0, (uint64)pa, offset + i, n) != n) + return -1; + } + + return 0; } diff --git a/kernel/file.c b/kernel/file.c index 25fa226..24204bb 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -15,168 +15,151 @@ struct devsw devsw[NDEV]; struct { - struct spinlock lock; - struct file file[NFILE]; + struct spinlock lock; + struct file file[NFILE]; } ftable; -void -fileinit(void) -{ - initlock(&ftable.lock, "ftable"); -} +void fileinit(void) { initlock(&ftable.lock, "ftable"); } // Allocate a file structure. -struct file* -filealloc(void) -{ - struct file *f; +struct file *filealloc(void) { + struct file *f; - acquire(&ftable.lock); - for(f = ftable.file; f < ftable.file + NFILE; f++){ - if(f->ref == 0){ - f->ref = 1; - release(&ftable.lock); - return f; - } - } - release(&ftable.lock); - return 0; + acquire(&ftable.lock); + for (f = ftable.file; f < ftable.file + NFILE; f++) { + if (f->ref == 0) { + f->ref = 1; + release(&ftable.lock); + return f; + } + } + release(&ftable.lock); + return 0; } // Increment ref count for file f. -struct file* -filedup(struct file *f) -{ - acquire(&ftable.lock); - if(f->ref < 1) - panic("filedup"); - f->ref++; - release(&ftable.lock); - return f; +struct file *filedup(struct file *f) { + acquire(&ftable.lock); + if (f->ref < 1) + panic("filedup"); + f->ref++; + release(&ftable.lock); + return f; } // Close file f. (Decrement ref count, close when reaches 0.) -void -fileclose(struct file *f) -{ - struct file ff; +void fileclose(struct file *f) { + struct file ff; - acquire(&ftable.lock); - if(f->ref < 1) - panic("fileclose"); - if(--f->ref > 0){ - release(&ftable.lock); - return; - } - ff = *f; - f->ref = 0; - f->type = FD_NONE; - release(&ftable.lock); + acquire(&ftable.lock); + if (f->ref < 1) + panic("fileclose"); + if (--f->ref > 0) { + release(&ftable.lock); + return; + } + ff = *f; + f->ref = 0; + f->type = FD_NONE; + release(&ftable.lock); - if(ff.type == FD_PIPE){ - pipeclose(ff.pipe, ff.writable); - } else if(ff.type == FD_INODE || ff.type == FD_DEVICE){ - begin_op(); - iput(ff.ip); - end_op(); - } + if (ff.type == FD_PIPE) { + pipeclose(ff.pipe, ff.writable); + } else if (ff.type == FD_INODE || ff.type == FD_DEVICE) { + begin_op(); + iput(ff.ip); + end_op(); + } } // Get metadata about file f. // addr is a user virtual address, pointing to a struct stat. -int -filestat(struct file *f, uint64 addr) -{ - struct proc *p = myproc(); - struct stat st; - - if(f->type == FD_INODE || f->type == FD_DEVICE){ - ilock(f->ip); - stati(f->ip, &st); - iunlock(f->ip); - if(copyout(p->pagetable, addr, (char *)&st, sizeof(st)) < 0) - return -1; - return 0; - } - return -1; +int filestat(struct file *f, uint64 addr) { + struct proc *p = myproc(); + struct stat st; + + if (f->type == FD_INODE || f->type == FD_DEVICE) { + ilock(f->ip); + stati(f->ip, &st); + iunlock(f->ip); + if (copyout(p->pagetable, addr, (char *)&st, sizeof(st)) < 0) + return -1; + return 0; + } + return -1; } // Read from file f. // addr is a user virtual address. -int -fileread(struct file *f, uint64 addr, int n) -{ - int r = 0; +int fileread(struct file *f, uint64 addr, int n) { + int r = 0; - if(f->readable == 0) - return -1; + if (f->readable == 0) + return -1; - if(f->type == FD_PIPE){ - r = piperead(f->pipe, addr, n); - } else if(f->type == FD_DEVICE){ - if(f->major < 0 || f->major >= NDEV || !devsw[f->major].read) - return -1; - r = devsw[f->major].read(1, addr, n); - } else if(f->type == FD_INODE){ - ilock(f->ip); - if((r = readi(f->ip, 1, addr, f->off, n)) > 0) - f->off += r; - iunlock(f->ip); - } else { - panic("fileread"); - } + if (f->type == FD_PIPE) { + r = piperead(f->pipe, addr, n); + } else if (f->type == FD_DEVICE) { + if (f->major < 0 || f->major >= NDEV || !devsw[f->major].read) + return -1; + r = devsw[f->major].read(1, addr, n); + } else if (f->type == FD_INODE) { + ilock(f->ip); + if ((r = readi(f->ip, 1, addr, f->off, n)) > 0) + f->off += r; + iunlock(f->ip); + } else { + panic("fileread"); + } - return r; + return r; } // Write to file f. // addr is a user virtual address. -int -filewrite(struct file *f, uint64 addr, int n) -{ - int r, ret = 0; +int filewrite(struct file *f, uint64 addr, int n) { + int r, ret = 0; - if(f->writable == 0) - return -1; + if (f->writable == 0) + return -1; - if(f->type == FD_PIPE){ - ret = pipewrite(f->pipe, addr, n); - } else if(f->type == FD_DEVICE){ - if(f->major < 0 || f->major >= NDEV || !devsw[f->major].write) - return -1; - ret = devsw[f->major].write(1, addr, n); - } else if(f->type == FD_INODE){ - // write a few blocks at a time to avoid exceeding - // the maximum log transaction size, including - // i-node, indirect block, allocation blocks, - // and 2 blocks of slop for non-aligned writes. - // this really belongs lower down, since writei() - // might be writing a device like the console. - int max = ((MAXOPBLOCKS-1-1-2) / 2) * BSIZE; - int i = 0; - while(i < n){ - int n1 = n - i; - if(n1 > max) - n1 = max; + if (f->type == FD_PIPE) { + ret = pipewrite(f->pipe, addr, n); + } else if (f->type == FD_DEVICE) { + if (f->major < 0 || f->major >= NDEV || !devsw[f->major].write) + return -1; + ret = devsw[f->major].write(1, addr, n); + } else if (f->type == FD_INODE) { + // write a few blocks at a time to avoid exceeding + // the maximum log transaction size, including + // i-node, indirect block, allocation blocks, + // and 2 blocks of slop for non-aligned writes. + // this really belongs lower down, since writei() + // might be writing a device like the console. + int max = ((MAXOPBLOCKS - 1 - 1 - 2) / 2) * BSIZE; + int i = 0; + while (i < n) { + int n1 = n - i; + if (n1 > max) + n1 = max; - begin_op(); - ilock(f->ip); - if ((r = writei(f->ip, 1, addr + i, f->off, n1)) > 0) - f->off += r; - iunlock(f->ip); - end_op(); + begin_op(); + ilock(f->ip); + if ((r = writei(f->ip, 1, addr + i, f->off, n1)) > 0) + f->off += r; + iunlock(f->ip); + end_op(); - if(r != n1){ - // error from writei - break; - } - i += r; - } - ret = (i == n ? n : -1); - } else { - panic("filewrite"); - } + if (r != n1) { + // error from writei + break; + } + i += r; + } + ret = (i == n ? n : -1); + } else { + panic("filewrite"); + } - return ret; + return ret; } - diff --git a/kernel/fs.c b/kernel/fs.c index c6bab15..fa5d54d 100644 --- a/kernel/fs.c +++ b/kernel/fs.c @@ -24,84 +24,75 @@ #define min(a, b) ((a) < (b) ? (a) : (b)) // there should be one superblock per disk device, but we run with // only one device -struct superblock sb; +struct superblock sb; // Read the super block. -static void -readsb(int dev, struct superblock *sb) -{ - struct buf *bp; +static void readsb(int dev, struct superblock *sb) { + struct buf *bp; - bp = bread(dev, 1); - memmove(sb, bp->data, sizeof(*sb)); - brelse(bp); + bp = bread(dev, 1); + memmove(sb, bp->data, sizeof(*sb)); + brelse(bp); } // Init fs -void -fsinit(int dev) { - readsb(dev, &sb); - if(sb.magic != FSMAGIC) - panic("invalid file system"); - initlog(dev, &sb); +void fsinit(int dev) { + readsb(dev, &sb); + if (sb.magic != FSMAGIC) + panic("invalid file system"); + initlog(dev, &sb); } // Zero a block. -static void -bzero(int dev, int bno) -{ - struct buf *bp; +static void bzero(int dev, int bno) { + struct buf *bp; - bp = bread(dev, bno); - memset(bp->data, 0, BSIZE); - log_write(bp); - brelse(bp); + bp = bread(dev, bno); + memset(bp->data, 0, BSIZE); + log_write(bp); + brelse(bp); } // Blocks. // Allocate a zeroed disk block. // returns 0 if out of disk space. -static uint -balloc(uint dev) -{ - int b, bi, m; - struct buf *bp; +static uint balloc(uint dev) { + int b, bi, m; + struct buf *bp; - bp = 0; - for(b = 0; b < sb.size; b += BPB){ - bp = bread(dev, BBLOCK(b, sb)); - for(bi = 0; bi < BPB && b + bi < sb.size; bi++){ - m = 1 << (bi % 8); - if((bp->data[bi/8] & m) == 0){ // Is block free? - bp->data[bi/8] |= m; // Mark block in use. - log_write(bp); - brelse(bp); - bzero(dev, b + bi); - return b + bi; - } - } - brelse(bp); - } - printf("balloc: out of blocks\n"); - return 0; + bp = 0; + for (b = 0; b < sb.size; b += BPB) { + bp = bread(dev, BBLOCK(b, sb)); + for (bi = 0; bi < BPB && b + bi < sb.size; bi++) { + m = 1 << (bi % 8); + if ((bp->data[bi / 8] & m) == 0) { // Is block free? + bp->data[bi / 8] |= m; // Mark block in use. + log_write(bp); + brelse(bp); + bzero(dev, b + bi); + return b + bi; + } + } + brelse(bp); + } + printf("balloc: out of blocks\n"); + return 0; } // Free a disk block. -static void -bfree(int dev, uint b) -{ - struct buf *bp; - int bi, m; +static void bfree(int dev, uint b) { + struct buf *bp; + int bi, m; - bp = bread(dev, BBLOCK(b, sb)); - bi = b % BPB; - m = 1 << (bi % 8); - if((bp->data[bi/8] & m) == 0) - panic("freeing free block"); - bp->data[bi/8] &= ~m; - log_write(bp); - brelse(bp); + bp = bread(dev, BBLOCK(b, sb)); + bi = b % BPB; + m = 1 << (bi % 8); + if ((bp->data[bi / 8] & m) == 0) + panic("freeing free block"); + bp->data[bi / 8] &= ~m; + log_write(bp); + brelse(bp); } // Inodes. @@ -174,156 +165,142 @@ bfree(int dev, uint b) // read or write that inode's ip->valid, ip->size, ip->type, &c. struct { - struct spinlock lock; - struct inode inode[NINODE]; + struct spinlock lock; + struct inode inode[NINODE]; } itable; -void -iinit() -{ - int i = 0; - - initlock(&itable.lock, "itable"); - for(i = 0; i < NINODE; i++) { - initsleeplock(&itable.inode[i].lock, "inode"); - } +void iinit() { + int i = 0; + + initlock(&itable.lock, "itable"); + for (i = 0; i < NINODE; i++) { + initsleeplock(&itable.inode[i].lock, "inode"); + } } -static struct inode* iget(uint dev, uint inum); +static struct inode *iget(uint dev, uint inum); // Allocate an inode on device dev. // Mark it as allocated by giving it type type. // Returns an unlocked but allocated and referenced inode, // or NULL if there is no free inode. -struct inode* -ialloc(uint dev, short type) -{ - int inum; - struct buf *bp; - struct dinode *dip; +struct inode *ialloc(uint dev, short type) { + int inum; + struct buf *bp; + struct dinode *dip; - for(inum = 1; inum < sb.ninodes; inum++){ - bp = bread(dev, IBLOCK(inum, sb)); - dip = (struct dinode*)bp->data + inum%IPB; - if(dip->type == 0){ // a free inode - memset(dip, 0, sizeof(*dip)); - dip->type = type; - log_write(bp); // mark it allocated on the disk - brelse(bp); - return iget(dev, inum); - } - brelse(bp); - } - printf("ialloc: no inodes\n"); - return 0; + for (inum = 1; inum < sb.ninodes; inum++) { + bp = bread(dev, IBLOCK(inum, sb)); + dip = (struct dinode *)bp->data + inum % IPB; + if (dip->type == 0) { // a free inode + memset(dip, 0, sizeof(*dip)); + dip->type = type; + log_write(bp); // mark it allocated on the disk + brelse(bp); + return iget(dev, inum); + } + brelse(bp); + } + printf("ialloc: no inodes\n"); + return 0; } // Copy a modified in-memory inode to disk. // Must be called after every change to an ip->xxx field // that lives on disk. // Caller must hold ip->lock. -void -iupdate(struct inode *ip) -{ - struct buf *bp; - struct dinode *dip; +void iupdate(struct inode *ip) { + struct buf *bp; + struct dinode *dip; - bp = bread(ip->dev, IBLOCK(ip->inum, sb)); - dip = (struct dinode*)bp->data + ip->inum%IPB; - dip->type = ip->type; - dip->major = ip->major; - dip->minor = ip->minor; - dip->nlink = ip->nlink; - dip->size = ip->size; - memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); - log_write(bp); - brelse(bp); + bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + dip = (struct dinode *)bp->data + ip->inum % IPB; + dip->type = ip->type; + dip->major = ip->major; + dip->minor = ip->minor; + dip->nlink = ip->nlink; + dip->size = ip->size; + memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); + log_write(bp); + brelse(bp); } // Find the inode with number inum on device dev // and return the in-memory copy. Does not lock // the inode and does not read it from disk. -static struct inode* -iget(uint dev, uint inum) -{ - struct inode *ip, *empty; +static struct inode *iget(uint dev, uint inum) { + struct inode *ip, *empty; - acquire(&itable.lock); + acquire(&itable.lock); - // Is the inode already in the table? - empty = 0; - for(ip = &itable.inode[0]; ip < &itable.inode[NINODE]; ip++){ - if(ip->ref > 0 && ip->dev == dev && ip->inum == inum){ - ip->ref++; - release(&itable.lock); - return ip; - } - if(empty == 0 && ip->ref == 0) // Remember empty slot. - empty = ip; - } + // Is the inode already in the table? + empty = 0; + for (ip = &itable.inode[0]; ip < &itable.inode[NINODE]; ip++) { + if (ip->ref > 0 && ip->dev == dev && ip->inum == inum) { + ip->ref++; + release(&itable.lock); + return ip; + } + if (empty == 0 && ip->ref == 0) // Remember empty slot. + empty = ip; + } - // Recycle an inode entry. - if(empty == 0) - panic("iget: no inodes"); + // Recycle an inode entry. + if (empty == 0) + panic("iget: no inodes"); - ip = empty; - ip->dev = dev; - ip->inum = inum; - ip->ref = 1; - ip->valid = 0; - release(&itable.lock); + ip = empty; + ip->dev = dev; + ip->inum = inum; + ip->ref = 1; + ip->valid = 0; + release(&itable.lock); - return ip; + return ip; } // Increment reference count for ip. // Returns ip to enable ip = idup(ip1) idiom. -struct inode* -idup(struct inode *ip) -{ - acquire(&itable.lock); - ip->ref++; - release(&itable.lock); - return ip; +struct inode *idup(struct inode *ip) { + acquire(&itable.lock); + ip->ref++; + release(&itable.lock); + return ip; } // Lock the given inode. // Reads the inode from disk if necessary. -void -ilock(struct inode *ip) -{ - struct buf *bp; - struct dinode *dip; +void ilock(struct inode *ip) { + struct buf *bp; + struct dinode *dip; - if(ip == 0 || ip->ref < 1) - panic("ilock"); + if (ip == 0 || ip->ref < 1) + panic("ilock"); - acquiresleep(&ip->lock); + acquiresleep(&ip->lock); - if(ip->valid == 0){ - bp = bread(ip->dev, IBLOCK(ip->inum, sb)); - dip = (struct dinode*)bp->data + ip->inum%IPB; - ip->type = dip->type; - ip->major = dip->major; - ip->minor = dip->minor; - ip->nlink = dip->nlink; - ip->size = dip->size; - memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); - brelse(bp); - ip->valid = 1; - if(ip->type == 0) - panic("ilock: no type"); - } + if (ip->valid == 0) { + bp = bread(ip->dev, IBLOCK(ip->inum, sb)); + dip = (struct dinode *)bp->data + ip->inum % IPB; + ip->type = dip->type; + ip->major = dip->major; + ip->minor = dip->minor; + ip->nlink = dip->nlink; + ip->size = dip->size; + memmove(ip->addrs, dip->addrs, sizeof(ip->addrs)); + brelse(bp); + ip->valid = 1; + if (ip->type == 0) + panic("ilock: no type"); + } } // Unlock the given inode. -void -iunlock(struct inode *ip) -{ - if(ip == 0 || !holdingsleep(&ip->lock) || ip->ref < 1) - panic("iunlock"); +void iunlock(struct inode *ip) { + if (ip == 0 || !holdingsleep(&ip->lock) || ip->ref < 1) + panic("iunlock"); - releasesleep(&ip->lock); + releasesleep(&ip->lock); } // Drop a reference to an in-memory inode. @@ -333,40 +310,36 @@ iunlock(struct inode *ip) // to it, free the inode (and its content) on disk. // All calls to iput() must be inside a transaction in // case it has to free the inode. -void -iput(struct inode *ip) -{ - acquire(&itable.lock); +void iput(struct inode *ip) { + acquire(&itable.lock); - if(ip->ref == 1 && ip->valid && ip->nlink == 0){ - // inode has no links and no other references: truncate and free. + if (ip->ref == 1 && ip->valid && ip->nlink == 0) { + // inode has no links and no other references: truncate and free. - // ip->ref == 1 means no other process can have ip locked, - // so this acquiresleep() won't block (or deadlock). - acquiresleep(&ip->lock); + // ip->ref == 1 means no other process can have ip locked, + // so this acquiresleep() won't block (or deadlock). + acquiresleep(&ip->lock); - release(&itable.lock); + release(&itable.lock); - itrunc(ip); - ip->type = 0; - iupdate(ip); - ip->valid = 0; + itrunc(ip); + ip->type = 0; + iupdate(ip); + ip->valid = 0; - releasesleep(&ip->lock); + releasesleep(&ip->lock); - acquire(&itable.lock); - } + acquire(&itable.lock); + } - ip->ref--; - release(&itable.lock); + ip->ref--; + release(&itable.lock); } // Common idiom: unlock, then put. -void -iunlockput(struct inode *ip) -{ - iunlock(ip); - iput(ip); +void iunlockput(struct inode *ip) { + iunlock(ip); + iput(ip); } // Inode content @@ -379,120 +352,112 @@ iunlockput(struct inode *ip) // Return the disk block address of the nth block in inode ip. // If there is no such block, bmap allocates one. // returns 0 if out of disk space. -static uint -bmap(struct inode *ip, uint bn) -{ - uint addr, *a; - struct buf *bp; +static uint bmap(struct inode *ip, uint bn) { + uint addr, *a; + struct buf *bp; - if(bn < NDIRECT){ - if((addr = ip->addrs[bn]) == 0){ - addr = balloc(ip->dev); - if(addr == 0) - return 0; - ip->addrs[bn] = addr; - } - return addr; - } - bn -= NDIRECT; + if (bn < NDIRECT) { + if ((addr = ip->addrs[bn]) == 0) { + addr = balloc(ip->dev); + if (addr == 0) + return 0; + ip->addrs[bn] = addr; + } + return addr; + } + bn -= NDIRECT; - if(bn < NINDIRECT){ - // Load indirect block, allocating if necessary. - if((addr = ip->addrs[NDIRECT]) == 0){ - addr = balloc(ip->dev); - if(addr == 0) - return 0; - ip->addrs[NDIRECT] = addr; - } - bp = bread(ip->dev, addr); - a = (uint*)bp->data; - if((addr = a[bn]) == 0){ - addr = balloc(ip->dev); - if(addr){ - a[bn] = addr; - log_write(bp); - } - } - brelse(bp); - return addr; - } + if (bn < NINDIRECT) { + // Load indirect block, allocating if necessary. + if ((addr = ip->addrs[NDIRECT]) == 0) { + addr = balloc(ip->dev); + if (addr == 0) + return 0; + ip->addrs[NDIRECT] = addr; + } + bp = bread(ip->dev, addr); + a = (uint *)bp->data; + if ((addr = a[bn]) == 0) { + addr = balloc(ip->dev); + if (addr) { + a[bn] = addr; + log_write(bp); + } + } + brelse(bp); + return addr; + } - panic("bmap: out of range"); + panic("bmap: out of range"); } // Truncate inode (discard contents). // Caller must hold ip->lock. -void -itrunc(struct inode *ip) -{ - int i, j; - struct buf *bp; - uint *a; +void itrunc(struct inode *ip) { + int i, j; + struct buf *bp; + uint *a; - for(i = 0; i < NDIRECT; i++){ - if(ip->addrs[i]){ - bfree(ip->dev, ip->addrs[i]); - ip->addrs[i] = 0; - } - } + for (i = 0; i < NDIRECT; i++) { + if (ip->addrs[i]) { + bfree(ip->dev, ip->addrs[i]); + ip->addrs[i] = 0; + } + } - if(ip->addrs[NDIRECT]){ - bp = bread(ip->dev, ip->addrs[NDIRECT]); - a = (uint*)bp->data; - for(j = 0; j < NINDIRECT; j++){ - if(a[j]) - bfree(ip->dev, a[j]); - } - brelse(bp); - bfree(ip->dev, ip->addrs[NDIRECT]); - ip->addrs[NDIRECT] = 0; - } + if (ip->addrs[NDIRECT]) { + bp = bread(ip->dev, ip->addrs[NDIRECT]); + a = (uint *)bp->data; + for (j = 0; j < NINDIRECT; j++) { + if (a[j]) + bfree(ip->dev, a[j]); + } + brelse(bp); + bfree(ip->dev, ip->addrs[NDIRECT]); + ip->addrs[NDIRECT] = 0; + } - ip->size = 0; - iupdate(ip); + ip->size = 0; + iupdate(ip); } // Copy stat information from inode. // Caller must hold ip->lock. -void -stati(struct inode *ip, struct stat *st) -{ - st->dev = ip->dev; - st->ino = ip->inum; - st->type = ip->type; - st->nlink = ip->nlink; - st->size = ip->size; +void stati(struct inode *ip, struct stat *st) { + st->dev = ip->dev; + st->ino = ip->inum; + st->type = ip->type; + st->nlink = ip->nlink; + st->size = ip->size; } // Read data from inode. // Caller must hold ip->lock. // If user_dst==1, then dst is a user virtual address; // otherwise, dst is a kernel address. -int -readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) -{ - uint tot, m; - struct buf *bp; +int readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) { + uint tot, m; + struct buf *bp; - if(off > ip->size || off + n < off) - return 0; - if(off + n > ip->size) - n = ip->size - off; + if (off > ip->size || off + n < off) + return 0; + if (off + n > ip->size) + n = ip->size - off; - for(tot=0; totdev, addr); - m = min(n - tot, BSIZE - off%BSIZE); - if(either_copyout(user_dst, dst, bp->data + (off % BSIZE), m) == -1) { - brelse(bp); - tot = -1; - break; - } - brelse(bp); - } - return tot; + for (tot = 0; tot < n; tot += m, off += m, dst += m) { + uint addr = bmap(ip, off / BSIZE); + if (addr == 0) + break; + bp = bread(ip->dev, addr); + m = min(n - tot, BSIZE - off % BSIZE); + if (either_copyout(user_dst, dst, bp->data + (off % BSIZE), m) == -1) { + brelse(bp); + tot = -1; + break; + } + brelse(bp); + } + return tot; } // Write data to inode. @@ -502,107 +467,97 @@ readi(struct inode *ip, int user_dst, uint64 dst, uint off, uint n) // Returns the number of bytes successfully written. // If the return value is less than the requested n, // there was an error of some kind. -int -writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) -{ - uint tot, m; - struct buf *bp; +int writei(struct inode *ip, int user_src, uint64 src, uint off, uint n) { + uint tot, m; + struct buf *bp; - if(off > ip->size || off + n < off) - return -1; - if(off + n > MAXFILE*BSIZE) - return -1; + if (off > ip->size || off + n < off) + return -1; + if (off + n > MAXFILE * BSIZE) + return -1; - for(tot=0; totdev, addr); - m = min(n - tot, BSIZE - off%BSIZE); - if(either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) { - brelse(bp); - break; - } - log_write(bp); - brelse(bp); - } + for (tot = 0; tot < n; tot += m, off += m, src += m) { + uint addr = bmap(ip, off / BSIZE); + if (addr == 0) + break; + bp = bread(ip->dev, addr); + m = min(n - tot, BSIZE - off % BSIZE); + if (either_copyin(bp->data + (off % BSIZE), user_src, src, m) == -1) { + brelse(bp); + break; + } + log_write(bp); + brelse(bp); + } - if(off > ip->size) - ip->size = off; + if (off > ip->size) + ip->size = off; - // write the i-node back to disk even if the size didn't change - // because the loop above might have called bmap() and added a new - // block to ip->addrs[]. - iupdate(ip); + // write the i-node back to disk even if the size didn't change + // because the loop above might have called bmap() and added a new + // block to ip->addrs[]. + iupdate(ip); - return tot; + return tot; } // Directories -int -namecmp(const char *s, const char *t) -{ - return strncmp(s, t, DIRSIZ); -} +int namecmp(const char *s, const char *t) { return strncmp(s, t, DIRSIZ); } // Look for a directory entry in a directory. // If found, set *poff to byte offset of entry. -struct inode* -dirlookup(struct inode *dp, char *name, uint *poff) -{ - uint off, inum; - struct dirent de; +struct inode *dirlookup(struct inode *dp, char *name, uint *poff) { + uint off, inum; + struct dirent de; - if(dp->type != T_DIR) - panic("dirlookup not DIR"); + if (dp->type != T_DIR) + panic("dirlookup not DIR"); - for(off = 0; off < dp->size; off += sizeof(de)){ - if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) - panic("dirlookup read"); - if(de.inum == 0) - continue; - if(namecmp(name, de.name) == 0){ - // entry matches path element - if(poff) - *poff = off; - inum = de.inum; - return iget(dp->dev, inum); - } - } + for (off = 0; off < dp->size; off += sizeof(de)) { + if (readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) + panic("dirlookup read"); + if (de.inum == 0) + continue; + if (namecmp(name, de.name) == 0) { + // entry matches path element + if (poff) + *poff = off; + inum = de.inum; + return iget(dp->dev, inum); + } + } - return 0; + return 0; } // Write a new directory entry (name, inum) into the directory dp. // Returns 0 on success, -1 on failure (e.g. out of disk blocks). -int -dirlink(struct inode *dp, char *name, uint inum) -{ - int off; - struct dirent de; - struct inode *ip; +int dirlink(struct inode *dp, char *name, uint inum) { + int off; + struct dirent de; + struct inode *ip; - // Check that name is not present. - if((ip = dirlookup(dp, name, 0)) != 0){ - iput(ip); - return -1; - } + // Check that name is not present. + if ((ip = dirlookup(dp, name, 0)) != 0) { + iput(ip); + return -1; + } - // Look for an empty dirent. - for(off = 0; off < dp->size; off += sizeof(de)){ - if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) - panic("dirlink read"); - if(de.inum == 0) - break; - } + // Look for an empty dirent. + for (off = 0; off < dp->size; off += sizeof(de)) { + if (readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) + panic("dirlink read"); + if (de.inum == 0) + break; + } - strncpy(de.name, name, DIRSIZ); - de.inum = inum; - if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) - return -1; + strncpy(de.name, name, DIRSIZ); + de.inum = inum; + if (writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) + return -1; - return 0; + return 0; } // Paths @@ -619,79 +574,71 @@ dirlink(struct inode *dp, char *name, uint inum) // skipelem("a", name) = "", setting name = "a" // skipelem("", name) = skipelem("////", name) = 0 // -static char* -skipelem(char *path, char *name) -{ - char *s; - int len; +static char *skipelem(char *path, char *name) { + char *s; + int len; - while(*path == '/') - path++; - if(*path == 0) - return 0; - s = path; - while(*path != '/' && *path != 0) - path++; - len = path - s; - if(len >= DIRSIZ) - memmove(name, s, DIRSIZ); - else { - memmove(name, s, len); - name[len] = 0; - } - while(*path == '/') - path++; - return path; + while (*path == '/') + path++; + if (*path == 0) + return 0; + s = path; + while (*path != '/' && *path != 0) + path++; + len = path - s; + if (len >= DIRSIZ) + memmove(name, s, DIRSIZ); + else { + memmove(name, s, len); + name[len] = 0; + } + while (*path == '/') + path++; + return path; } // Look up and return the inode for a path name. // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. // Must be called inside a transaction since it calls iput(). -static struct inode* -namex(char *path, int nameiparent, char *name) -{ - struct inode *ip, *next; +static struct inode *namex(char *path, int nameiparent, char *name) { + struct inode *ip, *next; - if(*path == '/') - ip = iget(ROOTDEV, ROOTINO); - else - ip = idup(myproc()->cwd); + if (*path == '/') + ip = iget(ROOTDEV, ROOTINO); + else + ip = idup(myproc()->cwd); - while((path = skipelem(path, name)) != 0){ - ilock(ip); - if(ip->type != T_DIR){ - iunlockput(ip); - return 0; - } - if(nameiparent && *path == '\0'){ - // Stop one level early. - iunlock(ip); - return ip; - } - if((next = dirlookup(ip, name, 0)) == 0){ - iunlockput(ip); - return 0; - } - iunlockput(ip); - ip = next; - } - if(nameiparent){ - iput(ip); - return 0; - } - return ip; + while ((path = skipelem(path, name)) != 0) { + ilock(ip); + if (ip->type != T_DIR) { + iunlockput(ip); + return 0; + } + if (nameiparent && *path == '\0') { + // Stop one level early. + iunlock(ip); + return ip; + } + if ((next = dirlookup(ip, name, 0)) == 0) { + iunlockput(ip); + return 0; + } + iunlockput(ip); + ip = next; + } + if (nameiparent) { + iput(ip); + return 0; + } + return ip; } -struct inode* -namei(char *path) -{ - char name[DIRSIZ]; - return namex(path, 0, name); +struct inode *namei(char *path) { + char name[DIRSIZ]; + return namex(path, 0, name); } -struct inode* -nameiparent(char *path, char *name) -{ - return namex(path, 1, name); +struct inode *nameiparent(char *path, char *name) { + return namex(path, 1, name); } diff --git a/kernel/kalloc.c b/kernel/kalloc.c index 0699e7e..e469623 100644 --- a/kernel/kalloc.c +++ b/kernel/kalloc.c @@ -12,71 +12,63 @@ void freerange(void *pa_start, void *pa_end); extern char end[]; // first address after kernel. - // defined by kernel.ld. + // defined by kernel.ld. struct run { - struct run *next; + struct run *next; }; struct { - struct spinlock lock; - struct run *freelist; + struct spinlock lock; + struct run *freelist; } kmem; -void -kinit() -{ - initlock(&kmem.lock, "kmem"); - freerange(end, (void*)PHYSTOP); +void kinit() { + initlock(&kmem.lock, "kmem"); + freerange(end, (void *)PHYSTOP); } -void -freerange(void *pa_start, void *pa_end) -{ - char *p; - p = (char*)PGROUNDUP((uint64)pa_start); - for(; p + PGSIZE <= (char*)pa_end; p += PGSIZE) - kfree(p); +void freerange(void *pa_start, void *pa_end) { + char *p; + p = (char *)PGROUNDUP((uint64)pa_start); + for (; p + PGSIZE <= (char *)pa_end; p += PGSIZE) + kfree(p); } // Free the page of physical memory pointed at by pa, // which normally should have been returned by a // call to kalloc(). (The exception is when // initializing the allocator; see kinit above.) -void -kfree(void *pa) -{ - struct run *r; +void kfree(void *pa) { + struct run *r; - if(((uint64)pa % PGSIZE) != 0 || (char*)pa < end || (uint64)pa >= PHYSTOP) - panic("kfree"); + if (((uint64)pa % PGSIZE) != 0 || (char *)pa < end || (uint64)pa >= PHYSTOP) + panic("kfree"); - // Fill with junk to catch dangling refs. - memset(pa, 1, PGSIZE); + // Fill with junk to catch dangling refs. + memset(pa, 1, PGSIZE); - r = (struct run*)pa; + r = (struct run *)pa; - acquire(&kmem.lock); - r->next = kmem.freelist; - kmem.freelist = r; - release(&kmem.lock); + acquire(&kmem.lock); + r->next = kmem.freelist; + kmem.freelist = r; + release(&kmem.lock); } // Allocate one 4096-byte page of physical memory. // Returns a pointer that the kernel can use. // Returns 0 if the memory cannot be allocated. -void * -kalloc(void) -{ - struct run *r; +void *kalloc(void) { + struct run *r; - acquire(&kmem.lock); - r = kmem.freelist; - if(r) - kmem.freelist = r->next; - release(&kmem.lock); + acquire(&kmem.lock); + r = kmem.freelist; + if (r) + kmem.freelist = r->next; + release(&kmem.lock); - if(r) - memset((char*)r, 5, PGSIZE); // fill with junk - return (void*)r; + if (r) + memset((char *)r, 5, PGSIZE); // fill with junk + return (void *)r; } diff --git a/kernel/log.c b/kernel/log.c index 5b58306..b78a9e1 100644 --- a/kernel/log.c +++ b/kernel/log.c @@ -33,173 +33,156 @@ // Contents of the header block, used for both the on-disk header block // and to keep track in memory of logged block# before commit. struct logheader { - int n; - int block[LOGSIZE]; + int n; + int block[LOGSIZE]; }; struct log { - struct spinlock lock; - int start; - int size; - int outstanding; // how many FS sys calls are executing. - int committing; // in commit(), please wait. - int dev; - struct logheader lh; + struct spinlock lock; + int start; + int size; + int outstanding; // how many FS sys calls are executing. + int committing; // in commit(), please wait. + int dev; + struct logheader lh; }; struct log log; static void recover_from_log(void); static void commit(); -void -initlog(int dev, struct superblock *sb) -{ - if (sizeof(struct logheader) >= BSIZE) - panic("initlog: too big logheader"); +void initlog(int dev, struct superblock *sb) { + if (sizeof(struct logheader) >= BSIZE) + panic("initlog: too big logheader"); - initlock(&log.lock, "log"); - log.start = sb->logstart; - log.size = sb->nlog; - log.dev = dev; - recover_from_log(); + initlock(&log.lock, "log"); + log.start = sb->logstart; + log.size = sb->nlog; + log.dev = dev; + recover_from_log(); } // Copy committed blocks from log to their home location -static void -install_trans(int recovering) -{ - int tail; +static void install_trans(int recovering) { + int tail; - for (tail = 0; tail < log.lh.n; tail++) { - struct buf *lbuf = bread(log.dev, log.start+tail+1); // read log block - struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst - memmove(dbuf->data, lbuf->data, BSIZE); // copy block to dst - bwrite(dbuf); // write dst to disk - if(recovering == 0) - bunpin(dbuf); - brelse(lbuf); - brelse(dbuf); - } + for (tail = 0; tail < log.lh.n; tail++) { + struct buf *lbuf = + bread(log.dev, log.start + tail + 1); // read log block + struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst + memmove(dbuf->data, lbuf->data, BSIZE); // copy block to dst + bwrite(dbuf); // write dst to disk + if (recovering == 0) + bunpin(dbuf); + brelse(lbuf); + brelse(dbuf); + } } // Read the log header from disk into the in-memory log header -static void -read_head(void) -{ - struct buf *buf = bread(log.dev, log.start); - struct logheader *lh = (struct logheader *) (buf->data); - int i; - log.lh.n = lh->n; - for (i = 0; i < log.lh.n; i++) { - log.lh.block[i] = lh->block[i]; - } - brelse(buf); +static void read_head(void) { + struct buf *buf = bread(log.dev, log.start); + struct logheader *lh = (struct logheader *)(buf->data); + int i; + log.lh.n = lh->n; + for (i = 0; i < log.lh.n; i++) { + log.lh.block[i] = lh->block[i]; + } + brelse(buf); } // Write in-memory log header to disk. // This is the true point at which the // current transaction commits. -static void -write_head(void) -{ - struct buf *buf = bread(log.dev, log.start); - struct logheader *hb = (struct logheader *) (buf->data); - int i; - hb->n = log.lh.n; - for (i = 0; i < log.lh.n; i++) { - hb->block[i] = log.lh.block[i]; - } - bwrite(buf); - brelse(buf); +static void write_head(void) { + struct buf *buf = bread(log.dev, log.start); + struct logheader *hb = (struct logheader *)(buf->data); + int i; + hb->n = log.lh.n; + for (i = 0; i < log.lh.n; i++) { + hb->block[i] = log.lh.block[i]; + } + bwrite(buf); + brelse(buf); } -static void -recover_from_log(void) -{ - read_head(); - install_trans(1); // if committed, copy from log to disk - log.lh.n = 0; - write_head(); // clear the log +static void recover_from_log(void) { + read_head(); + install_trans(1); // if committed, copy from log to disk + log.lh.n = 0; + write_head(); // clear the log } // called at the start of each FS system call. -void -begin_op(void) -{ - acquire(&log.lock); - while(1){ - if(log.committing){ - sleep(&log, &log.lock); - } else if(log.lh.n + (log.outstanding+1)*MAXOPBLOCKS > LOGSIZE){ - // this op might exhaust log space; wait for commit. - sleep(&log, &log.lock); - } else { - log.outstanding += 1; - release(&log.lock); - break; - } - } +void begin_op(void) { + acquire(&log.lock); + while (1) { + if (log.committing) { + sleep(&log, &log.lock); + } else if (log.lh.n + (log.outstanding + 1) * MAXOPBLOCKS > LOGSIZE) { + // this op might exhaust log space; wait for commit. + sleep(&log, &log.lock); + } else { + log.outstanding += 1; + release(&log.lock); + break; + } + } } // called at the end of each FS system call. // commits if this was the last outstanding operation. -void -end_op(void) -{ - int do_commit = 0; +void end_op(void) { + int do_commit = 0; - acquire(&log.lock); - log.outstanding -= 1; - if(log.committing) - panic("log.committing"); - if(log.outstanding == 0){ - do_commit = 1; - log.committing = 1; - } else { - // begin_op() may be waiting for log space, - // and decrementing log.outstanding has decreased - // the amount of reserved space. - wakeup(&log); - } - release(&log.lock); + acquire(&log.lock); + log.outstanding -= 1; + if (log.committing) + panic("log.committing"); + if (log.outstanding == 0) { + do_commit = 1; + log.committing = 1; + } else { + // begin_op() may be waiting for log space, + // and decrementing log.outstanding has decreased + // the amount of reserved space. + wakeup(&log); + } + release(&log.lock); - if(do_commit){ - // call commit w/o holding locks, since not allowed - // to sleep with locks. - commit(); - acquire(&log.lock); - log.committing = 0; - wakeup(&log); - release(&log.lock); - } + if (do_commit) { + // call commit w/o holding locks, since not allowed + // to sleep with locks. + commit(); + acquire(&log.lock); + log.committing = 0; + wakeup(&log); + release(&log.lock); + } } // Copy modified blocks from cache to log. -static void -write_log(void) -{ - int tail; +static void write_log(void) { + int tail; - for (tail = 0; tail < log.lh.n; tail++) { - struct buf *to = bread(log.dev, log.start+tail+1); // log block - struct buf *from = bread(log.dev, log.lh.block[tail]); // cache block - memmove(to->data, from->data, BSIZE); - bwrite(to); // write the log - brelse(from); - brelse(to); - } + for (tail = 0; tail < log.lh.n; tail++) { + struct buf *to = bread(log.dev, log.start + tail + 1); // log block + struct buf *from = bread(log.dev, log.lh.block[tail]); // cache block + memmove(to->data, from->data, BSIZE); + bwrite(to); // write the log + brelse(from); + brelse(to); + } } -static void -commit() -{ - if (log.lh.n > 0) { - write_log(); // Write modified blocks from cache to log - write_head(); // Write header to disk -- the real commit - install_trans(0); // Now install writes to home locations - log.lh.n = 0; - write_head(); // Erase the transaction from the log - } +static void commit() { + if (log.lh.n > 0) { + write_log(); // Write modified blocks from cache to log + write_head(); // Write header to disk -- the real commit + install_trans(0); // Now install writes to home locations + log.lh.n = 0; + write_head(); // Erase the transaction from the log + } } // Caller has modified b->data and is done with the buffer. @@ -211,26 +194,23 @@ commit() // modify bp->data[] // log_write(bp) // brelse(bp) -void -log_write(struct buf *b) -{ - int i; +void log_write(struct buf *b) { + int i; - acquire(&log.lock); - if (log.lh.n >= LOGSIZE || log.lh.n >= log.size - 1) - panic("too big a transaction"); - if (log.outstanding < 1) - panic("log_write outside of trans"); + acquire(&log.lock); + if (log.lh.n >= LOGSIZE || log.lh.n >= log.size - 1) + panic("too big a transaction"); + if (log.outstanding < 1) + panic("log_write outside of trans"); - for (i = 0; i < log.lh.n; i++) { - if (log.lh.block[i] == b->blockno) // log absorption - break; - } - log.lh.block[i] = b->blockno; - if (i == log.lh.n) { // Add new block to log? - bpin(b); - log.lh.n++; - } - release(&log.lock); + for (i = 0; i < log.lh.n; i++) { + if (log.lh.block[i] == b->blockno) // log absorption + break; + } + log.lh.block[i] = b->blockno; + if (i == log.lh.n) { // Add new block to log? + bpin(b); + log.lh.n++; + } + release(&log.lock); } - diff --git a/kernel/main.c b/kernel/main.c index f0d3171..d2642ad 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,39 +7,38 @@ volatile static int started = 0; // start() jumps here in supervisor mode on all CPUs. -void -main() -{ - if(cpuid() == 0){ - consoleinit(); - printfinit(); - printf("\n"); - printf("xv6 kernel is booting\n"); - printf("\n"); - kinit(); // physical page allocator - kvminit(); // create kernel page table - kvminithart(); // turn on paging - procinit(); // process table - trapinit(); // trap vectors - trapinithart(); // install kernel trap vector - plicinit(); // set up interrupt controller - plicinithart(); // ask PLIC for device interrupts - binit(); // buffer cache - iinit(); // inode table - fileinit(); // file table - virtio_disk_init(); // emulated hard disk - userinit(); // first user process - __sync_synchronize(); - started = 1; - } else { - while(started == 0) - ; - __sync_synchronize(); - printf("hart %d starting\n", cpuid()); - kvminithart(); // turn on paging - trapinithart(); // install kernel trap vector - plicinithart(); // ask PLIC for device interrupts - } +void main() { + if (cpuid() == 0) { + consoleinit(); + printfinit(); + printf("\n"); + printf("xv6 kernel is booting\n"); + // printf("rustlib: add(1, 2) = %d\n", add(1, 2)); + printf("\n"); + kinit(); // physical page allocator + kvminit(); // create kernel page table + kvminithart(); // turn on paging + procinit(); // process table + trapinit(); // trap vectors + trapinithart(); // install kernel trap vector + plicinit(); // set up interrupt controller + plicinithart(); // ask PLIC for device interrupts + binit(); // buffer cache + iinit(); // inode table + fileinit(); // file table + virtio_disk_init(); // emulated hard disk + userinit(); // first user process + __sync_synchronize(); + started = 1; + } else { + while (started == 0) + ; + __sync_synchronize(); + printf("hart %d starting\n", cpuid()); + kvminithart(); // turn on paging + trapinithart(); // install kernel trap vector + plicinithart(); // ask PLIC for device interrupts + } - scheduler(); + scheduler(); } diff --git a/kernel/pipe.c b/kernel/pipe.c index f6b501a..05fa9e0 100644 --- a/kernel/pipe.c +++ b/kernel/pipe.c @@ -11,120 +11,112 @@ #define PIPESIZE 512 struct pipe { - struct spinlock lock; - char data[PIPESIZE]; - uint nread; // number of bytes read - uint nwrite; // number of bytes written - int readopen; // read fd is still open - int writeopen; // write fd is still open + struct spinlock lock; + char data[PIPESIZE]; + uint nread; // number of bytes read + uint nwrite; // number of bytes written + int readopen; // read fd is still open + int writeopen; // write fd is still open }; -int -pipealloc(struct file **f0, struct file **f1) -{ - struct pipe *pi; +int pipealloc(struct file **f0, struct file **f1) { + struct pipe *pi; - pi = 0; - *f0 = *f1 = 0; - if((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) - goto bad; - if((pi = (struct pipe*)kalloc()) == 0) - goto bad; - pi->readopen = 1; - pi->writeopen = 1; - pi->nwrite = 0; - pi->nread = 0; - initlock(&pi->lock, "pipe"); - (*f0)->type = FD_PIPE; - (*f0)->readable = 1; - (*f0)->writable = 0; - (*f0)->pipe = pi; - (*f1)->type = FD_PIPE; - (*f1)->readable = 0; - (*f1)->writable = 1; - (*f1)->pipe = pi; - return 0; + pi = 0; + *f0 = *f1 = 0; + if ((*f0 = filealloc()) == 0 || (*f1 = filealloc()) == 0) + goto bad; + if ((pi = (struct pipe *)kalloc()) == 0) + goto bad; + pi->readopen = 1; + pi->writeopen = 1; + pi->nwrite = 0; + pi->nread = 0; + initlock(&pi->lock, "pipe"); + (*f0)->type = FD_PIPE; + (*f0)->readable = 1; + (*f0)->writable = 0; + (*f0)->pipe = pi; + (*f1)->type = FD_PIPE; + (*f1)->readable = 0; + (*f1)->writable = 1; + (*f1)->pipe = pi; + return 0; - bad: - if(pi) - kfree((char*)pi); - if(*f0) - fileclose(*f0); - if(*f1) - fileclose(*f1); - return -1; +bad: + if (pi) + kfree((char *)pi); + if (*f0) + fileclose(*f0); + if (*f1) + fileclose(*f1); + return -1; } -void -pipeclose(struct pipe *pi, int writable) -{ - acquire(&pi->lock); - if(writable){ - pi->writeopen = 0; - wakeup(&pi->nread); - } else { - pi->readopen = 0; - wakeup(&pi->nwrite); - } - if(pi->readopen == 0 && pi->writeopen == 0){ - release(&pi->lock); - kfree((char*)pi); - } else - release(&pi->lock); +void pipeclose(struct pipe *pi, int writable) { + acquire(&pi->lock); + if (writable) { + pi->writeopen = 0; + wakeup(&pi->nread); + } else { + pi->readopen = 0; + wakeup(&pi->nwrite); + } + if (pi->readopen == 0 && pi->writeopen == 0) { + release(&pi->lock); + kfree((char *)pi); + } else + release(&pi->lock); } -int -pipewrite(struct pipe *pi, uint64 addr, int n) -{ - int i = 0; - struct proc *pr = myproc(); +int pipewrite(struct pipe *pi, uint64 addr, int n) { + int i = 0; + struct proc *pr = myproc(); - acquire(&pi->lock); - while(i < n){ - if(pi->readopen == 0 || killed(pr)){ - release(&pi->lock); - return -1; - } - if(pi->nwrite == pi->nread + PIPESIZE){ //DOC: pipewrite-full - wakeup(&pi->nread); - sleep(&pi->nwrite, &pi->lock); - } else { - char ch; - if(copyin(pr->pagetable, &ch, addr + i, 1) == -1) - break; - pi->data[pi->nwrite++ % PIPESIZE] = ch; - i++; - } - } - wakeup(&pi->nread); - release(&pi->lock); + acquire(&pi->lock); + while (i < n) { + if (pi->readopen == 0 || killed(pr)) { + release(&pi->lock); + return -1; + } + if (pi->nwrite == pi->nread + PIPESIZE) { // DOC: pipewrite-full + wakeup(&pi->nread); + sleep(&pi->nwrite, &pi->lock); + } else { + char ch; + if (copyin(pr->pagetable, &ch, addr + i, 1) == -1) + break; + pi->data[pi->nwrite++ % PIPESIZE] = ch; + i++; + } + } + wakeup(&pi->nread); + release(&pi->lock); - return i; + return i; } -int -piperead(struct pipe *pi, uint64 addr, int n) -{ - int i; - struct proc *pr = myproc(); - char ch; +int piperead(struct pipe *pi, uint64 addr, int n) { + int i; + struct proc *pr = myproc(); + char ch; - acquire(&pi->lock); - while(pi->nread == pi->nwrite && pi->writeopen){ //DOC: pipe-empty - if(killed(pr)){ - release(&pi->lock); - return -1; - } - sleep(&pi->nread, &pi->lock); //DOC: piperead-sleep - } - for(i = 0; i < n; i++){ //DOC: piperead-copy - if(pi->nread == pi->nwrite) - break; - ch = pi->data[pi->nread++ % PIPESIZE]; - if(copyout(pr->pagetable, addr + i, &ch, 1) == -1) - break; - } - wakeup(&pi->nwrite); //DOC: piperead-wakeup - release(&pi->lock); - return i; + acquire(&pi->lock); + while (pi->nread == pi->nwrite && pi->writeopen) { // DOC: pipe-empty + if (killed(pr)) { + release(&pi->lock); + return -1; + } + sleep(&pi->nread, &pi->lock); // DOC: piperead-sleep + } + for (i = 0; i < n; i++) { // DOC: piperead-copy + if (pi->nread == pi->nwrite) + break; + ch = pi->data[pi->nread++ % PIPESIZE]; + if (copyout(pr->pagetable, addr + i, &ch, 1) == -1) + break; + } + wakeup(&pi->nwrite); // DOC: piperead-wakeup + release(&pi->lock); + return i; } diff --git a/kernel/plic.c b/kernel/plic.c index 4175db9..3d912ec 100644 --- a/kernel/plic.c +++ b/kernel/plic.c @@ -8,40 +8,32 @@ // the riscv Platform Level Interrupt Controller (PLIC). // -void -plicinit(void) -{ - // set desired IRQ priorities non-zero (otherwise disabled). - *(uint32*)(PLIC + UART0_IRQ*4) = 1; - *(uint32*)(PLIC + VIRTIO0_IRQ*4) = 1; +void plicinit(void) { + // set desired IRQ priorities non-zero (otherwise disabled). + *(uint32 *)(PLIC + UART0_IRQ * 4) = 1; + *(uint32 *)(PLIC + VIRTIO0_IRQ * 4) = 1; } -void -plicinithart(void) -{ - int hart = cpuid(); - - // 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); +void plicinithart(void) { + int hart = cpuid(); - // set this hart's S-mode priority threshold to 0. - *(uint32*)PLIC_SPRIORITY(hart) = 0; + // 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); + + // set this hart's S-mode priority threshold to 0. + *(uint32 *)PLIC_SPRIORITY(hart) = 0; } // ask the PLIC what interrupt we should serve. -int -plic_claim(void) -{ - int hart = cpuid(); - int irq = *(uint32*)PLIC_SCLAIM(hart); - return irq; +int plic_claim(void) { + int hart = cpuid(); + int irq = *(uint32 *)PLIC_SCLAIM(hart); + return irq; } // tell the PLIC we've served this IRQ. -void -plic_complete(int irq) -{ - int hart = cpuid(); - *(uint32*)PLIC_SCLAIM(hart) = irq; +void plic_complete(int irq) { + int hart = cpuid(); + *(uint32 *)PLIC_SCLAIM(hart) = irq; } diff --git a/kernel/printf.c b/kernel/printf.c index 1a50203..0afc501 100644 --- a/kernel/printf.c +++ b/kernel/printf.c @@ -19,117 +19,107 @@ volatile int panicked = 0; // lock to avoid interleaving concurrent printf's. static struct { - struct spinlock lock; - int locking; + struct spinlock lock; + int locking; } pr; static char digits[] = "0123456789abcdef"; -static void -printint(int xx, int base, int sign) -{ - char buf[16]; - int i; - uint x; +static void printint(int xx, int base, int sign) { + char buf[16]; + int i; + uint x; - if(sign && (sign = xx < 0)) - x = -xx; - else - x = xx; + if (sign && (sign = xx < 0)) + x = -xx; + else + x = xx; - i = 0; - do { - buf[i++] = digits[x % base]; - } while((x /= base) != 0); + i = 0; + do { + buf[i++] = digits[x % base]; + } while ((x /= base) != 0); - if(sign) - buf[i++] = '-'; + if (sign) + buf[i++] = '-'; - while(--i >= 0) - consputc(buf[i]); + while (--i >= 0) + consputc(buf[i]); } -static void -printptr(uint64 x) -{ - int i; - consputc('0'); - consputc('x'); - for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) - consputc(digits[x >> (sizeof(uint64) * 8 - 4)]); +static void printptr(uint64 x) { + int i; + consputc('0'); + consputc('x'); + for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) + consputc(digits[x >> (sizeof(uint64) * 8 - 4)]); } // Print to the console. only understands %d, %x, %p, %s. -void -printf(char *fmt, ...) -{ - va_list ap; - int i, c, locking; - char *s; +void printf(char *fmt, ...) { + va_list ap; + int i, c, locking; + char *s; - locking = pr.locking; - if(locking) - acquire(&pr.lock); + locking = pr.locking; + if (locking) + acquire(&pr.lock); - if (fmt == 0) - panic("null fmt"); + if (fmt == 0) + panic("null fmt"); - va_start(ap, fmt); - for(i = 0; (c = fmt[i] & 0xff) != 0; i++){ - if(c != '%'){ - consputc(c); - continue; - } - c = fmt[++i] & 0xff; - if(c == 0) - break; - switch(c){ - case 'd': - printint(va_arg(ap, int), 10, 1); - break; - case 'x': - printint(va_arg(ap, int), 16, 1); - break; - case 'p': - printptr(va_arg(ap, uint64)); - break; - case 's': - if((s = va_arg(ap, char*)) == 0) - s = "(null)"; - for(; *s; s++) - consputc(*s); - break; - case '%': - consputc('%'); - break; - default: - // Print unknown % sequence to draw attention. - consputc('%'); - consputc(c); - break; - } - } - va_end(ap); + va_start(ap, fmt); + for (i = 0; (c = fmt[i] & 0xff) != 0; i++) { + if (c != '%') { + consputc(c); + continue; + } + c = fmt[++i] & 0xff; + if (c == 0) + break; + switch (c) { + case 'd': + printint(va_arg(ap, int), 10, 1); + break; + case 'x': + printint(va_arg(ap, int), 16, 1); + break; + case 'p': + printptr(va_arg(ap, uint64)); + break; + case 's': + if ((s = va_arg(ap, char *)) == 0) + s = "(null)"; + for (; *s; s++) + consputc(*s); + break; + case '%': + consputc('%'); + break; + default: + // Print unknown % sequence to draw attention. + consputc('%'); + consputc(c); + break; + } + } + va_end(ap); - if(locking) - release(&pr.lock); + if (locking) + release(&pr.lock); } -void -panic(char *s) -{ - pr.locking = 0; - printf("panic: "); - printf(s); - printf("\n"); - panicked = 1; // freeze uart output from other CPUs - for(;;) - ; +void panic(char *s) { + pr.locking = 0; + printf("panic: "); + printf(s); + printf("\n"); + panicked = 1; // freeze uart output from other CPUs + for (;;) + ; } -void -printfinit(void) -{ - initlock(&pr.lock, "pr"); - pr.locking = 1; +void printfinit(void) { + initlock(&pr.lock, "pr"); + pr.locking = 1; } diff --git a/kernel/proc.c b/kernel/proc.c index 959b778..d80af15 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -29,409 +29,375 @@ struct spinlock wait_lock; // Allocate a page for each process's kernel stack. // Map it high in memory, followed by an invalid // guard page. -void -proc_mapstacks(pagetable_t kpgtbl) -{ - struct proc *p; - - for(p = proc; p < &proc[NPROC]; p++) { - char *pa = kalloc(); - if(pa == 0) - panic("kalloc"); - uint64 va = KSTACK((int) (p - proc)); - kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W); - } +void proc_mapstacks(pagetable_t kpgtbl) { + struct proc *p; + + for (p = proc; p < &proc[NPROC]; p++) { + char *pa = kalloc(); + if (pa == 0) + panic("kalloc"); + uint64 va = KSTACK((int)(p - proc)); + kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W); + } } // initialize the proc table. -void -procinit(void) -{ - struct proc *p; - - initlock(&pid_lock, "nextpid"); - 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)); - } +void procinit(void) { + struct proc *p; + + initlock(&pid_lock, "nextpid"); + 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)); + } } // Must be called with interrupts disabled, // to prevent race with process being moved // to a different CPU. -int -cpuid() -{ - int id = r_tp(); - return id; +int cpuid() { + int id = r_tp(); + return id; } // Return this CPU's cpu struct. // Interrupts must be disabled. -struct cpu* -mycpu(void) -{ - int id = cpuid(); - struct cpu *c = &cpus[id]; - return c; +struct cpu *mycpu(void) { + int id = cpuid(); + struct cpu *c = &cpus[id]; + return c; } // Return the current struct proc *, or zero if none. -struct proc* -myproc(void) -{ - push_off(); - struct cpu *c = mycpu(); - struct proc *p = c->proc; - pop_off(); - return p; +struct proc *myproc(void) { + push_off(); + struct cpu *c = mycpu(); + struct proc *p = c->proc; + pop_off(); + return p; } -int -allocpid() -{ - int pid; - - acquire(&pid_lock); - pid = nextpid; - nextpid = nextpid + 1; - release(&pid_lock); +int allocpid() { + int pid; - return pid; + acquire(&pid_lock); + pid = nextpid; + nextpid = nextpid + 1; + release(&pid_lock); + + return pid; } // Look in the process table for an UNUSED proc. // If found, initialize state required to run in the kernel, // and return with p->lock held. // If there are no free procs, or a memory allocation fails, return 0. -static struct proc* -allocproc(void) -{ - struct proc *p; +static struct proc *allocproc(void) { + struct proc *p; - for(p = proc; p < &proc[NPROC]; p++) { - acquire(&p->lock); - if(p->state == UNUSED) { - goto found; - } else { - release(&p->lock); - } - } - return 0; + for (p = proc; p < &proc[NPROC]; p++) { + acquire(&p->lock); + if (p->state == UNUSED) { + goto found; + } else { + release(&p->lock); + } + } + return 0; found: - p->pid = allocpid(); - p->state = USED; + p->pid = allocpid(); + p->state = USED; - // Allocate a trapframe page. - if((p->trapframe = (struct trapframe *)kalloc()) == 0){ - freeproc(p); - release(&p->lock); - return 0; - } + // Allocate a trapframe page. + if ((p->trapframe = (struct trapframe *)kalloc()) == 0) { + freeproc(p); + release(&p->lock); + return 0; + } - // An empty user page table. - p->pagetable = proc_pagetable(p); - if(p->pagetable == 0){ - freeproc(p); - release(&p->lock); - return 0; - } + // An empty user page table. + p->pagetable = proc_pagetable(p); + if (p->pagetable == 0) { + freeproc(p); + release(&p->lock); + return 0; + } - // Set up new context to start executing at forkret, - // which returns to user space. - memset(&p->context, 0, sizeof(p->context)); - p->context.ra = (uint64)forkret; - p->context.sp = p->kstack + PGSIZE; + // Set up new context to start executing at forkret, + // which returns to user space. + memset(&p->context, 0, sizeof(p->context)); + p->context.ra = (uint64)forkret; + p->context.sp = p->kstack + PGSIZE; - return p; + return p; } // free a proc structure and the data hanging from it, // including user pages. // p->lock must be held. -static void -freeproc(struct proc *p) -{ - if(p->trapframe) - kfree((void*)p->trapframe); - p->trapframe = 0; - if(p->pagetable) - proc_freepagetable(p->pagetable, p->sz); - p->pagetable = 0; - p->sz = 0; - p->pid = 0; - p->parent = 0; - p->name[0] = 0; - p->chan = 0; - p->killed = 0; - p->xstate = 0; - p->state = UNUSED; +static void freeproc(struct proc *p) { + if (p->trapframe) + kfree((void *)p->trapframe); + p->trapframe = 0; + if (p->pagetable) + proc_freepagetable(p->pagetable, p->sz); + p->pagetable = 0; + p->sz = 0; + p->pid = 0; + p->parent = 0; + p->name[0] = 0; + p->chan = 0; + p->killed = 0; + p->xstate = 0; + p->state = UNUSED; } // 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) -{ - pagetable_t pagetable; +pagetable_t proc_pagetable(struct proc *p) { + pagetable_t pagetable; - // An empty page table. - pagetable = uvmcreate(); - if(pagetable == 0) - return 0; + // An empty page table. + pagetable = uvmcreate(); + if (pagetable == 0) + return 0; - // map the trampoline code (for system call return) - // at the highest user virtual address. - // only the supervisor uses it, on the way - // to/from user space, so not PTE_U. - if(mappages(pagetable, TRAMPOLINE, PGSIZE, - (uint64)trampoline, PTE_R | PTE_X) < 0){ - uvmfree(pagetable, 0); - return 0; - } + // map the trampoline code (for system call return) + // at the highest user virtual address. + // only the supervisor uses it, on the way + // to/from user space, so not PTE_U. + if (mappages(pagetable, TRAMPOLINE, PGSIZE, (uint64)trampoline, + PTE_R | PTE_X) < 0) { + uvmfree(pagetable, 0); + return 0; + } - // 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); - uvmfree(pagetable, 0); - return 0; - } + // 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); + uvmfree(pagetable, 0); + return 0; + } - return pagetable; + return pagetable; } // Free a process's page table, and free the // physical memory it refers to. -void -proc_freepagetable(pagetable_t pagetable, uint64 sz) -{ - uvmunmap(pagetable, TRAMPOLINE, 1, 0); - uvmunmap(pagetable, TRAPFRAME, 1, 0); - uvmfree(pagetable, sz); +void proc_freepagetable(pagetable_t pagetable, uint64 sz) { + uvmunmap(pagetable, TRAMPOLINE, 1, 0); + uvmunmap(pagetable, TRAPFRAME, 1, 0); + uvmfree(pagetable, sz); } // a user program that calls exec("/init") // assembled from ../user/initcode.S // od -t xC ../user/initcode -uchar initcode[] = { - 0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x45, 0x02, - 0x97, 0x05, 0x00, 0x00, 0x93, 0x85, 0x35, 0x02, - 0x93, 0x08, 0x70, 0x00, 0x73, 0x00, 0x00, 0x00, - 0x93, 0x08, 0x20, 0x00, 0x73, 0x00, 0x00, 0x00, - 0xef, 0xf0, 0x9f, 0xff, 0x2f, 0x69, 0x6e, 0x69, - 0x74, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; +uchar initcode[] = {0x17, 0x05, 0x00, 0x00, 0x13, 0x05, 0x45, 0x02, 0x97, + 0x05, 0x00, 0x00, 0x93, 0x85, 0x35, 0x02, 0x93, 0x08, + 0x70, 0x00, 0x73, 0x00, 0x00, 0x00, 0x93, 0x08, 0x20, + 0x00, 0x73, 0x00, 0x00, 0x00, 0xef, 0xf0, 0x9f, 0xff, + 0x2f, 0x69, 0x6e, 0x69, 0x74, 0x00, 0x00, 0x24, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Set up first user process. -void -userinit(void) -{ - struct proc *p; +void userinit(void) { + struct proc *p; - p = allocproc(); - initproc = p; - - // allocate one user page and copy initcode's instructions - // and data into it. - uvmfirst(p->pagetable, initcode, sizeof(initcode)); - p->sz = PGSIZE; + p = allocproc(); + initproc = p; - // prepare for the very first "return" from kernel to user. - p->trapframe->epc = 0; // user program counter - p->trapframe->sp = PGSIZE; // user stack pointer + // allocate one user page and copy initcode's instructions + // and data into it. + uvmfirst(p->pagetable, initcode, sizeof(initcode)); + p->sz = PGSIZE; - safestrcpy(p->name, "initcode", sizeof(p->name)); - p->cwd = namei("/"); + // prepare for the very first "return" from kernel to user. + p->trapframe->epc = 0; // user program counter + p->trapframe->sp = PGSIZE; // user stack pointer - p->state = RUNNABLE; + safestrcpy(p->name, "initcode", sizeof(p->name)); + p->cwd = namei("/"); - release(&p->lock); + p->state = RUNNABLE; + + release(&p->lock); } // Grow or shrink user memory by n bytes. // Return 0 on success, -1 on failure. -int -growproc(int n) -{ - uint64 sz; - struct proc *p = myproc(); +int growproc(int n) { + uint64 sz; + struct proc *p = myproc(); - sz = p->sz; - if(n > 0){ - if((sz = uvmalloc(p->pagetable, sz, sz + n, PTE_W)) == 0) { - return -1; - } - } else if(n < 0){ - sz = uvmdealloc(p->pagetable, sz, sz + n); - } - p->sz = sz; - return 0; + sz = p->sz; + if (n > 0) { + if ((sz = uvmalloc(p->pagetable, sz, sz + n, PTE_W)) == 0) { + return -1; + } + } else if (n < 0) { + sz = uvmdealloc(p->pagetable, sz, sz + n); + } + p->sz = sz; + return 0; } // Create a new process, copying the parent. // Sets up child kernel stack to return as if from fork() system call. -int -fork(void) -{ - int i, pid; - struct proc *np; - struct proc *p = myproc(); +int fork(void) { + int i, pid; + struct proc *np; + struct proc *p = myproc(); - // Allocate process. - if((np = allocproc()) == 0){ - return -1; - } + // Allocate process. + if ((np = allocproc()) == 0) { + return -1; + } - // Copy user memory from parent to child. - if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){ - freeproc(np); - release(&np->lock); - return -1; - } - np->sz = p->sz; + // Copy user memory from parent to child. + if (uvmcopy(p->pagetable, np->pagetable, p->sz) < 0) { + freeproc(np); + release(&np->lock); + return -1; + } + np->sz = p->sz; - // copy saved user registers. - *(np->trapframe) = *(p->trapframe); + // copy saved user registers. + *(np->trapframe) = *(p->trapframe); - // Cause fork to return 0 in the child. - np->trapframe->a0 = 0; + // Cause fork to return 0 in the child. + np->trapframe->a0 = 0; - // increment reference counts on open file descriptors. - for(i = 0; i < NOFILE; i++) - if(p->ofile[i]) - np->ofile[i] = filedup(p->ofile[i]); - np->cwd = idup(p->cwd); + // increment reference counts on open file descriptors. + for (i = 0; i < NOFILE; i++) + if (p->ofile[i]) + np->ofile[i] = filedup(p->ofile[i]); + np->cwd = idup(p->cwd); - safestrcpy(np->name, p->name, sizeof(p->name)); + safestrcpy(np->name, p->name, sizeof(p->name)); - pid = np->pid; + pid = np->pid; - release(&np->lock); + release(&np->lock); - acquire(&wait_lock); - np->parent = p; - release(&wait_lock); + acquire(&wait_lock); + np->parent = p; + release(&wait_lock); - acquire(&np->lock); - np->state = RUNNABLE; - release(&np->lock); + acquire(&np->lock); + np->state = RUNNABLE; + release(&np->lock); - return pid; + return pid; } // Pass p's abandoned children to init. // Caller must hold wait_lock. -void -reparent(struct proc *p) -{ - struct proc *pp; +void reparent(struct proc *p) { + struct proc *pp; - for(pp = proc; pp < &proc[NPROC]; pp++){ - if(pp->parent == p){ - pp->parent = initproc; - wakeup(initproc); - } - } + for (pp = proc; pp < &proc[NPROC]; pp++) { + if (pp->parent == p) { + pp->parent = initproc; + wakeup(initproc); + } + } } // Exit the current process. Does not return. // An exited process remains in the zombie state // until its parent calls wait(). -void -exit(int status) -{ - struct proc *p = myproc(); +void exit(int status) { + struct proc *p = myproc(); - if(p == initproc) - panic("init exiting"); + if (p == initproc) + panic("init exiting"); - // Close all open files. - for(int fd = 0; fd < NOFILE; fd++){ - if(p->ofile[fd]){ - struct file *f = p->ofile[fd]; - fileclose(f); - p->ofile[fd] = 0; - } - } + // Close all open files. + for (int fd = 0; fd < NOFILE; fd++) { + if (p->ofile[fd]) { + struct file *f = p->ofile[fd]; + fileclose(f); + p->ofile[fd] = 0; + } + } - begin_op(); - iput(p->cwd); - end_op(); - p->cwd = 0; + begin_op(); + iput(p->cwd); + end_op(); + p->cwd = 0; - acquire(&wait_lock); + acquire(&wait_lock); - // Give any children to init. - reparent(p); + // Give any children to init. + reparent(p); - // Parent might be sleeping in wait(). - wakeup(p->parent); - - acquire(&p->lock); + // Parent might be sleeping in wait(). + wakeup(p->parent); - p->xstate = status; - p->state = ZOMBIE; + acquire(&p->lock); - release(&wait_lock); + p->xstate = status; + p->state = ZOMBIE; - // Jump into the scheduler, never to return. - sched(); - panic("zombie exit"); + release(&wait_lock); + + // Jump into the scheduler, never to return. + sched(); + panic("zombie exit"); } // Wait for a child process to exit and return its pid. // Return -1 if this process has no children. -int -wait(uint64 addr) -{ - struct proc *pp; - int havekids, pid; - struct proc *p = myproc(); +int wait(uint64 addr) { + struct proc *pp; + int havekids, pid; + struct proc *p = myproc(); - acquire(&wait_lock); + acquire(&wait_lock); - for(;;){ - // Scan through table looking for exited children. - havekids = 0; - for(pp = proc; pp < &proc[NPROC]; pp++){ - if(pp->parent == p){ - // make sure the child isn't still in exit() or swtch(). - acquire(&pp->lock); + for (;;) { + // Scan through table looking for exited children. + havekids = 0; + for (pp = proc; pp < &proc[NPROC]; pp++) { + if (pp->parent == p) { + // make sure the child isn't still in exit() or swtch(). + acquire(&pp->lock); - havekids = 1; - if(pp->state == ZOMBIE){ - // Found one. - 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(pp); - release(&pp->lock); - release(&wait_lock); - return pid; - } - release(&pp->lock); - } - } + havekids = 1; + if (pp->state == ZOMBIE) { + // Found one. + 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(pp); + release(&pp->lock); + release(&wait_lock); + return pid; + } + release(&pp->lock); + } + } - // No point waiting if we don't have any children. - if(!havekids || killed(p)){ - release(&wait_lock); - return -1; - } - - // Wait for a child to exit. - sleep(p, &wait_lock); //DOC: wait-sleep - } + // No point waiting if we don't have any children. + if (!havekids || killed(p)) { + release(&wait_lock); + return -1; + } + + // Wait for a child to exit. + sleep(p, &wait_lock); // DOC: wait-sleep + } } // Per-CPU process scheduler. @@ -441,34 +407,32 @@ wait(uint64 addr) // - swtch to start running that process. // - eventually that process transfers control // via swtch back to the scheduler. -void -scheduler(void) -{ - struct proc *p; - struct cpu *c = mycpu(); - - c->proc = 0; - for(;;){ - // Avoid deadlock by ensuring that devices can interrupt. - intr_on(); +void scheduler(void) { + struct proc *p; + struct cpu *c = mycpu(); - for(p = proc; p < &proc[NPROC]; p++) { - acquire(&p->lock); - if(p->state == RUNNABLE) { - // Switch to chosen process. It is the process's job - // to release its lock and then reacquire it - // before jumping back to us. - p->state = RUNNING; - c->proc = p; - swtch(&c->context, &p->context); + c->proc = 0; + for (;;) { + // Avoid deadlock by ensuring that devices can interrupt. + intr_on(); - // Process is done running for now. - // It should have changed its p->state before coming back. - c->proc = 0; - } - release(&p->lock); - } - } + for (p = proc; p < &proc[NPROC]; p++) { + acquire(&p->lock); + if (p->state == RUNNABLE) { + // Switch to chosen process. It is the process's job + // to release its lock and then reacquire it + // before jumping back to us. + p->state = RUNNING; + c->proc = p; + swtch(&c->context, &p->context); + + // Process is done running for now. + // It should have changed its p->state before coming back. + c->proc = 0; + } + release(&p->lock); + } + } } // Switch to scheduler. Must hold only p->lock @@ -478,206 +442,179 @@ scheduler(void) // be proc->intena and proc->noff, but that would // break in the few places where a lock is held but // there's no process. -void -sched(void) -{ - int intena; - struct proc *p = myproc(); +void sched(void) { + int intena; + struct proc *p = myproc(); - if(!holding(&p->lock)) - panic("sched p->lock"); - if(mycpu()->noff != 1) - panic("sched locks"); - if(p->state == RUNNING) - panic("sched running"); - if(intr_get()) - panic("sched interruptible"); + if (!holding(&p->lock)) + panic("sched p->lock"); + if (mycpu()->noff != 1) + panic("sched locks"); + if (p->state == RUNNING) + panic("sched running"); + if (intr_get()) + panic("sched interruptible"); - intena = mycpu()->intena; - swtch(&p->context, &mycpu()->context); - mycpu()->intena = intena; + intena = mycpu()->intena; + swtch(&p->context, &mycpu()->context); + mycpu()->intena = intena; } // Give up the CPU for one scheduling round. -void -yield(void) -{ - struct proc *p = myproc(); - acquire(&p->lock); - p->state = RUNNABLE; - sched(); - release(&p->lock); +void yield(void) { + struct proc *p = myproc(); + acquire(&p->lock); + p->state = RUNNABLE; + sched(); + release(&p->lock); } // A fork child's very first scheduling by scheduler() // will swtch to forkret. -void -forkret(void) -{ - static int first = 1; +void forkret(void) { + static int first = 1; - // Still holding p->lock from scheduler. - release(&myproc()->lock); + // Still holding p->lock from scheduler. + release(&myproc()->lock); - if (first) { - // File system initialization must be run in the context of a - // regular process (e.g., because it calls sleep), and thus cannot - // be run from main(). - first = 0; - fsinit(ROOTDEV); - } + if (first) { + // File system initialization must be run in the context of a + // regular process (e.g., because it calls sleep), and thus cannot + // be run from main(). + first = 0; + fsinit(ROOTDEV); + } - usertrapret(); + usertrapret(); } // Atomically release lock and sleep on chan. // Reacquires lock when awakened. -void -sleep(void *chan, struct spinlock *lk) -{ - struct proc *p = myproc(); - - // Must acquire p->lock in order to - // change p->state and then call sched. - // Once we hold p->lock, we can be - // guaranteed that we won't miss any wakeup - // (wakeup locks p->lock), - // so it's okay to release lk. +void sleep(void *chan, struct spinlock *lk) { + struct proc *p = myproc(); - acquire(&p->lock); //DOC: sleeplock1 - release(lk); + // Must acquire p->lock in order to + // change p->state and then call sched. + // Once we hold p->lock, we can be + // guaranteed that we won't miss any wakeup + // (wakeup locks p->lock), + // so it's okay to release lk. - // Go to sleep. - p->chan = chan; - p->state = SLEEPING; + acquire(&p->lock); // DOC: sleeplock1 + release(lk); - sched(); + // Go to sleep. + p->chan = chan; + p->state = SLEEPING; - // Tidy up. - p->chan = 0; + sched(); - // Reacquire original lock. - release(&p->lock); - acquire(lk); + // Tidy up. + p->chan = 0; + + // Reacquire original lock. + release(&p->lock); + acquire(lk); } // Wake up all processes sleeping on chan. // Must be called without any p->lock. -void -wakeup(void *chan) -{ - struct proc *p; +void wakeup(void *chan) { + struct proc *p; - for(p = proc; p < &proc[NPROC]; p++) { - if(p != myproc()){ - acquire(&p->lock); - if(p->state == SLEEPING && p->chan == chan) { - p->state = RUNNABLE; - } - release(&p->lock); - } - } + for (p = proc; p < &proc[NPROC]; p++) { + if (p != myproc()) { + acquire(&p->lock); + if (p->state == SLEEPING && p->chan == chan) { + p->state = RUNNABLE; + } + release(&p->lock); + } + } } // Kill the process with the given pid. // The victim won't exit until it tries to return // to user space (see usertrap() in trap.c). -int -kill(int pid) -{ - struct proc *p; +int kill(int pid) { + struct proc *p; - for(p = proc; p < &proc[NPROC]; p++){ - acquire(&p->lock); - if(p->pid == pid){ - p->killed = 1; - if(p->state == SLEEPING){ - // Wake process from sleep(). - p->state = RUNNABLE; - } - release(&p->lock); - return 0; - } - release(&p->lock); - } - return -1; + for (p = proc; p < &proc[NPROC]; p++) { + acquire(&p->lock); + if (p->pid == pid) { + p->killed = 1; + if (p->state == SLEEPING) { + // Wake process from sleep(). + p->state = RUNNABLE; + } + release(&p->lock); + return 0; + } + release(&p->lock); + } + return -1; } -void -setkilled(struct proc *p) -{ - acquire(&p->lock); - p->killed = 1; - release(&p->lock); +void setkilled(struct proc *p) { + acquire(&p->lock); + p->killed = 1; + release(&p->lock); } -int -killed(struct proc *p) -{ - int k; - - acquire(&p->lock); - k = p->killed; - release(&p->lock); - return k; +int killed(struct proc *p) { + int k; + + acquire(&p->lock); + k = p->killed; + release(&p->lock); + return k; } // Copy to either a user address, or kernel address, // depending on usr_dst. // Returns 0 on success, -1 on error. -int -either_copyout(int user_dst, uint64 dst, void *src, uint64 len) -{ - struct proc *p = myproc(); - if(user_dst){ - return copyout(p->pagetable, dst, src, len); - } else { - memmove((char *)dst, src, len); - return 0; - } +int either_copyout(int user_dst, uint64 dst, void *src, uint64 len) { + struct proc *p = myproc(); + if (user_dst) { + return copyout(p->pagetable, dst, src, len); + } else { + memmove((char *)dst, src, len); + return 0; + } } // Copy from either a user address, or kernel address, // depending on usr_src. // Returns 0 on success, -1 on error. -int -either_copyin(void *dst, int user_src, uint64 src, uint64 len) -{ - struct proc *p = myproc(); - if(user_src){ - return copyin(p->pagetable, dst, src, len); - } else { - memmove(dst, (char*)src, len); - return 0; - } +int either_copyin(void *dst, int user_src, uint64 src, uint64 len) { + struct proc *p = myproc(); + if (user_src) { + return copyin(p->pagetable, dst, src, len); + } else { + memmove(dst, (char *)src, len); + return 0; + } } // Print a process listing to console. For debugging. // Runs when user types ^P on console. // No lock to avoid wedging a stuck machine further. -void -procdump(void) -{ - static char *states[] = { - [UNUSED] "unused", - [USED] "used", - [SLEEPING] "sleep ", - [RUNNABLE] "runble", - [RUNNING] "run ", - [ZOMBIE] "zombie" - }; - struct proc *p; - char *state; +void procdump(void) { + static char *states[] = { + [UNUSED] "unused", [USED] "used", [SLEEPING] "sleep ", + [RUNNABLE] "runble", [RUNNING] "run ", [ZOMBIE] "zombie"}; + struct proc *p; + char *state; - printf("\n"); - for(p = proc; p < &proc[NPROC]; p++){ - if(p->state == UNUSED) - continue; - if(p->state >= 0 && p->state < NELEM(states) && states[p->state]) - state = states[p->state]; - else - state = "???"; - printf("%d %s %s", p->pid, state, p->name); - printf("\n"); - } + printf("\n"); + for (p = proc; p < &proc[NPROC]; p++) { + if (p->state == UNUSED) + continue; + if (p->state >= 0 && p->state < NELEM(states) && states[p->state]) + state = states[p->state]; + else + state = "???"; + printf("%d %s %s", p->pid, state, p->name); + printf("\n"); + } } diff --git a/kernel/ramdisk.c b/kernel/ramdisk.c index eb60ee7..6359b10 100644 --- a/kernel/ramdisk.c +++ b/kernel/ramdisk.c @@ -12,34 +12,29 @@ #include "fs.h" #include "buf.h" -void -ramdiskinit(void) -{ -} +void ramdiskinit(void) {} // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. // Else if B_VALID is not set, read buf from disk, set B_VALID. -void -ramdiskrw(struct buf *b) -{ - if(!holdingsleep(&b->lock)) - panic("ramdiskrw: buf not locked"); - if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) - panic("ramdiskrw: nothing to do"); +void ramdiskrw(struct buf *b) { + if (!holdingsleep(&b->lock)) + panic("ramdiskrw: buf not locked"); + if ((b->flags & (B_VALID | B_DIRTY)) == B_VALID) + panic("ramdiskrw: nothing to do"); - if(b->blockno >= FSSIZE) - panic("ramdiskrw: blockno too big"); + if (b->blockno >= FSSIZE) + panic("ramdiskrw: blockno too big"); - uint64 diskaddr = b->blockno * BSIZE; - char *addr = (char *)RAMDISK + diskaddr; + uint64 diskaddr = b->blockno * BSIZE; + char *addr = (char *)RAMDISK + diskaddr; - if(b->flags & B_DIRTY){ - // write - memmove(addr, b->data, BSIZE); - b->flags &= ~B_DIRTY; - } else { - // read - memmove(b->data, addr, BSIZE); - b->flags |= B_VALID; - } + if (b->flags & B_DIRTY) { + // write + memmove(addr, b->data, BSIZE); + b->flags &= ~B_DIRTY; + } else { + // read + memmove(b->data, addr, BSIZE); + b->flags |= B_VALID; + } } diff --git a/kernel/sleeplock.c b/kernel/sleeplock.c index 81de585..0e06320 100644 --- a/kernel/sleeplock.c +++ b/kernel/sleeplock.c @@ -9,47 +9,36 @@ #include "proc.h" #include "sleeplock.h" -void -initsleeplock(struct sleeplock *lk, char *name) -{ - initlock(&lk->lk, "sleep lock"); - lk->name = name; - lk->locked = 0; - lk->pid = 0; +void initsleeplock(struct sleeplock *lk, char *name) { + initlock(&lk->lk, "sleep lock"); + lk->name = name; + lk->locked = 0; + lk->pid = 0; } -void -acquiresleep(struct sleeplock *lk) -{ - acquire(&lk->lk); - while (lk->locked) { - sleep(lk, &lk->lk); - } - lk->locked = 1; - lk->pid = myproc()->pid; - release(&lk->lk); +void acquiresleep(struct sleeplock *lk) { + acquire(&lk->lk); + while (lk->locked) { + sleep(lk, &lk->lk); + } + lk->locked = 1; + lk->pid = myproc()->pid; + release(&lk->lk); } -void -releasesleep(struct sleeplock *lk) -{ - acquire(&lk->lk); - lk->locked = 0; - lk->pid = 0; - wakeup(lk); - release(&lk->lk); +void releasesleep(struct sleeplock *lk) { + acquire(&lk->lk); + lk->locked = 0; + lk->pid = 0; + wakeup(lk); + release(&lk->lk); } -int -holdingsleep(struct sleeplock *lk) -{ - int r; - - acquire(&lk->lk); - r = lk->locked && (lk->pid == myproc()->pid); - release(&lk->lk); - return r; +int holdingsleep(struct sleeplock *lk) { + int r; + + acquire(&lk->lk); + r = lk->locked && (lk->pid == myproc()->pid); + release(&lk->lk); + return r; } - - - diff --git a/kernel/spinlock.c b/kernel/spinlock.c index 9840302..aaf1b09 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c @@ -8,103 +8,91 @@ #include "proc.h" #include "defs.h" -void -initlock(struct spinlock *lk, char *name) -{ - lk->name = name; - lk->locked = 0; - lk->cpu = 0; +void initlock(struct spinlock *lk, char *name) { + lk->name = name; + lk->locked = 0; + lk->cpu = 0; } // Acquire the lock. // Loops (spins) until the lock is acquired. -void -acquire(struct spinlock *lk) -{ - push_off(); // disable interrupts to avoid deadlock. - if(holding(lk)) - panic("acquire"); +void acquire(struct spinlock *lk) { + push_off(); // disable interrupts to avoid deadlock. + if (holding(lk)) + panic("acquire"); - // On RISC-V, sync_lock_test_and_set turns into an atomic swap: - // a5 = 1 - // s1 = &lk->locked - // amoswap.w.aq a5, a5, (s1) - while(__sync_lock_test_and_set(&lk->locked, 1) != 0) - ; + // On RISC-V, sync_lock_test_and_set turns into an atomic swap: + // a5 = 1 + // s1 = &lk->locked + // amoswap.w.aq a5, a5, (s1) + while (__sync_lock_test_and_set(&lk->locked, 1) != 0) + ; - // Tell the C compiler and the processor to not move loads or stores - // past this point, to ensure that the critical section's memory - // references happen strictly after the lock is acquired. - // On RISC-V, this emits a fence instruction. - __sync_synchronize(); + // Tell the C compiler and the processor to not move loads or stores + // past this point, to ensure that the critical section's memory + // references happen strictly after the lock is acquired. + // On RISC-V, this emits a fence instruction. + __sync_synchronize(); - // Record info about lock acquisition for holding() and debugging. - lk->cpu = mycpu(); + // Record info about lock acquisition for holding() and debugging. + lk->cpu = mycpu(); } // Release the lock. -void -release(struct spinlock *lk) -{ - if(!holding(lk)) - panic("release"); +void release(struct spinlock *lk) { + if (!holding(lk)) + panic("release"); - lk->cpu = 0; + lk->cpu = 0; - // Tell the C compiler and the CPU to not move loads or stores - // past this point, to ensure that all the stores in the critical - // section are visible to other CPUs before the lock is released, - // and that loads in the critical section occur strictly before - // the lock is released. - // On RISC-V, this emits a fence instruction. - __sync_synchronize(); + // Tell the C compiler and the CPU to not move loads or stores + // past this point, to ensure that all the stores in the critical + // section are visible to other CPUs before the lock is released, + // and that loads in the critical section occur strictly before + // the lock is released. + // On RISC-V, this emits a fence instruction. + __sync_synchronize(); - // Release the lock, equivalent to lk->locked = 0. - // This code doesn't use a C assignment, since the C standard - // implies that an assignment might be implemented with - // multiple store instructions. - // On RISC-V, sync_lock_release turns into an atomic swap: - // s1 = &lk->locked - // amoswap.w zero, zero, (s1) - __sync_lock_release(&lk->locked); + // Release the lock, equivalent to lk->locked = 0. + // This code doesn't use a C assignment, since the C standard + // implies that an assignment might be implemented with + // multiple store instructions. + // On RISC-V, sync_lock_release turns into an atomic swap: + // s1 = &lk->locked + // amoswap.w zero, zero, (s1) + __sync_lock_release(&lk->locked); - pop_off(); + pop_off(); } // Check whether this cpu is holding the lock. // Interrupts must be off. -int -holding(struct spinlock *lk) -{ - int r; - r = (lk->locked && lk->cpu == mycpu()); - return r; +int holding(struct spinlock *lk) { + int r; + r = (lk->locked && lk->cpu == mycpu()); + return r; } // push_off/pop_off are like intr_off()/intr_on() except that they are matched: // it takes two pop_off()s to undo two push_off()s. Also, if interrupts // are initially off, then push_off, pop_off leaves them off. -void -push_off(void) -{ - int old = intr_get(); +void push_off(void) { + int old = intr_get(); - intr_off(); - if(mycpu()->noff == 0) - mycpu()->intena = old; - mycpu()->noff += 1; + intr_off(); + if (mycpu()->noff == 0) + mycpu()->intena = old; + mycpu()->noff += 1; } -void -pop_off(void) -{ - struct cpu *c = mycpu(); - if(intr_get()) - panic("pop_off - interruptible"); - if(c->noff < 1) - panic("pop_off"); - c->noff -= 1; - if(c->noff == 0 && c->intena) - intr_on(); +void pop_off(void) { + struct cpu *c = mycpu(); + if (intr_get()) + panic("pop_off - interruptible"); + if (c->noff < 1) + panic("pop_off"); + c->noff -= 1; + if (c->noff == 0 && c->intena) + intr_on(); } diff --git a/kernel/start.c b/kernel/start.c index e16f18a..f83b619 100644 --- a/kernel/start.c +++ b/kernel/start.c @@ -8,7 +8,7 @@ void main(); void timerinit(); // entry.S needs one stack per CPU. -__attribute__ ((aligned (16))) char stack0[4096 * NCPU]; +__attribute__((aligned(16))) char stack0[4096 * NCPU]; // a scratch area per CPU for machine-mode timer interrupts. uint64 timer_scratch[NCPU][5]; @@ -17,41 +17,39 @@ uint64 timer_scratch[NCPU][5]; extern void timervec(); // entry.S jumps here in machine mode on stack0. -void -start() -{ - // set M Previous Privilege mode to Supervisor, for mret. - unsigned long x = r_mstatus(); - x &= ~MSTATUS_MPP_MASK; - x |= MSTATUS_MPP_S; - w_mstatus(x); +void start() { + // set M Previous Privilege mode to Supervisor, for mret. + unsigned long x = r_mstatus(); + x &= ~MSTATUS_MPP_MASK; + x |= MSTATUS_MPP_S; + w_mstatus(x); - // set M Exception Program Counter to main, for mret. - // requires gcc -mcmodel=medany - w_mepc((uint64)main); + // set M Exception Program Counter to main, for mret. + // requires gcc -mcmodel=medany + w_mepc((uint64)main); - // disable paging for now. - w_satp(0); + // disable paging for now. + w_satp(0); - // delegate all interrupts and exceptions to supervisor mode. - w_medeleg(0xffff); - w_mideleg(0xffff); - w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE); + // delegate all interrupts and exceptions to supervisor mode. + w_medeleg(0xffff); + w_mideleg(0xffff); + w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE); - // configure Physical Memory Protection to give supervisor mode - // access to all of physical memory. - w_pmpaddr0(0x3fffffffffffffull); - w_pmpcfg0(0xf); + // configure Physical Memory Protection to give supervisor mode + // access to all of physical memory. + w_pmpaddr0(0x3fffffffffffffull); + w_pmpcfg0(0xf); - // ask for clock interrupts. - timerinit(); + // ask for clock interrupts. + timerinit(); - // keep each CPU's hartid in its tp register, for cpuid(). - int id = r_mhartid(); - w_tp(id); + // keep each CPU's hartid in its tp register, for cpuid(). + int id = r_mhartid(); + w_tp(id); - // switch to supervisor mode and jump to main(). - asm volatile("mret"); + // switch to supervisor mode and jump to main(). + asm volatile("mret"); } // arrange to receive timer interrupts. @@ -59,31 +57,29 @@ start() // at timervec in kernelvec.S, // which turns them into software interrupts for // devintr() in trap.c. -void -timerinit() -{ - // each CPU has a separate source of timer interrupts. - int id = r_mhartid(); +void timerinit() { + // each CPU has a separate source of timer interrupts. + int id = r_mhartid(); - // ask the CLINT for a timer interrupt. - int interval = 1000000; // cycles; about 1/10th second in qemu. - *(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + interval; + // ask the CLINT for a timer interrupt. + int interval = 1000000; // cycles; about 1/10th second in qemu. + *(uint64 *)CLINT_MTIMECMP(id) = *(uint64 *)CLINT_MTIME + interval; - // prepare information in scratch[] for timervec. - // scratch[0..2] : space for timervec to save registers. - // scratch[3] : address of CLINT MTIMECMP register. - // scratch[4] : desired interval (in cycles) between timer interrupts. - uint64 *scratch = &timer_scratch[id][0]; - scratch[3] = CLINT_MTIMECMP(id); - scratch[4] = interval; - w_mscratch((uint64)scratch); + // prepare information in scratch[] for timervec. + // scratch[0..2] : space for timervec to save registers. + // scratch[3] : address of CLINT MTIMECMP register. + // scratch[4] : desired interval (in cycles) between timer interrupts. + uint64 *scratch = &timer_scratch[id][0]; + scratch[3] = CLINT_MTIMECMP(id); + scratch[4] = interval; + w_mscratch((uint64)scratch); - // set the machine-mode trap handler. - w_mtvec((uint64)timervec); + // set the machine-mode trap handler. + w_mtvec((uint64)timervec); - // enable machine-mode interrupts. - w_mstatus(r_mstatus() | MSTATUS_MIE); + // enable machine-mode interrupts. + w_mstatus(r_mstatus() | MSTATUS_MIE); - // enable machine-mode timer interrupts. - w_mie(r_mie() | MIE_MTIE); + // enable machine-mode timer interrupts. + w_mie(r_mie() | MIE_MTIE); } diff --git a/kernel/string.c b/kernel/string.c index 153536f..2392150 100644 --- a/kernel/string.c +++ b/kernel/string.c @@ -1,107 +1,90 @@ #include "types.h" -void* -memset(void *dst, int c, uint n) -{ - char *cdst = (char *) dst; - int i; - for(i = 0; i < n; i++){ - cdst[i] = c; - } - return dst; +void *memset(void *dst, int c, uint n) { + char *cdst = (char *)dst; + int i; + for (i = 0; i < n; i++) { + cdst[i] = c; + } + return dst; } -int -memcmp(const void *v1, const void *v2, uint n) -{ - const uchar *s1, *s2; +int memcmp(const void *v1, const void *v2, uint n) { + const uchar *s1, *s2; - s1 = v1; - s2 = v2; - while(n-- > 0){ - if(*s1 != *s2) - return *s1 - *s2; - s1++, s2++; - } + s1 = v1; + s2 = v2; + while (n-- > 0) { + if (*s1 != *s2) + return *s1 - *s2; + s1++, s2++; + } - return 0; + return 0; } -void* -memmove(void *dst, const void *src, uint n) -{ - const char *s; - char *d; +void *memmove(void *dst, const void *src, uint n) { + const char *s; + char *d; - if(n == 0) - return dst; - - s = src; - d = dst; - if(s < d && s + n > d){ - s += n; - d += n; - while(n-- > 0) - *--d = *--s; - } else - while(n-- > 0) - *d++ = *s++; + if (n == 0) + return dst; - return dst; + s = src; + d = dst; + if (s < d && s + n > d) { + s += n; + d += n; + while (n-- > 0) + *--d = *--s; + } else + while (n-- > 0) + *d++ = *s++; + + return dst; } // memcpy exists to placate GCC. Use memmove. -void* -memcpy(void *dst, const void *src, uint n) -{ - return memmove(dst, src, n); +void *memcpy(void *dst, const void *src, uint n) { + return memmove(dst, src, n); } -int -strncmp(const char *p, const char *q, uint n) -{ - while(n > 0 && *p && *p == *q) - n--, p++, q++; - if(n == 0) - return 0; - return (uchar)*p - (uchar)*q; +int strncmp(const char *p, const char *q, uint n) { + while (n > 0 && *p && *p == *q) + n--, p++, q++; + if (n == 0) + return 0; + return (uchar)*p - (uchar)*q; } -char* -strncpy(char *s, const char *t, int n) -{ - char *os; +char *strncpy(char *s, const char *t, int n) { + char *os; - os = s; - while(n-- > 0 && (*s++ = *t++) != 0) - ; - while(n-- > 0) - *s++ = 0; - return os; + os = s; + while (n-- > 0 && (*s++ = *t++) != 0) + ; + while (n-- > 0) + *s++ = 0; + return os; } // Like strncpy but guaranteed to NUL-terminate. -char* -safestrcpy(char *s, const char *t, int n) -{ - char *os; +char *safestrcpy(char *s, const char *t, int n) { + char *os; - os = s; - if(n <= 0) - return os; - while(--n > 0 && (*s++ = *t++) != 0) - ; - *s = 0; - return os; + os = s; + if (n <= 0) + return os; + while (--n > 0 && (*s++ = *t++) != 0) + ; + *s = 0; + return os; } -int -strlen(const char *s) -{ - int n; +int strlen(const char *s) { + int n; - for(n = 0; s[n]; n++) - ; - return n; + for (n = 0; s[n]; n++) + ; + return n; } - diff --git a/kernel/syscall.c b/kernel/syscall.c index ed65409..9b1e67f 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -8,75 +8,60 @@ #include "defs.h" // Fetch the uint64 at addr from the current process. -int -fetchaddr(uint64 addr, uint64 *ip) -{ - struct proc *p = myproc(); - 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; - return 0; +int fetchaddr(uint64 addr, uint64 *ip) { + struct proc *p = myproc(); + 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; + return 0; } // Fetch the nul-terminated string at addr from the current process. // Returns length of string, not including nul, or -1 for error. -int -fetchstr(uint64 addr, char *buf, int max) -{ - struct proc *p = myproc(); - if(copyinstr(p->pagetable, buf, addr, max) < 0) - return -1; - return strlen(buf); +int fetchstr(uint64 addr, char *buf, int max) { + struct proc *p = myproc(); + if (copyinstr(p->pagetable, buf, addr, max) < 0) + return -1; + return strlen(buf); } -static uint64 -argraw(int n) -{ - struct proc *p = myproc(); - switch (n) { - case 0: - return p->trapframe->a0; - case 1: - return p->trapframe->a1; - case 2: - return p->trapframe->a2; - case 3: - return p->trapframe->a3; - case 4: - return p->trapframe->a4; - case 5: - return p->trapframe->a5; - } - panic("argraw"); - return -1; +static uint64 argraw(int n) { + struct proc *p = myproc(); + switch (n) { + case 0: + return p->trapframe->a0; + case 1: + return p->trapframe->a1; + case 2: + return p->trapframe->a2; + case 3: + return p->trapframe->a3; + case 4: + return p->trapframe->a4; + case 5: + return p->trapframe->a5; + } + panic("argraw"); + return -1; } // Fetch the nth 32-bit system call argument. -void -argint(int n, int *ip) -{ - *ip = argraw(n); -} +void argint(int n, int *ip) { *ip = argraw(n); } // Retrieve an argument as a pointer. // Doesn't check for legality, since // copyin/copyout will do that. -void -argaddr(int n, uint64 *ip) -{ - *ip = argraw(n); -} +void argaddr(int n, uint64 *ip) { *ip = argraw(n); } // Fetch the nth word-sized system call argument as a null-terminated string. // Copies into buf, at most max. // Returns string length if OK (including nul), -1 if error. -int -argstr(int n, char *buf, int max) -{ - uint64 addr; - argaddr(n, &addr); - return fetchstr(addr, buf, max); +int argstr(int n, char *buf, int max) { + uint64 addr; + argaddr(n, &addr); + return fetchstr(addr, buf, max); } // Prototypes for the functions that handle system calls. @@ -105,43 +90,26 @@ extern uint64 sys_close(void); // An array mapping syscall numbers from syscall.h // to the function that handles the system call. static uint64 (*syscalls[])(void) = { -[SYS_fork] sys_fork, -[SYS_exit] sys_exit, -[SYS_wait] sys_wait, -[SYS_pipe] sys_pipe, -[SYS_read] sys_read, -[SYS_kill] sys_kill, -[SYS_exec] sys_exec, -[SYS_fstat] sys_fstat, -[SYS_chdir] sys_chdir, -[SYS_dup] sys_dup, -[SYS_getpid] sys_getpid, -[SYS_sbrk] sys_sbrk, -[SYS_sleep] sys_sleep, -[SYS_uptime] sys_uptime, -[SYS_open] sys_open, -[SYS_write] sys_write, -[SYS_mknod] sys_mknod, -[SYS_unlink] sys_unlink, -[SYS_link] sys_link, -[SYS_mkdir] sys_mkdir, -[SYS_close] sys_close, + [SYS_fork] sys_fork, [SYS_exit] sys_exit, [SYS_wait] sys_wait, + [SYS_pipe] sys_pipe, [SYS_read] sys_read, [SYS_kill] sys_kill, + [SYS_exec] sys_exec, [SYS_fstat] sys_fstat, [SYS_chdir] sys_chdir, + [SYS_dup] sys_dup, [SYS_getpid] sys_getpid, [SYS_sbrk] sys_sbrk, + [SYS_sleep] sys_sleep, [SYS_uptime] sys_uptime, [SYS_open] sys_open, + [SYS_write] sys_write, [SYS_mknod] sys_mknod, [SYS_unlink] sys_unlink, + [SYS_link] sys_link, [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, }; -void -syscall(void) -{ - int num; - struct proc *p = myproc(); +void syscall(void) { + int num; + struct proc *p = myproc(); - num = p->trapframe->a7; - if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { - // Use num to lookup the system call function for num, call it, - // and store its return value in p->trapframe->a0 - p->trapframe->a0 = syscalls[num](); - } else { - printf("%d %s: unknown sys call %d\n", - p->pid, p->name, num); - p->trapframe->a0 = -1; - } + num = p->trapframe->a7; + if (num > 0 && num < NELEM(syscalls) && syscalls[num]) { + // Use num to lookup the system call function for num, call it, + // and store its return value in p->trapframe->a0 + p->trapframe->a0 = syscalls[num](); + } else { + printf("%d %s: unknown sys call %d\n", p->pid, p->name, num); + p->trapframe->a0 = -1; + } } diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 16b668c..1a4f04d 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -18,488 +18,455 @@ // 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 n, int *pfd, struct file **pf) -{ - int fd; - struct file *f; +static int argfd(int n, int *pfd, struct file **pf) { + int fd; + struct file *f; - argint(n, &fd); - if(fd < 0 || fd >= NOFILE || (f=myproc()->ofile[fd]) == 0) - return -1; - if(pfd) - *pfd = fd; - if(pf) - *pf = f; - return 0; + argint(n, &fd); + if (fd < 0 || fd >= NOFILE || (f = myproc()->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 = myproc(); +static int fdalloc(struct file *f) { + int fd; + struct proc *p = myproc(); - for(fd = 0; fd < NOFILE; fd++){ - if(p->ofile[fd] == 0){ - p->ofile[fd] = f; - return fd; - } - } - return -1; + for (fd = 0; fd < NOFILE; fd++) { + if (p->ofile[fd] == 0) { + p->ofile[fd] = f; + return fd; + } + } + return -1; } -uint64 -sys_dup(void) -{ - struct file *f; - int fd; +uint64 sys_dup(void) { + struct file *f; + int fd; - if(argfd(0, 0, &f) < 0) - return -1; - if((fd=fdalloc(f)) < 0) - return -1; - filedup(f); - return fd; + if (argfd(0, 0, &f) < 0) + return -1; + if ((fd = fdalloc(f)) < 0) + return -1; + filedup(f); + return fd; } -uint64 -sys_read(void) -{ - struct file *f; - int n; - uint64 p; +uint64 sys_read(void) { + struct file *f; + int n; + uint64 p; - argaddr(1, &p); - argint(2, &n); - if(argfd(0, 0, &f) < 0) - return -1; - return fileread(f, p, n); + argaddr(1, &p); + argint(2, &n); + if (argfd(0, 0, &f) < 0) + return -1; + return fileread(f, p, n); } -uint64 -sys_write(void) -{ - struct file *f; - int n; - uint64 p; - - argaddr(1, &p); - argint(2, &n); - if(argfd(0, 0, &f) < 0) - return -1; +uint64 sys_write(void) { + struct file *f; + int n; + uint64 p; - return filewrite(f, p, n); + argaddr(1, &p); + argint(2, &n); + if (argfd(0, 0, &f) < 0) + return -1; + + return filewrite(f, p, n); } -uint64 -sys_close(void) -{ - int fd; - struct file *f; +uint64 sys_close(void) { + int fd; + struct file *f; - if(argfd(0, &fd, &f) < 0) - return -1; - myproc()->ofile[fd] = 0; - fileclose(f); - return 0; + if (argfd(0, &fd, &f) < 0) + return -1; + myproc()->ofile[fd] = 0; + fileclose(f); + return 0; } -uint64 -sys_fstat(void) -{ - struct file *f; - uint64 st; // user pointer to struct stat +uint64 sys_fstat(void) { + struct file *f; + uint64 st; // user pointer to struct stat - argaddr(1, &st); - if(argfd(0, 0, &f) < 0) - return -1; - return filestat(f, st); + argaddr(1, &st); + if (argfd(0, 0, &f) < 0) + return -1; + return filestat(f, st); } // Create the path new as a link to the same inode as old. -uint64 -sys_link(void) -{ - char name[DIRSIZ], new[MAXPATH], old[MAXPATH]; - struct inode *dp, *ip; +uint64 sys_link(void) { + char name[DIRSIZ], new[MAXPATH], old[MAXPATH]; + struct inode *dp, *ip; - if(argstr(0, old, MAXPATH) < 0 || argstr(1, new, MAXPATH) < 0) - return -1; + if (argstr(0, old, MAXPATH) < 0 || argstr(1, new, MAXPATH) < 0) + return -1; - begin_op(); - if((ip = namei(old)) == 0){ - end_op(); - return -1; - } + begin_op(); + if ((ip = namei(old)) == 0) { + end_op(); + return -1; + } - ilock(ip); - if(ip->type == T_DIR){ - iunlockput(ip); - end_op(); - return -1; - } + ilock(ip); + if (ip->type == T_DIR) { + iunlockput(ip); + end_op(); + return -1; + } - ip->nlink++; - iupdate(ip); - iunlock(ip); + ip->nlink++; + iupdate(ip); + iunlock(ip); - if((dp = nameiparent(new, name)) == 0) - goto bad; - ilock(dp); - if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){ - iunlockput(dp); - goto bad; - } - iunlockput(dp); - iput(ip); + if ((dp = nameiparent(new, name)) == 0) + goto bad; + ilock(dp); + if (dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0) { + iunlockput(dp); + goto bad; + } + iunlockput(dp); + iput(ip); - end_op(); + end_op(); - return 0; + return 0; bad: - ilock(ip); - ip->nlink--; - iupdate(ip); - iunlockput(ip); - end_op(); - return -1; + ilock(ip); + ip->nlink--; + iupdate(ip); + iunlockput(ip); + end_op(); + return -1; } // Is the directory dp empty except for "." and ".." ? -static int -isdirempty(struct inode *dp) -{ - int off; - struct dirent de; +static int isdirempty(struct inode *dp) { + int off; + struct dirent de; - for(off=2*sizeof(de); offsize; off+=sizeof(de)){ - if(readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) - panic("isdirempty: readi"); - if(de.inum != 0) - return 0; - } - return 1; + for (off = 2 * sizeof(de); off < dp->size; off += sizeof(de)) { + if (readi(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) + panic("isdirempty: readi"); + if (de.inum != 0) + return 0; + } + return 1; } -uint64 -sys_unlink(void) -{ - struct inode *ip, *dp; - struct dirent de; - char name[DIRSIZ], path[MAXPATH]; - uint off; +uint64 sys_unlink(void) { + struct inode *ip, *dp; + struct dirent de; + char name[DIRSIZ], path[MAXPATH]; + uint off; - if(argstr(0, path, MAXPATH) < 0) - return -1; + if (argstr(0, path, MAXPATH) < 0) + return -1; - begin_op(); - if((dp = nameiparent(path, name)) == 0){ - end_op(); - return -1; - } + begin_op(); + if ((dp = nameiparent(path, name)) == 0) { + end_op(); + return -1; + } - ilock(dp); + ilock(dp); - // Cannot unlink "." or "..". - if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) - goto bad; + // Cannot unlink "." or "..". + if (namecmp(name, ".") == 0 || namecmp(name, "..") == 0) + goto bad; - if((ip = dirlookup(dp, name, &off)) == 0) - goto bad; - ilock(ip); + if ((ip = dirlookup(dp, name, &off)) == 0) + goto bad; + ilock(ip); - if(ip->nlink < 1) - panic("unlink: nlink < 1"); - if(ip->type == T_DIR && !isdirempty(ip)){ - iunlockput(ip); - goto bad; - } + if (ip->nlink < 1) + panic("unlink: nlink < 1"); + if (ip->type == T_DIR && !isdirempty(ip)) { + iunlockput(ip); + goto bad; + } - memset(&de, 0, sizeof(de)); - if(writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) - panic("unlink: writei"); - if(ip->type == T_DIR){ - dp->nlink--; - iupdate(dp); - } - iunlockput(dp); + memset(&de, 0, sizeof(de)); + if (writei(dp, 0, (uint64)&de, off, sizeof(de)) != sizeof(de)) + panic("unlink: writei"); + if (ip->type == T_DIR) { + dp->nlink--; + iupdate(dp); + } + iunlockput(dp); - ip->nlink--; - iupdate(ip); - iunlockput(ip); + ip->nlink--; + iupdate(ip); + iunlockput(ip); - end_op(); + end_op(); - return 0; + return 0; bad: - iunlockput(dp); - end_op(); - return -1; + iunlockput(dp); + end_op(); + return -1; } -static struct inode* -create(char *path, short type, short major, short minor) -{ - struct inode *ip, *dp; - char name[DIRSIZ]; +static struct inode *create(char *path, short type, short major, short minor) { + struct inode *ip, *dp; + char name[DIRSIZ]; - if((dp = nameiparent(path, name)) == 0) - return 0; + if ((dp = nameiparent(path, name)) == 0) + return 0; - ilock(dp); + ilock(dp); - if((ip = dirlookup(dp, name, 0)) != 0){ - iunlockput(dp); - ilock(ip); - if(type == T_FILE && (ip->type == T_FILE || ip->type == T_DEVICE)) - return ip; - iunlockput(ip); - return 0; - } + if ((ip = dirlookup(dp, name, 0)) != 0) { + iunlockput(dp); + ilock(ip); + if (type == T_FILE && (ip->type == T_FILE || ip->type == T_DEVICE)) + return ip; + iunlockput(ip); + return 0; + } - if((ip = ialloc(dp->dev, type)) == 0){ - iunlockput(dp); - return 0; - } + if ((ip = ialloc(dp->dev, type)) == 0) { + iunlockput(dp); + return 0; + } - ilock(ip); - ip->major = major; - ip->minor = minor; - ip->nlink = 1; - iupdate(ip); + ilock(ip); + ip->major = major; + ip->minor = minor; + ip->nlink = 1; + iupdate(ip); - if(type == T_DIR){ // Create . and .. entries. - // No ip->nlink++ for ".": avoid cyclic ref count. - if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) - goto fail; - } + if (type == T_DIR) { // Create . and .. entries. + // No ip->nlink++ for ".": avoid cyclic ref count. + if (dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) + goto fail; + } - if(dirlink(dp, name, ip->inum) < 0) - goto fail; + if (dirlink(dp, name, ip->inum) < 0) + goto fail; - if(type == T_DIR){ - // now that success is guaranteed: - dp->nlink++; // for ".." - iupdate(dp); - } + if (type == T_DIR) { + // now that success is guaranteed: + dp->nlink++; // for ".." + iupdate(dp); + } - iunlockput(dp); + iunlockput(dp); - return ip; + return ip; - fail: - // something went wrong. de-allocate ip. - ip->nlink = 0; - iupdate(ip); - iunlockput(ip); - iunlockput(dp); - return 0; +fail: + // something went wrong. de-allocate ip. + ip->nlink = 0; + iupdate(ip); + iunlockput(ip); + iunlockput(dp); + return 0; } -uint64 -sys_open(void) -{ - char path[MAXPATH]; - int fd, omode; - struct file *f; - struct inode *ip; - int n; +uint64 sys_open(void) { + char path[MAXPATH]; + int fd, omode; + struct file *f; + struct inode *ip; + int n; - argint(1, &omode); - if((n = argstr(0, path, MAXPATH)) < 0) - return -1; + argint(1, &omode); + if ((n = argstr(0, path, MAXPATH)) < 0) + return -1; - begin_op(); + begin_op(); - if(omode & O_CREATE){ - ip = create(path, T_FILE, 0, 0); - if(ip == 0){ - end_op(); - return -1; - } - } else { - if((ip = namei(path)) == 0){ - end_op(); - return -1; - } - ilock(ip); - if(ip->type == T_DIR && omode != O_RDONLY){ - iunlockput(ip); - end_op(); - return -1; - } - } + if (omode & O_CREATE) { + ip = create(path, T_FILE, 0, 0); + if (ip == 0) { + end_op(); + return -1; + } + } else { + if ((ip = namei(path)) == 0) { + end_op(); + return -1; + } + ilock(ip); + if (ip->type == T_DIR && omode != O_RDONLY) { + iunlockput(ip); + end_op(); + return -1; + } + } - if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){ - iunlockput(ip); - end_op(); - return -1; - } + if (ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)) { + iunlockput(ip); + end_op(); + return -1; + } - if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ - if(f) - fileclose(f); - iunlockput(ip); - end_op(); - return -1; - } + if ((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0) { + if (f) + fileclose(f); + iunlockput(ip); + end_op(); + return -1; + } - if(ip->type == T_DEVICE){ - f->type = FD_DEVICE; - f->major = ip->major; - } else { - f->type = FD_INODE; - f->off = 0; - } - f->ip = ip; - f->readable = !(omode & O_WRONLY); - f->writable = (omode & O_WRONLY) || (omode & O_RDWR); + if (ip->type == T_DEVICE) { + f->type = FD_DEVICE; + f->major = ip->major; + } else { + f->type = FD_INODE; + f->off = 0; + } + f->ip = ip; + f->readable = !(omode & O_WRONLY); + f->writable = (omode & O_WRONLY) || (omode & O_RDWR); - if((omode & O_TRUNC) && ip->type == T_FILE){ - itrunc(ip); - } + if ((omode & O_TRUNC) && ip->type == T_FILE) { + itrunc(ip); + } - iunlock(ip); - end_op(); + iunlock(ip); + end_op(); - return fd; + return fd; } -uint64 -sys_mkdir(void) -{ - char path[MAXPATH]; - struct inode *ip; +uint64 sys_mkdir(void) { + char path[MAXPATH]; + struct inode *ip; - begin_op(); - if(argstr(0, path, MAXPATH) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){ - end_op(); - return -1; - } - iunlockput(ip); - end_op(); - return 0; + begin_op(); + if (argstr(0, path, MAXPATH) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0) { + end_op(); + return -1; + } + iunlockput(ip); + end_op(); + return 0; } -uint64 -sys_mknod(void) -{ - struct inode *ip; - char path[MAXPATH]; - int major, minor; +uint64 sys_mknod(void) { + struct inode *ip; + char path[MAXPATH]; + int major, minor; - begin_op(); - argint(1, &major); - argint(2, &minor); - if((argstr(0, path, MAXPATH)) < 0 || - (ip = create(path, T_DEVICE, major, minor)) == 0){ - end_op(); - return -1; - } - iunlockput(ip); - end_op(); - return 0; + begin_op(); + argint(1, &major); + argint(2, &minor); + if ((argstr(0, path, MAXPATH)) < 0 || + (ip = create(path, T_DEVICE, major, minor)) == 0) { + end_op(); + return -1; + } + iunlockput(ip); + end_op(); + return 0; } -uint64 -sys_chdir(void) -{ - char path[MAXPATH]; - struct inode *ip; - struct proc *p = myproc(); - - begin_op(); - if(argstr(0, path, MAXPATH) < 0 || (ip = namei(path)) == 0){ - end_op(); - return -1; - } - ilock(ip); - if(ip->type != T_DIR){ - iunlockput(ip); - end_op(); - return -1; - } - iunlock(ip); - iput(p->cwd); - end_op(); - p->cwd = ip; - return 0; +uint64 sys_chdir(void) { + char path[MAXPATH]; + struct inode *ip; + struct proc *p = myproc(); + + begin_op(); + if (argstr(0, path, MAXPATH) < 0 || (ip = namei(path)) == 0) { + end_op(); + return -1; + } + ilock(ip); + if (ip->type != T_DIR) { + iunlockput(ip); + end_op(); + return -1; + } + iunlock(ip); + iput(p->cwd); + end_op(); + p->cwd = ip; + return 0; } -uint64 -sys_exec(void) -{ - char path[MAXPATH], *argv[MAXARG]; - int i; - uint64 uargv, uarg; +uint64 sys_exec(void) { + char path[MAXPATH], *argv[MAXARG]; + int i; + uint64 uargv, uarg; - argaddr(1, &uargv); - if(argstr(0, path, MAXPATH) < 0) { - return -1; - } - memset(argv, 0, sizeof(argv)); - for(i=0;; i++){ - if(i >= NELEM(argv)){ - goto bad; - } - if(fetchaddr(uargv+sizeof(uint64)*i, (uint64*)&uarg) < 0){ - goto bad; - } - if(uarg == 0){ - argv[i] = 0; - break; - } - argv[i] = kalloc(); - if(argv[i] == 0) - goto bad; - if(fetchstr(uarg, argv[i], PGSIZE) < 0) - goto bad; - } + argaddr(1, &uargv); + if (argstr(0, path, MAXPATH) < 0) { + return -1; + } + memset(argv, 0, sizeof(argv)); + for (i = 0;; i++) { + if (i >= NELEM(argv)) { + goto bad; + } + if (fetchaddr(uargv + sizeof(uint64) * i, (uint64 *)&uarg) < 0) { + goto bad; + } + if (uarg == 0) { + argv[i] = 0; + break; + } + argv[i] = kalloc(); + if (argv[i] == 0) + goto bad; + if (fetchstr(uarg, argv[i], PGSIZE) < 0) + goto bad; + } - int ret = exec(path, argv); + int ret = exec(path, argv); - for(i = 0; i < NELEM(argv) && argv[i] != 0; i++) - kfree(argv[i]); + for (i = 0; i < NELEM(argv) && argv[i] != 0; i++) + kfree(argv[i]); - return ret; + return ret; - bad: - for(i = 0; i < NELEM(argv) && argv[i] != 0; i++) - kfree(argv[i]); - return -1; +bad: + for (i = 0; i < NELEM(argv) && argv[i] != 0; i++) + kfree(argv[i]); + return -1; } -uint64 -sys_pipe(void) -{ - uint64 fdarray; // user pointer to array of two integers - struct file *rf, *wf; - int fd0, fd1; - struct proc *p = myproc(); +uint64 sys_pipe(void) { + uint64 fdarray; // user pointer to array of two integers + struct file *rf, *wf; + int fd0, fd1; + struct proc *p = myproc(); - argaddr(0, &fdarray); - if(pipealloc(&rf, &wf) < 0) - return -1; - fd0 = -1; - if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ - if(fd0 >= 0) - p->ofile[fd0] = 0; - fileclose(rf); - fileclose(wf); - return -1; - } - if(copyout(p->pagetable, fdarray, (char*)&fd0, sizeof(fd0)) < 0 || - copyout(p->pagetable, fdarray+sizeof(fd0), (char *)&fd1, sizeof(fd1)) < 0){ - p->ofile[fd0] = 0; - p->ofile[fd1] = 0; - fileclose(rf); - fileclose(wf); - return -1; - } - return 0; + argaddr(0, &fdarray); + if (pipealloc(&rf, &wf) < 0) + return -1; + fd0 = -1; + if ((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0) { + if (fd0 >= 0) + p->ofile[fd0] = 0; + fileclose(rf); + fileclose(wf); + return -1; + } + if (copyout(p->pagetable, fdarray, (char *)&fd0, sizeof(fd0)) < 0 || + copyout(p->pagetable, fdarray + sizeof(fd0), (char *)&fd1, + sizeof(fd1)) < 0) { + p->ofile[fd0] = 0; + p->ofile[fd1] = 0; + fileclose(rf); + fileclose(wf); + return -1; + } + return 0; } diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 1de184e..4e4cb5e 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -6,86 +6,66 @@ #include "spinlock.h" #include "proc.h" -uint64 -sys_exit(void) -{ - int n; - argint(0, &n); - exit(n); - return 0; // not reached +uint64 sys_exit(void) { + int n; + argint(0, &n); + exit(n); + return 0; // not reached } -uint64 -sys_getpid(void) -{ - return myproc()->pid; +uint64 sys_getpid(void) { return myproc()->pid; } + +uint64 sys_fork(void) { return fork(); } + +uint64 sys_wait(void) { + uint64 p; + argaddr(0, &p); + return wait(p); } -uint64 -sys_fork(void) -{ - return fork(); +uint64 sys_sbrk(void) { + uint64 addr; + int n; + + argint(0, &n); + addr = myproc()->sz; + if (growproc(n) < 0) + return -1; + return addr; } -uint64 -sys_wait(void) -{ - uint64 p; - argaddr(0, &p); - return wait(p); +uint64 sys_sleep(void) { + int n; + uint ticks0; + + argint(0, &n); + acquire(&tickslock); + ticks0 = ticks; + while (ticks - ticks0 < n) { + if (killed(myproc())) { + release(&tickslock); + return -1; + } + sleep(&ticks, &tickslock); + } + release(&tickslock); + return 0; } -uint64 -sys_sbrk(void) -{ - uint64 addr; - int n; +uint64 sys_kill(void) { + int pid; - argint(0, &n); - addr = myproc()->sz; - if(growproc(n) < 0) - return -1; - return addr; -} - -uint64 -sys_sleep(void) -{ - int n; - uint ticks0; - - argint(0, &n); - acquire(&tickslock); - ticks0 = ticks; - while(ticks - ticks0 < n){ - if(killed(myproc())){ - release(&tickslock); - return -1; - } - sleep(&ticks, &tickslock); - } - release(&tickslock); - return 0; -} - -uint64 -sys_kill(void) -{ - int pid; - - argint(0, &pid); - return kill(pid); + argint(0, &pid); + return kill(pid); } // return how many clock tick interrupts have occurred // since start. -uint64 -sys_uptime(void) -{ - uint xticks; +uint64 sys_uptime(void) { + uint xticks; - acquire(&tickslock); - xticks = ticks; - release(&tickslock); - return xticks; + acquire(&tickslock); + xticks = ticks; + release(&tickslock); + return xticks; } diff --git a/kernel/trap.c b/kernel/trap.c index 512c850..e45e5c3 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -16,157 +16,141 @@ void kernelvec(); extern int devintr(); -void -trapinit(void) -{ - initlock(&tickslock, "time"); -} +void trapinit(void) { initlock(&tickslock, "time"); } // set up to take exceptions and traps while in the kernel. -void -trapinithart(void) -{ - w_stvec((uint64)kernelvec); -} +void trapinithart(void) { w_stvec((uint64)kernelvec); } // // handle an interrupt, exception, or system call from user space. // called from trampoline.S // -void -usertrap(void) -{ - int which_dev = 0; +void usertrap(void) { + int which_dev = 0; - if((r_sstatus() & SSTATUS_SPP) != 0) - panic("usertrap: not from user mode"); + if ((r_sstatus() & SSTATUS_SPP) != 0) + panic("usertrap: not from user mode"); - // send interrupts and exceptions to kerneltrap(), - // since we're now in the kernel. - w_stvec((uint64)kernelvec); + // send interrupts and exceptions to kerneltrap(), + // since we're now in the kernel. + w_stvec((uint64)kernelvec); - struct proc *p = myproc(); - - // save user program counter. - p->trapframe->epc = r_sepc(); - - if(r_scause() == 8){ - // system call + struct proc *p = myproc(); - if(killed(p)) - exit(-1); + // save user program counter. + p->trapframe->epc = r_sepc(); - // sepc points to the ecall instruction, - // but we want to return to the next instruction. - p->trapframe->epc += 4; + if (r_scause() == 8) { + // system call - // an interrupt will change sepc, scause, and sstatus, - // so enable only now that we're done with those registers. - intr_on(); + if (killed(p)) + exit(-1); - syscall(); - } else if((which_dev = devintr()) != 0){ - // ok - } else { - printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid); - printf(" sepc=%p stval=%p\n", r_sepc(), r_stval()); - setkilled(p); - } + // sepc points to the ecall instruction, + // but we want to return to the next instruction. + p->trapframe->epc += 4; - if(killed(p)) - exit(-1); + // an interrupt will change sepc, scause, and sstatus, + // so enable only now that we're done with those registers. + intr_on(); - // give up the CPU if this is a timer interrupt. - if(which_dev == 2) - yield(); + syscall(); + } else if ((which_dev = devintr()) != 0) { + // ok + } else { + printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid); + printf(" sepc=%p stval=%p\n", r_sepc(), r_stval()); + setkilled(p); + } - usertrapret(); + if (killed(p)) + exit(-1); + + // give up the CPU if this is a timer interrupt. + if (which_dev == 2) + yield(); + + usertrapret(); } // // return to user space // -void -usertrapret(void) -{ - struct proc *p = myproc(); +void usertrapret(void) { + struct proc *p = myproc(); - // we're about to switch the destination of traps from - // kerneltrap() to usertrap(), so turn off interrupts until - // we're back in user space, where usertrap() is correct. - intr_off(); + // we're about to switch the destination of traps from + // kerneltrap() to usertrap(), so turn off interrupts until + // we're back in user space, where usertrap() is correct. + intr_off(); - // send syscalls, interrupts, and exceptions to uservec in trampoline.S - uint64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline); - w_stvec(trampoline_uservec); + // send syscalls, interrupts, and exceptions to uservec in trampoline.S + uint64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline); + w_stvec(trampoline_uservec); - // set up trapframe values that uservec will need when - // 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; - p->trapframe->kernel_hartid = r_tp(); // hartid for cpuid() + // set up trapframe values that uservec will need when + // 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; + p->trapframe->kernel_hartid = r_tp(); // hartid for cpuid() - // set up the registers that trampoline.S's sret will use - // to get to user space. - - // set S Previous Privilege mode to User. - unsigned long x = r_sstatus(); - x &= ~SSTATUS_SPP; // clear SPP to 0 for user mode - x |= SSTATUS_SPIE; // enable interrupts in user mode - w_sstatus(x); + // set up the registers that trampoline.S's sret will use + // to get to user space. - // set S Exception Program Counter to the saved user pc. - w_sepc(p->trapframe->epc); + // set S Previous Privilege mode to User. + unsigned long x = r_sstatus(); + x &= ~SSTATUS_SPP; // clear SPP to 0 for user mode + x |= SSTATUS_SPIE; // enable interrupts in user mode + w_sstatus(x); - // tell trampoline.S the user page table to switch to. - uint64 satp = MAKE_SATP(p->pagetable); + // set S Exception Program Counter to the saved user pc. + w_sepc(p->trapframe->epc); - // jump to userret in trampoline.S at the top of memory, which - // switches to the user page table, restores user registers, - // and switches to user mode with sret. - uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline); - ((void (*)(uint64))trampoline_userret)(satp); + // tell trampoline.S the user page table to switch to. + uint64 satp = MAKE_SATP(p->pagetable); + + // jump to userret in trampoline.S at the top of memory, which + // switches to the user page table, restores user registers, + // and switches to user mode with sret. + uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline); + ((void (*)(uint64))trampoline_userret)(satp); } // interrupts and exceptions from kernel code go here via kernelvec, // on whatever the current kernel stack is. -void -kerneltrap() -{ - int which_dev = 0; - uint64 sepc = r_sepc(); - uint64 sstatus = r_sstatus(); - uint64 scause = r_scause(); - - if((sstatus & SSTATUS_SPP) == 0) - panic("kerneltrap: not from supervisor mode"); - if(intr_get() != 0) - panic("kerneltrap: interrupts enabled"); +void kerneltrap() { + int which_dev = 0; + uint64 sepc = r_sepc(); + uint64 sstatus = r_sstatus(); + uint64 scause = r_scause(); - if((which_dev = devintr()) == 0){ - printf("scause %p\n", scause); - printf("sepc=%p stval=%p\n", r_sepc(), r_stval()); - panic("kerneltrap"); - } + if ((sstatus & SSTATUS_SPP) == 0) + panic("kerneltrap: not from supervisor mode"); + if (intr_get() != 0) + panic("kerneltrap: interrupts enabled"); - // give up the CPU if this is a timer interrupt. - if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING) - yield(); + if ((which_dev = devintr()) == 0) { + printf("scause %p\n", scause); + printf("sepc=%p stval=%p\n", r_sepc(), r_stval()); + panic("kerneltrap"); + } - // the yield() may have caused some traps to occur, - // so restore trap registers for use by kernelvec.S's sepc instruction. - w_sepc(sepc); - w_sstatus(sstatus); + // give up the CPU if this is a timer interrupt. + if (which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING) + yield(); + + // the yield() may have caused some traps to occur, + // so restore trap registers for use by kernelvec.S's sepc instruction. + w_sepc(sepc); + w_sstatus(sstatus); } -void -clockintr() -{ - acquire(&tickslock); - ticks++; - wakeup(&ticks); - release(&tickslock); +void clockintr() { + acquire(&tickslock); + ticks++; + wakeup(&ticks); + release(&tickslock); } // check if it's an external interrupt or software interrupt, @@ -174,48 +158,44 @@ clockintr() // returns 2 if timer interrupt, // 1 if other device, // 0 if not recognized. -int -devintr() -{ - uint64 scause = r_scause(); +int devintr() { + uint64 scause = r_scause(); - if((scause & 0x8000000000000000L) && - (scause & 0xff) == 9){ - // this is a supervisor external interrupt, via PLIC. + if ((scause & 0x8000000000000000L) && (scause & 0xff) == 9) { + // this is a supervisor external interrupt, via PLIC. - // irq indicates which device interrupted. - int irq = plic_claim(); + // irq indicates which device interrupted. + int irq = plic_claim(); - if(irq == UART0_IRQ){ - uartintr(); - } else if(irq == VIRTIO0_IRQ){ - virtio_disk_intr(); - } else if(irq){ - printf("unexpected interrupt irq=%d\n", irq); - } + if (irq == UART0_IRQ) { + uartintr(); + } else if (irq == VIRTIO0_IRQ) { + virtio_disk_intr(); + } else if (irq) { + printf("unexpected interrupt irq=%d\n", irq); + } - // the PLIC allows each device to raise at most one - // interrupt at a time; tell the PLIC the device is - // now allowed to interrupt again. - if(irq) - plic_complete(irq); + // the PLIC allows each device to raise at most one + // interrupt at a time; tell the PLIC the device is + // now allowed to interrupt again. + if (irq) + plic_complete(irq); - return 1; - } else if(scause == 0x8000000000000001L){ - // software interrupt from a machine-mode timer interrupt, - // forwarded by timervec in kernelvec.S. + return 1; + } else if (scause == 0x8000000000000001L) { + // software interrupt from a machine-mode timer interrupt, + // forwarded by timervec in kernelvec.S. - if(cpuid() == 0){ - clockintr(); - } - - // acknowledge the software interrupt by clearing - // the SSIP bit in sip. - w_sip(r_sip() & ~2); + if (cpuid() == 0) { + clockintr(); + } - return 2; - } else { - return 0; - } + // acknowledge the software interrupt by clearing + // the SSIP bit in sip. + w_sip(r_sip() & ~2); + + return 2; + } else { + return 0; + } } - diff --git a/kernel/uart.c b/kernel/uart.c index e3b3b8a..5ad60c9 100644 --- a/kernel/uart.c +++ b/kernel/uart.c @@ -19,21 +19,21 @@ // some have different meanings for // read vs write. // see http://byterunner.com/16550.html -#define RHR 0 // receive holding register (for input bytes) -#define THR 0 // transmit holding register (for output bytes) -#define IER 1 // interrupt enable register -#define IER_RX_ENABLE (1<<0) -#define IER_TX_ENABLE (1<<1) -#define FCR 2 // FIFO control register -#define FCR_FIFO_ENABLE (1<<0) -#define FCR_FIFO_CLEAR (3<<1) // clear the content of the two FIFOs -#define ISR 2 // interrupt status register -#define LCR 3 // line control register -#define LCR_EIGHT_BITS (3<<0) -#define LCR_BAUD_LATCH (1<<7) // special mode to set baud rate -#define LSR 5 // line status register -#define LSR_RX_READY (1<<0) // input is waiting to be read from RHR -#define LSR_TX_IDLE (1<<5) // THR can accept another character to send +#define RHR 0 // receive holding register (for input bytes) +#define THR 0 // transmit holding register (for output bytes) +#define IER 1 // interrupt enable register +#define IER_RX_ENABLE (1 << 0) +#define IER_TX_ENABLE (1 << 1) +#define FCR 2 // FIFO control register +#define FCR_FIFO_ENABLE (1 << 0) +#define FCR_FIFO_CLEAR (3 << 1) // clear the content of the two FIFOs +#define ISR 2 // interrupt status register +#define LCR 3 // line control register +#define LCR_EIGHT_BITS (3 << 0) +#define LCR_BAUD_LATCH (1 << 7) // special mode to set baud rate +#define LSR 5 // line status register +#define LSR_RX_READY (1 << 0) // input is waiting to be read from RHR +#define LSR_TX_IDLE (1 << 5) // THR can accept another character to send #define ReadReg(reg) (*(Reg(reg))) #define WriteReg(reg, v) (*(Reg(reg)) = (v)) @@ -49,32 +49,30 @@ extern volatile int panicked; // from printf.c void uartstart(); -void -uartinit(void) -{ - // disable interrupts. - WriteReg(IER, 0x00); +void uartinit(void) { + // disable interrupts. + WriteReg(IER, 0x00); - // special mode to set baud rate. - WriteReg(LCR, LCR_BAUD_LATCH); + // special mode to set baud rate. + WriteReg(LCR, LCR_BAUD_LATCH); - // LSB for baud rate of 38.4K. - WriteReg(0, 0x03); + // LSB for baud rate of 38.4K. + WriteReg(0, 0x03); - // MSB for baud rate of 38.4K. - WriteReg(1, 0x00); + // MSB for baud rate of 38.4K. + WriteReg(1, 0x00); - // leave set-baud mode, - // and set word length to 8 bits, no parity. - WriteReg(LCR, LCR_EIGHT_BITS); + // leave set-baud mode, + // and set word length to 8 bits, no parity. + WriteReg(LCR, LCR_EIGHT_BITS); - // reset and enable FIFOs. - WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR); + // reset and enable FIFOs. + WriteReg(FCR, FCR_FIFO_ENABLE | FCR_FIFO_CLEAR); - // enable transmit and receive interrupts. - WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE); + // enable transmit and receive interrupts. + WriteReg(IER, IER_TX_ENABLE | IER_RX_ENABLE); - initlock(&uart_tx_lock, "uart"); + initlock(&uart_tx_lock, "uart"); } // add a character to the output buffer and tell the @@ -83,108 +81,97 @@ uartinit(void) // because it may block, it can't be called // from interrupts; it's only suitable for use // by write(). -void -uartputc(int c) -{ - acquire(&uart_tx_lock); +void uartputc(int c) { + acquire(&uart_tx_lock); - if(panicked){ - for(;;) - ; - } - 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); + if (panicked) { + for (;;) + ; + } + 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 +// 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 // output register to be empty. -void -uartputc_sync(int c) -{ - push_off(); +void uartputc_sync(int c) { + push_off(); - if(panicked){ - for(;;) - ; - } + if (panicked) { + for (;;) + ; + } - // wait for Transmit Holding Empty to be set in LSR. - while((ReadReg(LSR) & LSR_TX_IDLE) == 0) - ; - WriteReg(THR, c); + // wait for Transmit Holding Empty to be set in LSR. + while ((ReadReg(LSR) & LSR_TX_IDLE) == 0) + ; + WriteReg(THR, c); - pop_off(); + pop_off(); } // if the UART is idle, and a character is waiting // in the transmit buffer, send it. // caller must hold uart_tx_lock. // called from both the top- and bottom-half. -void -uartstart() -{ - while(1){ - if(uart_tx_w == uart_tx_r){ - // transmit buffer is empty. - return; - } - - if((ReadReg(LSR) & LSR_TX_IDLE) == 0){ - // the UART transmit holding register is full, - // so we cannot give it another byte. - // it will interrupt when it's ready for a new byte. - return; - } - - int c = uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE]; - uart_tx_r += 1; - - // maybe uartputc() is waiting for space in the buffer. - wakeup(&uart_tx_r); - - WriteReg(THR, c); - } +void uartstart() { + while (1) { + if (uart_tx_w == uart_tx_r) { + // transmit buffer is empty. + return; + } + + if ((ReadReg(LSR) & LSR_TX_IDLE) == 0) { + // the UART transmit holding register is full, + // so we cannot give it another byte. + // it will interrupt when it's ready for a new byte. + return; + } + + int c = uart_tx_buf[uart_tx_r % UART_TX_BUF_SIZE]; + uart_tx_r += 1; + + // maybe uartputc() is waiting for space in the buffer. + wakeup(&uart_tx_r); + + WriteReg(THR, c); + } } // read one input character from the UART. // return -1 if none is waiting. -int -uartgetc(void) -{ - if(ReadReg(LSR) & 0x01){ - // input data is ready. - return ReadReg(RHR); - } else { - return -1; - } +int uartgetc(void) { + if (ReadReg(LSR) & 0x01) { + // input data is ready. + return ReadReg(RHR); + } else { + return -1; + } } // handle a uart interrupt, raised because input has // arrived, or the uart is ready for more output, or // both. called from devintr(). -void -uartintr(void) -{ - // read and process incoming characters. - while(1){ - int c = uartgetc(); - if(c == -1) - break; - consoleintr(c); - } +void uartintr(void) { + // read and process incoming characters. + while (1) { + int c = uartgetc(); + if (c == -1) + break; + consoleintr(c); + } - // send buffered characters. - acquire(&uart_tx_lock); - uartstart(); - release(&uart_tx_lock); + // send buffered characters. + acquire(&uart_tx_lock); + uartstart(); + release(&uart_tx_lock); } diff --git a/kernel/virtio_disk.c b/kernel/virtio_disk.c index ae6c164..f286b39 100644 --- a/kernel/virtio_disk.c +++ b/kernel/virtio_disk.c @@ -2,7 +2,8 @@ // driver for qemu's virtio disk device. // uses qemu's mmio interface to virtio. // -// qemu ... -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 +// qemu ... -drive file=fs.img,if=none,format=raw,id=x0 -device +// virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 // #include "types.h" @@ -20,308 +21,293 @@ #define R(r) ((volatile uint32 *)(VIRTIO0 + (r))) static struct disk { - // a set (not a ring) of DMA descriptors, with which the - // driver tells the device where to read and write individual - // disk operations. there are NUM descriptors. - // most commands consist of a "chain" (a linked list) of a couple of - // these descriptors. - struct virtq_desc *desc; + // a set (not a ring) of DMA descriptors, with which the + // driver tells the device where to read and write individual + // disk operations. there are NUM descriptors. + // most commands consist of a "chain" (a linked list) of a couple of + // these descriptors. + struct virtq_desc *desc; - // a ring in which the driver writes descriptor numbers - // that the driver would like the device to process. it only - // includes the head descriptor of each chain. the ring has - // NUM elements. - struct virtq_avail *avail; + // a ring in which the driver writes descriptor numbers + // that the driver would like the device to process. it only + // includes the head descriptor of each chain. the ring has + // NUM elements. + struct virtq_avail *avail; - // a ring in which the device writes descriptor numbers that - // the device has finished processing (just the head of each chain). - // there are NUM used ring entries. - struct virtq_used *used; + // a ring in which the device writes descriptor numbers that + // the device has finished processing (just the head of each chain). + // there are NUM used ring entries. + struct virtq_used *used; - // our own book-keeping. - char free[NUM]; // is a descriptor free? - uint16 used_idx; // we've looked this far in used[2..NUM]. + // our own book-keeping. + char free[NUM]; // is a descriptor free? + uint16 used_idx; // we've looked this far in used[2..NUM]. - // track info about in-flight operations, - // for use when completion interrupt arrives. - // indexed by first descriptor index of chain. - struct { - struct buf *b; - char status; - } info[NUM]; + // track info about in-flight operations, + // for use when completion interrupt arrives. + // indexed by first descriptor index of chain. + struct { + struct buf *b; + char status; + } info[NUM]; + + // disk command headers. + // one-for-one with descriptors, for convenience. + struct virtio_blk_req ops[NUM]; + + struct spinlock vdisk_lock; - // disk command headers. - // one-for-one with descriptors, for convenience. - struct virtio_blk_req ops[NUM]; - - struct spinlock vdisk_lock; - } disk; -void -virtio_disk_init(void) -{ - uint32 status = 0; +void virtio_disk_init(void) { + uint32 status = 0; - initlock(&disk.vdisk_lock, "virtio_disk"); + initlock(&disk.vdisk_lock, "virtio_disk"); - if(*R(VIRTIO_MMIO_MAGIC_VALUE) != 0x74726976 || - *R(VIRTIO_MMIO_VERSION) != 2 || - *R(VIRTIO_MMIO_DEVICE_ID) != 2 || - *R(VIRTIO_MMIO_VENDOR_ID) != 0x554d4551){ - panic("could not find virtio disk"); - } - - // reset device - *R(VIRTIO_MMIO_STATUS) = status; + if (*R(VIRTIO_MMIO_MAGIC_VALUE) != 0x74726976 || + *R(VIRTIO_MMIO_VERSION) != 2 || *R(VIRTIO_MMIO_DEVICE_ID) != 2 || + *R(VIRTIO_MMIO_VENDOR_ID) != 0x554d4551) { + panic("could not find virtio disk"); + } - // set ACKNOWLEDGE status bit - status |= VIRTIO_CONFIG_S_ACKNOWLEDGE; - *R(VIRTIO_MMIO_STATUS) = status; + // reset device + *R(VIRTIO_MMIO_STATUS) = status; - // set DRIVER status bit - status |= VIRTIO_CONFIG_S_DRIVER; - *R(VIRTIO_MMIO_STATUS) = status; + // set ACKNOWLEDGE status bit + status |= VIRTIO_CONFIG_S_ACKNOWLEDGE; + *R(VIRTIO_MMIO_STATUS) = status; - // negotiate features - uint64 features = *R(VIRTIO_MMIO_DEVICE_FEATURES); - features &= ~(1 << VIRTIO_BLK_F_RO); - features &= ~(1 << VIRTIO_BLK_F_SCSI); - features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE); - features &= ~(1 << VIRTIO_BLK_F_MQ); - features &= ~(1 << VIRTIO_F_ANY_LAYOUT); - features &= ~(1 << VIRTIO_RING_F_EVENT_IDX); - features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC); - *R(VIRTIO_MMIO_DRIVER_FEATURES) = features; + // set DRIVER status bit + status |= VIRTIO_CONFIG_S_DRIVER; + *R(VIRTIO_MMIO_STATUS) = status; - // tell device that feature negotiation is complete. - status |= VIRTIO_CONFIG_S_FEATURES_OK; - *R(VIRTIO_MMIO_STATUS) = status; + // negotiate features + uint64 features = *R(VIRTIO_MMIO_DEVICE_FEATURES); + features &= ~(1 << VIRTIO_BLK_F_RO); + features &= ~(1 << VIRTIO_BLK_F_SCSI); + features &= ~(1 << VIRTIO_BLK_F_CONFIG_WCE); + features &= ~(1 << VIRTIO_BLK_F_MQ); + features &= ~(1 << VIRTIO_F_ANY_LAYOUT); + features &= ~(1 << VIRTIO_RING_F_EVENT_IDX); + features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC); + *R(VIRTIO_MMIO_DRIVER_FEATURES) = features; - // re-read status to ensure FEATURES_OK is set. - status = *R(VIRTIO_MMIO_STATUS); - if(!(status & VIRTIO_CONFIG_S_FEATURES_OK)) - panic("virtio disk FEATURES_OK unset"); + // tell device that feature negotiation is complete. + status |= VIRTIO_CONFIG_S_FEATURES_OK; + *R(VIRTIO_MMIO_STATUS) = status; - // initialize queue 0. - *R(VIRTIO_MMIO_QUEUE_SEL) = 0; + // re-read status to ensure FEATURES_OK is set. + status = *R(VIRTIO_MMIO_STATUS); + if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) + panic("virtio disk FEATURES_OK unset"); - // ensure queue 0 is not in use. - if(*R(VIRTIO_MMIO_QUEUE_READY)) - panic("virtio disk should not be ready"); + // initialize queue 0. + *R(VIRTIO_MMIO_QUEUE_SEL) = 0; - // check maximum queue size. - uint32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX); - if(max == 0) - panic("virtio disk has no queue 0"); - if(max < NUM) - panic("virtio disk max queue too short"); + // ensure queue 0 is not in use. + if (*R(VIRTIO_MMIO_QUEUE_READY)) + panic("virtio disk should not be ready"); - // allocate and zero queue memory. - disk.desc = kalloc(); - disk.avail = kalloc(); - disk.used = kalloc(); - if(!disk.desc || !disk.avail || !disk.used) - panic("virtio disk kalloc"); - memset(disk.desc, 0, PGSIZE); - memset(disk.avail, 0, PGSIZE); - memset(disk.used, 0, PGSIZE); + // check maximum queue size. + uint32 max = *R(VIRTIO_MMIO_QUEUE_NUM_MAX); + if (max == 0) + panic("virtio disk has no queue 0"); + if (max < NUM) + panic("virtio disk max queue too short"); - // set queue size. - *R(VIRTIO_MMIO_QUEUE_NUM) = NUM; + // allocate and zero queue memory. + disk.desc = kalloc(); + disk.avail = kalloc(); + disk.used = kalloc(); + if (!disk.desc || !disk.avail || !disk.used) + panic("virtio disk kalloc"); + memset(disk.desc, 0, PGSIZE); + memset(disk.avail, 0, PGSIZE); + memset(disk.used, 0, PGSIZE); - // write physical addresses. - *R(VIRTIO_MMIO_QUEUE_DESC_LOW) = (uint64)disk.desc; - *R(VIRTIO_MMIO_QUEUE_DESC_HIGH) = (uint64)disk.desc >> 32; - *R(VIRTIO_MMIO_DRIVER_DESC_LOW) = (uint64)disk.avail; - *R(VIRTIO_MMIO_DRIVER_DESC_HIGH) = (uint64)disk.avail >> 32; - *R(VIRTIO_MMIO_DEVICE_DESC_LOW) = (uint64)disk.used; - *R(VIRTIO_MMIO_DEVICE_DESC_HIGH) = (uint64)disk.used >> 32; + // set queue size. + *R(VIRTIO_MMIO_QUEUE_NUM) = NUM; - // queue is ready. - *R(VIRTIO_MMIO_QUEUE_READY) = 0x1; + // write physical addresses. + *R(VIRTIO_MMIO_QUEUE_DESC_LOW) = (uint64)disk.desc; + *R(VIRTIO_MMIO_QUEUE_DESC_HIGH) = (uint64)disk.desc >> 32; + *R(VIRTIO_MMIO_DRIVER_DESC_LOW) = (uint64)disk.avail; + *R(VIRTIO_MMIO_DRIVER_DESC_HIGH) = (uint64)disk.avail >> 32; + *R(VIRTIO_MMIO_DEVICE_DESC_LOW) = (uint64)disk.used; + *R(VIRTIO_MMIO_DEVICE_DESC_HIGH) = (uint64)disk.used >> 32; - // all NUM descriptors start out unused. - for(int i = 0; i < NUM; i++) - disk.free[i] = 1; + // queue is ready. + *R(VIRTIO_MMIO_QUEUE_READY) = 0x1; - // tell device we're completely ready. - status |= VIRTIO_CONFIG_S_DRIVER_OK; - *R(VIRTIO_MMIO_STATUS) = status; + // all NUM descriptors start out unused. + for (int i = 0; i < NUM; i++) + disk.free[i] = 1; - // plic.c and trap.c arrange for interrupts from VIRTIO0_IRQ. + // tell device we're completely ready. + status |= VIRTIO_CONFIG_S_DRIVER_OK; + *R(VIRTIO_MMIO_STATUS) = status; + + // plic.c and trap.c arrange for interrupts from VIRTIO0_IRQ. } // find a free descriptor, mark it non-free, return its index. -static int -alloc_desc() -{ - for(int i = 0; i < NUM; i++){ - if(disk.free[i]){ - disk.free[i] = 0; - return i; - } - } - return -1; +static int alloc_desc() { + for (int i = 0; i < NUM; i++) { + if (disk.free[i]) { + disk.free[i] = 0; + return i; + } + } + return -1; } // mark a descriptor as free. -static void -free_desc(int i) -{ - if(i >= NUM) - panic("free_desc 1"); - if(disk.free[i]) - panic("free_desc 2"); - disk.desc[i].addr = 0; - disk.desc[i].len = 0; - disk.desc[i].flags = 0; - disk.desc[i].next = 0; - disk.free[i] = 1; - wakeup(&disk.free[0]); +static void free_desc(int i) { + if (i >= NUM) + panic("free_desc 1"); + if (disk.free[i]) + panic("free_desc 2"); + disk.desc[i].addr = 0; + disk.desc[i].len = 0; + disk.desc[i].flags = 0; + disk.desc[i].next = 0; + disk.free[i] = 1; + wakeup(&disk.free[0]); } // free a chain of descriptors. -static void -free_chain(int i) -{ - while(1){ - int flag = disk.desc[i].flags; - int nxt = disk.desc[i].next; - free_desc(i); - if(flag & VRING_DESC_F_NEXT) - i = nxt; - else - break; - } +static void free_chain(int i) { + while (1) { + int flag = disk.desc[i].flags; + int nxt = disk.desc[i].next; + free_desc(i); + if (flag & VRING_DESC_F_NEXT) + i = nxt; + else + break; + } } // allocate three descriptors (they need not be contiguous). // disk transfers always use three descriptors. -static int -alloc3_desc(int *idx) -{ - for(int i = 0; i < 3; i++){ - idx[i] = alloc_desc(); - if(idx[i] < 0){ - for(int j = 0; j < i; j++) - free_desc(idx[j]); - return -1; - } - } - return 0; +static int alloc3_desc(int *idx) { + for (int i = 0; i < 3; i++) { + idx[i] = alloc_desc(); + if (idx[i] < 0) { + for (int j = 0; j < i; j++) + free_desc(idx[j]); + return -1; + } + } + return 0; } -void -virtio_disk_rw(struct buf *b, int write) -{ - uint64 sector = b->blockno * (BSIZE / 512); +void virtio_disk_rw(struct buf *b, int write) { + uint64 sector = b->blockno * (BSIZE / 512); - acquire(&disk.vdisk_lock); + acquire(&disk.vdisk_lock); - // the spec's Section 5.2 says that legacy block operations use - // three descriptors: one for type/reserved/sector, one for the - // data, one for a 1-byte status result. + // the spec's Section 5.2 says that legacy block operations use + // three descriptors: one for type/reserved/sector, one for the + // data, one for a 1-byte status result. - // allocate the three descriptors. - int idx[3]; - while(1){ - if(alloc3_desc(idx) == 0) { - break; - } - sleep(&disk.free[0], &disk.vdisk_lock); - } + // allocate the three descriptors. + int idx[3]; + while (1) { + if (alloc3_desc(idx) == 0) { + break; + } + sleep(&disk.free[0], &disk.vdisk_lock); + } - // format the three descriptors. - // qemu's virtio-blk.c reads them. + // format the three descriptors. + // qemu's virtio-blk.c reads them. - struct virtio_blk_req *buf0 = &disk.ops[idx[0]]; + struct virtio_blk_req *buf0 = &disk.ops[idx[0]]; - if(write) - buf0->type = VIRTIO_BLK_T_OUT; // write the disk - else - buf0->type = VIRTIO_BLK_T_IN; // read the disk - buf0->reserved = 0; - buf0->sector = sector; + if (write) + buf0->type = VIRTIO_BLK_T_OUT; // write the disk + else + buf0->type = VIRTIO_BLK_T_IN; // read the disk + buf0->reserved = 0; + buf0->sector = sector; - disk.desc[idx[0]].addr = (uint64) buf0; - disk.desc[idx[0]].len = sizeof(struct virtio_blk_req); - disk.desc[idx[0]].flags = VRING_DESC_F_NEXT; - disk.desc[idx[0]].next = idx[1]; + disk.desc[idx[0]].addr = (uint64)buf0; + disk.desc[idx[0]].len = sizeof(struct virtio_blk_req); + disk.desc[idx[0]].flags = VRING_DESC_F_NEXT; + disk.desc[idx[0]].next = idx[1]; - disk.desc[idx[1]].addr = (uint64) b->data; - disk.desc[idx[1]].len = BSIZE; - if(write) - disk.desc[idx[1]].flags = 0; // device reads b->data - else - disk.desc[idx[1]].flags = VRING_DESC_F_WRITE; // device writes b->data - disk.desc[idx[1]].flags |= VRING_DESC_F_NEXT; - disk.desc[idx[1]].next = idx[2]; + disk.desc[idx[1]].addr = (uint64)b->data; + disk.desc[idx[1]].len = BSIZE; + if (write) + disk.desc[idx[1]].flags = 0; // device reads b->data + else + disk.desc[idx[1]].flags = VRING_DESC_F_WRITE; // device writes b->data + disk.desc[idx[1]].flags |= VRING_DESC_F_NEXT; + disk.desc[idx[1]].next = idx[2]; - disk.info[idx[0]].status = 0xff; // device writes 0 on success - disk.desc[idx[2]].addr = (uint64) &disk.info[idx[0]].status; - disk.desc[idx[2]].len = 1; - disk.desc[idx[2]].flags = VRING_DESC_F_WRITE; // device writes the status - disk.desc[idx[2]].next = 0; + disk.info[idx[0]].status = 0xff; // device writes 0 on success + disk.desc[idx[2]].addr = (uint64)&disk.info[idx[0]].status; + disk.desc[idx[2]].len = 1; + disk.desc[idx[2]].flags = VRING_DESC_F_WRITE; // device writes the status + disk.desc[idx[2]].next = 0; - // record struct buf for virtio_disk_intr(). - b->disk = 1; - disk.info[idx[0]].b = b; + // record struct buf for virtio_disk_intr(). + b->disk = 1; + disk.info[idx[0]].b = b; - // tell the device the first index in our chain of descriptors. - disk.avail->ring[disk.avail->idx % NUM] = idx[0]; + // tell the device the first index in our chain of descriptors. + disk.avail->ring[disk.avail->idx % NUM] = idx[0]; - __sync_synchronize(); + __sync_synchronize(); - // tell the device another avail ring entry is available. - disk.avail->idx += 1; // not % NUM ... + // tell the device another avail ring entry is available. + disk.avail->idx += 1; // not % NUM ... - __sync_synchronize(); + __sync_synchronize(); - *R(VIRTIO_MMIO_QUEUE_NOTIFY) = 0; // value is queue number + *R(VIRTIO_MMIO_QUEUE_NOTIFY) = 0; // value is queue number - // Wait for virtio_disk_intr() to say request has finished. - while(b->disk == 1) { - sleep(b, &disk.vdisk_lock); - } + // Wait for virtio_disk_intr() to say request has finished. + while (b->disk == 1) { + sleep(b, &disk.vdisk_lock); + } - disk.info[idx[0]].b = 0; - free_chain(idx[0]); + disk.info[idx[0]].b = 0; + free_chain(idx[0]); - release(&disk.vdisk_lock); + release(&disk.vdisk_lock); } -void -virtio_disk_intr() -{ - acquire(&disk.vdisk_lock); +void virtio_disk_intr() { + acquire(&disk.vdisk_lock); - // the device won't raise another interrupt until we tell it - // we've seen this interrupt, which the following line does. - // this may race with the device writing new entries to - // the "used" ring, in which case we may process the new - // completion entries in this interrupt, and have nothing to do - // in the next interrupt, which is harmless. - *R(VIRTIO_MMIO_INTERRUPT_ACK) = *R(VIRTIO_MMIO_INTERRUPT_STATUS) & 0x3; + // the device won't raise another interrupt until we tell it + // we've seen this interrupt, which the following line does. + // this may race with the device writing new entries to + // the "used" ring, in which case we may process the new + // completion entries in this interrupt, and have nothing to do + // in the next interrupt, which is harmless. + *R(VIRTIO_MMIO_INTERRUPT_ACK) = *R(VIRTIO_MMIO_INTERRUPT_STATUS) & 0x3; - __sync_synchronize(); + __sync_synchronize(); - // the device increments disk.used->idx when it - // adds an entry to the used ring. + // the device increments disk.used->idx when it + // adds an entry to the used ring. - while(disk.used_idx != disk.used->idx){ - __sync_synchronize(); - int id = disk.used->ring[disk.used_idx % NUM].id; + while (disk.used_idx != disk.used->idx) { + __sync_synchronize(); + int id = disk.used->ring[disk.used_idx % NUM].id; - if(disk.info[id].status != 0) - panic("virtio_disk_intr status"); + if (disk.info[id].status != 0) + panic("virtio_disk_intr status"); - struct buf *b = disk.info[id].b; - b->disk = 0; // disk is done with buf - wakeup(b); + struct buf *b = disk.info[id].b; + b->disk = 0; // disk is done with buf + wakeup(b); - disk.used_idx += 1; - } + disk.used_idx += 1; + } - release(&disk.vdisk_lock); + release(&disk.vdisk_lock); } diff --git a/kernel/vm.c b/kernel/vm.c index 9f69783..30d9c34 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -11,63 +11,56 @@ */ pagetable_t kernel_pagetable; -extern char etext[]; // kernel.ld sets this to end of kernel code. +extern char etext[]; // kernel.ld sets this to end of kernel code. extern char trampoline[]; // trampoline.S // Make a direct-map page table for the kernel. -pagetable_t -kvmmake(void) -{ - pagetable_t kpgtbl; +pagetable_t kvmmake(void) { + pagetable_t kpgtbl; - kpgtbl = (pagetable_t) kalloc(); - memset(kpgtbl, 0, PGSIZE); + kpgtbl = (pagetable_t)kalloc(); + memset(kpgtbl, 0, PGSIZE); - // uart registers - kvmmap(kpgtbl, UART0, UART0, PGSIZE, PTE_R | PTE_W); + // uart registers + kvmmap(kpgtbl, UART0, UART0, PGSIZE, PTE_R | PTE_W); - // virtio mmio disk interface - kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W); + // virtio mmio disk interface + kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W); - // PLIC - kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W); + // PLIC + kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W); - // map kernel text executable and read-only. - kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X); + // map kernel text executable and read-only. + kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext - KERNBASE, PTE_R | PTE_X); - // map kernel data and the physical RAM we'll make use of. - kvmmap(kpgtbl, (uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W); + // map kernel data and the physical RAM we'll make use of. + kvmmap(kpgtbl, (uint64)etext, (uint64)etext, PHYSTOP - (uint64)etext, + PTE_R | PTE_W); - // map the trampoline for trap entry/exit to - // the highest virtual address in the kernel. - kvmmap(kpgtbl, TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); + // map the trampoline for trap entry/exit to + // the highest virtual address in the kernel. + kvmmap(kpgtbl, TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); - // allocate and map a kernel stack for each process. - proc_mapstacks(kpgtbl); - - return kpgtbl; + // allocate and map a kernel stack for each process. + proc_mapstacks(kpgtbl); + + return kpgtbl; } // Initialize the one kernel_pagetable -void -kvminit(void) -{ - kernel_pagetable = kvmmake(); -} +void kvminit(void) { kernel_pagetable = kvmmake(); } // Switch h/w page table register to the kernel's page table, // and enable paging. -void -kvminithart() -{ - // wait for any previous writes to the page table memory to finish. - sfence_vma(); +void kvminithart() { + // wait for any previous writes to the page table memory to finish. + sfence_vma(); - w_satp(MAKE_SATP(kernel_pagetable)); + w_satp(MAKE_SATP(kernel_pagetable)); - // flush stale entries from the TLB. - sfence_vma(); + // flush stale entries from the TLB. + sfence_vma(); } // Return the address of the PTE in page table pagetable @@ -82,218 +75,198 @@ kvminithart() // 21..29 -- 9 bits of level-1 index. // 12..20 -- 9 bits of level-0 index. // 0..11 -- 12 bits of byte offset within the page. -pte_t * -walk(pagetable_t pagetable, uint64 va, int alloc) -{ - if(va >= MAXVA) - panic("walk"); +pte_t *walk(pagetable_t pagetable, uint64 va, int alloc) { + if (va >= MAXVA) + panic("walk"); - for(int level = 2; level > 0; level--) { - pte_t *pte = &pagetable[PX(level, va)]; - if(*pte & PTE_V) { - pagetable = (pagetable_t)PTE2PA(*pte); - } else { - if(!alloc || (pagetable = (pde_t*)kalloc()) == 0) - return 0; - memset(pagetable, 0, PGSIZE); - *pte = PA2PTE(pagetable) | PTE_V; - } - } - return &pagetable[PX(0, va)]; + for (int level = 2; level > 0; level--) { + pte_t *pte = &pagetable[PX(level, va)]; + if (*pte & PTE_V) { + pagetable = (pagetable_t)PTE2PA(*pte); + } else { + if (!alloc || (pagetable = (pde_t *)kalloc()) == 0) + return 0; + memset(pagetable, 0, PGSIZE); + *pte = PA2PTE(pagetable) | PTE_V; + } + } + return &pagetable[PX(0, va)]; } // Look up a virtual address, return the physical address, // or 0 if not mapped. // Can only be used to look up user pages. -uint64 -walkaddr(pagetable_t pagetable, uint64 va) -{ - pte_t *pte; - uint64 pa; +uint64 walkaddr(pagetable_t pagetable, uint64 va) { + pte_t *pte; + uint64 pa; - if(va >= MAXVA) - return 0; + if (va >= MAXVA) + return 0; - pte = walk(pagetable, va, 0); - if(pte == 0) - return 0; - if((*pte & PTE_V) == 0) - return 0; - if((*pte & PTE_U) == 0) - return 0; - pa = PTE2PA(*pte); - return pa; + pte = walk(pagetable, va, 0); + if (pte == 0) + return 0; + if ((*pte & PTE_V) == 0) + return 0; + if ((*pte & PTE_U) == 0) + return 0; + pa = PTE2PA(*pte); + return pa; } // add a mapping to the kernel page table. // only used when booting. // does not flush TLB or enable paging. -void -kvmmap(pagetable_t kpgtbl, uint64 va, uint64 pa, uint64 sz, int perm) -{ - if(mappages(kpgtbl, va, sz, pa, perm) != 0) - panic("kvmmap"); +void kvmmap(pagetable_t kpgtbl, uint64 va, uint64 pa, uint64 sz, int perm) { + if (mappages(kpgtbl, va, sz, pa, perm) != 0) + panic("kvmmap"); } // Create PTEs for virtual addresses starting at va that refer to // physical addresses starting at pa. va and size might not // be page-aligned. Returns 0 on success, -1 if walk() couldn't // allocate a needed page-table page. -int -mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm) -{ - uint64 a, last; - pte_t *pte; +int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, + int perm) { + uint64 a, last; + pte_t *pte; - if(size == 0) - panic("mappages: size"); - - a = PGROUNDDOWN(va); - last = PGROUNDDOWN(va + size - 1); - for(;;){ - if((pte = walk(pagetable, a, 1)) == 0) - return -1; - if(*pte & PTE_V) - panic("mappages: remap"); - *pte = PA2PTE(pa) | perm | PTE_V; - if(a == last) - break; - a += PGSIZE; - pa += PGSIZE; - } - return 0; + if (size == 0) + panic("mappages: size"); + + a = PGROUNDDOWN(va); + last = PGROUNDDOWN(va + size - 1); + for (;;) { + if ((pte = walk(pagetable, a, 1)) == 0) + return -1; + if (*pte & PTE_V) + panic("mappages: remap"); + *pte = PA2PTE(pa) | perm | PTE_V; + if (a == last) + break; + a += PGSIZE; + pa += PGSIZE; + } + return 0; } // Remove npages of mappings starting from va. va must be // page-aligned. The mappings must exist. // Optionally free the physical memory. -void -uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free) -{ - uint64 a; - pte_t *pte; +void uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free) { + uint64 a; + pte_t *pte; - if((va % PGSIZE) != 0) - panic("uvmunmap: not aligned"); + if ((va % PGSIZE) != 0) + panic("uvmunmap: not aligned"); - for(a = va; a < va + npages*PGSIZE; a += PGSIZE){ - if((pte = walk(pagetable, a, 0)) == 0) - panic("uvmunmap: walk"); - if((*pte & PTE_V) == 0) - panic("uvmunmap: not mapped"); - if(PTE_FLAGS(*pte) == PTE_V) - panic("uvmunmap: not a leaf"); - if(do_free){ - uint64 pa = PTE2PA(*pte); - kfree((void*)pa); - } - *pte = 0; - } + for (a = va; a < va + npages * PGSIZE; a += PGSIZE) { + if ((pte = walk(pagetable, a, 0)) == 0) + panic("uvmunmap: walk"); + if ((*pte & PTE_V) == 0) + panic("uvmunmap: not mapped"); + if (PTE_FLAGS(*pte) == PTE_V) + panic("uvmunmap: not a leaf"); + if (do_free) { + uint64 pa = PTE2PA(*pte); + kfree((void *)pa); + } + *pte = 0; + } } // create an empty user page table. // returns 0 if out of memory. -pagetable_t -uvmcreate() -{ - pagetable_t pagetable; - pagetable = (pagetable_t) kalloc(); - if(pagetable == 0) - return 0; - memset(pagetable, 0, PGSIZE); - return pagetable; +pagetable_t uvmcreate() { + pagetable_t pagetable; + pagetable = (pagetable_t)kalloc(); + if (pagetable == 0) + return 0; + memset(pagetable, 0, PGSIZE); + return pagetable; } // Load the user initcode into address 0 of pagetable, // for the very first process. // sz must be less than a page. -void -uvmfirst(pagetable_t pagetable, uchar *src, uint sz) -{ - char *mem; +void uvmfirst(pagetable_t pagetable, uchar *src, uint sz) { + char *mem; - if(sz >= PGSIZE) - panic("uvmfirst: more than a page"); - mem = kalloc(); - memset(mem, 0, PGSIZE); - mappages(pagetable, 0, PGSIZE, (uint64)mem, PTE_W|PTE_R|PTE_X|PTE_U); - memmove(mem, src, sz); + if (sz >= PGSIZE) + panic("uvmfirst: more than a page"); + mem = kalloc(); + memset(mem, 0, PGSIZE); + mappages(pagetable, 0, PGSIZE, (uint64)mem, PTE_W | PTE_R | PTE_X | PTE_U); + memmove(mem, src, sz); } // Allocate PTEs and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. -uint64 -uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm) -{ - char *mem; - uint64 a; +uint64 uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm) { + char *mem; + uint64 a; - if(newsz < oldsz) - return oldsz; + if (newsz < oldsz) + return oldsz; - oldsz = PGROUNDUP(oldsz); - for(a = oldsz; a < newsz; a += PGSIZE){ - mem = kalloc(); - if(mem == 0){ - uvmdealloc(pagetable, a, oldsz); - return 0; - } - memset(mem, 0, PGSIZE); - if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_R|PTE_U|xperm) != 0){ - kfree(mem); - uvmdealloc(pagetable, a, oldsz); - return 0; - } - } - return newsz; + oldsz = PGROUNDUP(oldsz); + for (a = oldsz; a < newsz; a += PGSIZE) { + mem = kalloc(); + if (mem == 0) { + uvmdealloc(pagetable, a, oldsz); + return 0; + } + memset(mem, 0, PGSIZE); + if (mappages(pagetable, a, PGSIZE, (uint64)mem, + PTE_R | PTE_U | xperm) != 0) { + kfree(mem); + uvmdealloc(pagetable, a, oldsz); + return 0; + } + } + return newsz; } // Deallocate user pages to bring the process size from oldsz to // newsz. oldsz and newsz need not be page-aligned, nor does newsz // need to be less than oldsz. oldsz can be larger than the actual // process size. Returns the new process size. -uint64 -uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) -{ - if(newsz >= oldsz) - return oldsz; +uint64 uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) { + if (newsz >= oldsz) + return oldsz; - if(PGROUNDUP(newsz) < PGROUNDUP(oldsz)){ - int npages = (PGROUNDUP(oldsz) - PGROUNDUP(newsz)) / PGSIZE; - uvmunmap(pagetable, PGROUNDUP(newsz), npages, 1); - } + if (PGROUNDUP(newsz) < PGROUNDUP(oldsz)) { + int npages = (PGROUNDUP(oldsz) - PGROUNDUP(newsz)) / PGSIZE; + uvmunmap(pagetable, PGROUNDUP(newsz), npages, 1); + } - return newsz; + return newsz; } // Recursively free page-table pages. // All leaf mappings must already have been removed. -void -freewalk(pagetable_t pagetable) -{ - // there are 2^9 = 512 PTEs in a page table. - for(int i = 0; i < 512; i++){ - pte_t pte = pagetable[i]; - if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){ - // this PTE points to a lower-level page table. - uint64 child = PTE2PA(pte); - freewalk((pagetable_t)child); - pagetable[i] = 0; - } else if(pte & PTE_V){ - panic("freewalk: leaf"); - } - } - kfree((void*)pagetable); +void freewalk(pagetable_t pagetable) { + // there are 2^9 = 512 PTEs in a page table. + for (int i = 0; i < 512; i++) { + pte_t pte = pagetable[i]; + if ((pte & PTE_V) && (pte & (PTE_R | PTE_W | PTE_X)) == 0) { + // this PTE points to a lower-level page table. + uint64 child = PTE2PA(pte); + freewalk((pagetable_t)child); + pagetable[i] = 0; + } else if (pte & PTE_V) { + panic("freewalk: leaf"); + } + } + kfree((void *)pagetable); } // Free user memory pages, // then free page-table pages. -void -uvmfree(pagetable_t pagetable, uint64 sz) -{ - if(sz > 0) - uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1); - freewalk(pagetable); +void uvmfree(pagetable_t pagetable, uint64 sz) { + if (sz > 0) + uvmunmap(pagetable, 0, PGROUNDUP(sz) / PGSIZE, 1); + freewalk(pagetable); } // Given a parent process's page table, copy @@ -302,138 +275,128 @@ uvmfree(pagetable_t pagetable, uint64 sz) // physical memory. // returns 0 on success, -1 on failure. // frees any allocated pages on failure. -int -uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) -{ - pte_t *pte; - uint64 pa, i; - uint flags; - char *mem; +int uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) { + pte_t *pte; + uint64 pa, i; + uint flags; + char *mem; - for(i = 0; i < sz; i += PGSIZE){ - if((pte = walk(old, i, 0)) == 0) - panic("uvmcopy: pte should exist"); - if((*pte & PTE_V) == 0) - panic("uvmcopy: page not present"); - pa = PTE2PA(*pte); - flags = PTE_FLAGS(*pte); - if((mem = kalloc()) == 0) - goto err; - memmove(mem, (char*)pa, PGSIZE); - if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){ - kfree(mem); - goto err; - } - } - return 0; + for (i = 0; i < sz; i += PGSIZE) { + if ((pte = walk(old, i, 0)) == 0) + panic("uvmcopy: pte should exist"); + if ((*pte & PTE_V) == 0) + panic("uvmcopy: page not present"); + pa = PTE2PA(*pte); + flags = PTE_FLAGS(*pte); + if ((mem = kalloc()) == 0) + goto err; + memmove(mem, (char *)pa, PGSIZE); + if (mappages(new, i, PGSIZE, (uint64)mem, flags) != 0) { + kfree(mem); + goto err; + } + } + return 0; - err: - uvmunmap(new, 0, i / PGSIZE, 1); - return -1; +err: + uvmunmap(new, 0, i / PGSIZE, 1); + return -1; } // mark a PTE invalid for user access. // used by exec for the user stack guard page. -void -uvmclear(pagetable_t pagetable, uint64 va) -{ - pte_t *pte; - - pte = walk(pagetable, va, 0); - if(pte == 0) - panic("uvmclear"); - *pte &= ~PTE_U; +void uvmclear(pagetable_t pagetable, uint64 va) { + pte_t *pte; + + pte = walk(pagetable, va, 0); + if (pte == 0) + panic("uvmclear"); + *pte &= ~PTE_U; } // Copy from kernel to user. // Copy len bytes from src to virtual address dstva in a given page table. // Return 0 on success, -1 on error. -int -copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len) -{ - uint64 n, va0, pa0; +int copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len) { + uint64 n, va0, pa0; - while(len > 0){ - va0 = PGROUNDDOWN(dstva); - pa0 = walkaddr(pagetable, va0); - if(pa0 == 0) - return -1; - n = PGSIZE - (dstva - va0); - if(n > len) - n = len; - memmove((void *)(pa0 + (dstva - va0)), src, n); + while (len > 0) { + va0 = PGROUNDDOWN(dstva); + pa0 = walkaddr(pagetable, va0); + if (pa0 == 0) + return -1; + n = PGSIZE - (dstva - va0); + if (n > len) + n = len; + memmove((void *)(pa0 + (dstva - va0)), src, n); - len -= n; - src += n; - dstva = va0 + PGSIZE; - } - return 0; + len -= n; + src += n; + dstva = va0 + PGSIZE; + } + return 0; } // Copy from user to kernel. // Copy len bytes to dst from virtual address srcva in a given page table. // Return 0 on success, -1 on error. -int -copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len) -{ - uint64 n, va0, pa0; +int copyin(pagetable_t pagetable, char *dst, uint64 srcva, uint64 len) { + uint64 n, va0, pa0; - while(len > 0){ - va0 = PGROUNDDOWN(srcva); - pa0 = walkaddr(pagetable, va0); - if(pa0 == 0) - return -1; - n = PGSIZE - (srcva - va0); - if(n > len) - n = len; - memmove(dst, (void *)(pa0 + (srcva - va0)), n); + while (len > 0) { + va0 = PGROUNDDOWN(srcva); + pa0 = walkaddr(pagetable, va0); + if (pa0 == 0) + return -1; + n = PGSIZE - (srcva - va0); + if (n > len) + n = len; + memmove(dst, (void *)(pa0 + (srcva - va0)), n); - len -= n; - dst += n; - srcva = va0 + PGSIZE; - } - return 0; + len -= n; + dst += n; + srcva = va0 + PGSIZE; + } + return 0; } // Copy a null-terminated string from user to kernel. // Copy bytes to dst from virtual address srcva in a given page table, // until a '\0', or max. // Return 0 on success, -1 on error. -int -copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max) -{ - uint64 n, va0, pa0; - int got_null = 0; +int copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max) { + uint64 n, va0, pa0; + int got_null = 0; - while(got_null == 0 && max > 0){ - va0 = PGROUNDDOWN(srcva); - pa0 = walkaddr(pagetable, va0); - if(pa0 == 0) - return -1; - n = PGSIZE - (srcva - va0); - if(n > max) - n = max; + while (got_null == 0 && max > 0) { + va0 = PGROUNDDOWN(srcva); + pa0 = walkaddr(pagetable, va0); + if (pa0 == 0) + return -1; + n = PGSIZE - (srcva - va0); + if (n > max) + n = max; - char *p = (char *) (pa0 + (srcva - va0)); - while(n > 0){ - if(*p == '\0'){ - *dst = '\0'; - got_null = 1; - break; - } else { - *dst = *p; - } - --n; - --max; - p++; - dst++; - } + char *p = (char *)(pa0 + (srcva - va0)); + while (n > 0) { + if (*p == '\0') { + *dst = '\0'; + got_null = 1; + break; + } else { + *dst = *p; + } + --n; + --max; + p++; + dst++; + } - srcva = va0 + PGSIZE; - } - if(got_null){ - return 0; - } else { - return -1; - } + srcva = va0 + PGSIZE; + } + if (got_null) { + return 0; + } else { + return -1; + } } diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c index 1ec326b..8bce917 100644 --- a/mkfs/mkfs.c +++ b/mkfs/mkfs.c @@ -5,14 +5,19 @@ #include #include -#define stat xv6_stat // avoid clash with host struct stat +#define stat xv6_stat // avoid clash with host struct stat #include "kernel/types.h" #include "kernel/fs.h" #include "kernel/stat.h" #include "kernel/param.h" #ifndef static_assert -#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0) +#define static_assert(a, b) \ + do { \ + switch (0) \ + case 0: \ + case (a):; \ + } while (0) #endif #define NINODES 200 @@ -20,11 +25,11 @@ // Disk layout: // [ boot block | sb block | log | inode blocks | free bit map | data blocks ] -int nbitmap = FSSIZE/(BSIZE*8) + 1; +int nbitmap = FSSIZE / (BSIZE * 8) + 1; int ninodeblocks = NINODES / IPB + 1; int nlog = LOGSIZE; -int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap) -int nblocks; // Number of data blocks +int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap) +int nblocks; // Number of data blocks int fsfd; struct superblock sb; @@ -32,10 +37,9 @@ char zeroes[BSIZE]; uint freeinode = 1; uint freeblock; - void balloc(int); -void wsect(uint, void*); -void winode(uint, struct dinode*); +void wsect(uint, void *); +void winode(uint, struct dinode *); void rinode(uint inum, struct dinode *ip); void rsect(uint sec, void *buf); uint ialloc(ushort type); @@ -43,259 +47,237 @@ void iappend(uint inum, void *p, int n); void die(const char *); // convert to riscv byte order -ushort -xshort(ushort x) -{ - ushort y; - uchar *a = (uchar*)&y; - a[0] = x; - a[1] = x >> 8; - return y; +ushort xshort(ushort x) { + ushort y; + uchar *a = (uchar *)&y; + a[0] = x; + a[1] = x >> 8; + return y; } -uint -xint(uint x) -{ - uint y; - uchar *a = (uchar*)&y; - a[0] = x; - a[1] = x >> 8; - a[2] = x >> 16; - a[3] = x >> 24; - return y; +uint xint(uint x) { + uint y; + uchar *a = (uchar *)&y; + a[0] = x; + a[1] = x >> 8; + a[2] = x >> 16; + a[3] = x >> 24; + return y; } -int -main(int argc, char *argv[]) -{ - int i, cc, fd; - uint rootino, inum, off; - struct dirent de; - char buf[BSIZE]; - struct dinode din; +int main(int argc, char *argv[]) { + int i, cc, fd; + uint rootino, inum, off; + struct dirent de; + char buf[BSIZE]; + struct dinode din; + static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); - static_assert(sizeof(int) == 4, "Integers must be 4 bytes!"); + if (argc < 2) { + fprintf(stderr, "Usage: mkfs fs.img files...\n"); + exit(1); + } - if(argc < 2){ - fprintf(stderr, "Usage: mkfs fs.img files...\n"); - exit(1); - } + assert((BSIZE % sizeof(struct dinode)) == 0); + assert((BSIZE % sizeof(struct dirent)) == 0); - assert((BSIZE % sizeof(struct dinode)) == 0); - assert((BSIZE % sizeof(struct dirent)) == 0); + fsfd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0666); + if (fsfd < 0) + die(argv[1]); - fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666); - if(fsfd < 0) - die(argv[1]); + // 1 fs block = 1 disk sector + nmeta = 2 + nlog + ninodeblocks + nbitmap; + nblocks = FSSIZE - nmeta; - // 1 fs block = 1 disk sector - nmeta = 2 + nlog + ninodeblocks + nbitmap; - nblocks = FSSIZE - nmeta; + sb.magic = FSMAGIC; + sb.size = xint(FSSIZE); + sb.nblocks = xint(nblocks); + sb.ninodes = xint(NINODES); + sb.nlog = xint(nlog); + sb.logstart = xint(2); + sb.inodestart = xint(2 + nlog); + sb.bmapstart = xint(2 + nlog + ninodeblocks); - sb.magic = FSMAGIC; - sb.size = xint(FSSIZE); - sb.nblocks = xint(nblocks); - sb.ninodes = xint(NINODES); - sb.nlog = xint(nlog); - sb.logstart = xint(2); - sb.inodestart = xint(2+nlog); - sb.bmapstart = xint(2+nlog+ninodeblocks); + printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap " + "blocks %u) blocks %d total %d\n", + nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE); - printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n", - nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE); + freeblock = nmeta; // the first free block that we can allocate - freeblock = nmeta; // the first free block that we can allocate + for (i = 0; i < FSSIZE; i++) + wsect(i, zeroes); - for(i = 0; i < FSSIZE; i++) - wsect(i, zeroes); + memset(buf, 0, sizeof(buf)); + memmove(buf, &sb, sizeof(sb)); + wsect(1, buf); - memset(buf, 0, sizeof(buf)); - memmove(buf, &sb, sizeof(sb)); - wsect(1, buf); + rootino = ialloc(T_DIR); + assert(rootino == ROOTINO); - rootino = ialloc(T_DIR); - assert(rootino == ROOTINO); + bzero(&de, sizeof(de)); + de.inum = xshort(rootino); + strcpy(de.name, "."); + iappend(rootino, &de, sizeof(de)); - bzero(&de, sizeof(de)); - de.inum = xshort(rootino); - strcpy(de.name, "."); - iappend(rootino, &de, sizeof(de)); + bzero(&de, sizeof(de)); + de.inum = xshort(rootino); + strcpy(de.name, ".."); + iappend(rootino, &de, sizeof(de)); - bzero(&de, sizeof(de)); - de.inum = xshort(rootino); - strcpy(de.name, ".."); - iappend(rootino, &de, sizeof(de)); + for (i = 2; i < argc; i++) { + // get rid of "user/" + char *shortname; + if (strncmp(argv[i], "user/", 5) == 0) + shortname = argv[i] + 5; + else + shortname = argv[i]; - for(i = 2; i < argc; i++){ - // get rid of "user/" - char *shortname; - if(strncmp(argv[i], "user/", 5) == 0) - shortname = argv[i] + 5; - else - shortname = argv[i]; - - assert(index(shortname, '/') == 0); + assert(index(shortname, '/') == 0); - if((fd = open(argv[i], 0)) < 0) - die(argv[i]); + if ((fd = open(argv[i], 0)) < 0) + die(argv[i]); - // Skip leading _ in name when writing to file system. - // The binaries are named _rm, _cat, etc. to keep the - // build operating system from trying to execute them - // in place of system binaries like rm and cat. - if(shortname[0] == '_') - shortname += 1; + // Skip leading _ in name when writing to file system. + // The binaries are named _rm, _cat, etc. to keep the + // build operating system from trying to execute them + // in place of system binaries like rm and cat. + if (shortname[0] == '_') + shortname += 1; - inum = ialloc(T_FILE); + inum = ialloc(T_FILE); - bzero(&de, sizeof(de)); - de.inum = xshort(inum); - strncpy(de.name, shortname, DIRSIZ); - iappend(rootino, &de, sizeof(de)); + bzero(&de, sizeof(de)); + de.inum = xshort(inum); + strncpy(de.name, shortname, DIRSIZ); + iappend(rootino, &de, sizeof(de)); - while((cc = read(fd, buf, sizeof(buf))) > 0) - iappend(inum, buf, cc); + while ((cc = read(fd, buf, sizeof(buf))) > 0) + iappend(inum, buf, cc); - close(fd); - } + close(fd); + } - // fix size of root inode dir - rinode(rootino, &din); - off = xint(din.size); - off = ((off/BSIZE) + 1) * BSIZE; - din.size = xint(off); - winode(rootino, &din); + // fix size of root inode dir + rinode(rootino, &din); + off = xint(din.size); + off = ((off / BSIZE) + 1) * BSIZE; + din.size = xint(off); + winode(rootino, &din); - balloc(freeblock); + balloc(freeblock); - exit(0); + exit(0); } -void -wsect(uint sec, void *buf) -{ - if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE) - die("lseek"); - if(write(fsfd, buf, BSIZE) != BSIZE) - die("write"); +void wsect(uint sec, void *buf) { + if (lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE) + die("lseek"); + if (write(fsfd, buf, BSIZE) != BSIZE) + die("write"); } -void -winode(uint inum, struct dinode *ip) -{ - char buf[BSIZE]; - uint bn; - struct dinode *dip; +void winode(uint inum, struct dinode *ip) { + char buf[BSIZE]; + uint bn; + struct dinode *dip; - bn = IBLOCK(inum, sb); - rsect(bn, buf); - dip = ((struct dinode*)buf) + (inum % IPB); - *dip = *ip; - wsect(bn, buf); + bn = IBLOCK(inum, sb); + rsect(bn, buf); + dip = ((struct dinode *)buf) + (inum % IPB); + *dip = *ip; + wsect(bn, buf); } -void -rinode(uint inum, struct dinode *ip) -{ - char buf[BSIZE]; - uint bn; - struct dinode *dip; +void rinode(uint inum, struct dinode *ip) { + char buf[BSIZE]; + uint bn; + struct dinode *dip; - bn = IBLOCK(inum, sb); - rsect(bn, buf); - dip = ((struct dinode*)buf) + (inum % IPB); - *ip = *dip; + bn = IBLOCK(inum, sb); + rsect(bn, buf); + dip = ((struct dinode *)buf) + (inum % IPB); + *ip = *dip; } -void -rsect(uint sec, void *buf) -{ - if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE) - die("lseek"); - if(read(fsfd, buf, BSIZE) != BSIZE) - die("read"); +void rsect(uint sec, void *buf) { + if (lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE) + die("lseek"); + if (read(fsfd, buf, BSIZE) != BSIZE) + die("read"); } -uint -ialloc(ushort type) -{ - uint inum = freeinode++; - struct dinode din; +uint ialloc(ushort type) { + uint inum = freeinode++; + struct dinode din; - bzero(&din, sizeof(din)); - din.type = xshort(type); - din.nlink = xshort(1); - din.size = xint(0); - winode(inum, &din); - return inum; + bzero(&din, sizeof(din)); + din.type = xshort(type); + din.nlink = xshort(1); + din.size = xint(0); + winode(inum, &din); + return inum; } -void -balloc(int used) -{ - uchar buf[BSIZE]; - int i; +void balloc(int used) { + uchar buf[BSIZE]; + int i; - printf("balloc: first %d blocks have been allocated\n", used); - assert(used < BSIZE*8); - bzero(buf, BSIZE); - for(i = 0; i < used; i++){ - buf[i/8] = buf[i/8] | (0x1 << (i%8)); - } - printf("balloc: write bitmap block at sector %d\n", sb.bmapstart); - wsect(sb.bmapstart, buf); + printf("balloc: first %d blocks have been allocated\n", used); + assert(used < BSIZE * 8); + bzero(buf, BSIZE); + for (i = 0; i < used; i++) { + buf[i / 8] = buf[i / 8] | (0x1 << (i % 8)); + } + printf("balloc: write bitmap block at sector %d\n", sb.bmapstart); + wsect(sb.bmapstart, buf); } #define min(a, b) ((a) < (b) ? (a) : (b)) -void -iappend(uint inum, void *xp, int n) -{ - char *p = (char*)xp; - uint fbn, off, n1; - struct dinode din; - char buf[BSIZE]; - uint indirect[NINDIRECT]; - uint x; +void iappend(uint inum, void *xp, int n) { + char *p = (char *)xp; + uint fbn, off, n1; + struct dinode din; + char buf[BSIZE]; + uint indirect[NINDIRECT]; + uint x; - rinode(inum, &din); - off = xint(din.size); - // printf("append inum %d at off %d sz %d\n", inum, off, n); - while(n > 0){ - fbn = off / BSIZE; - assert(fbn < MAXFILE); - if(fbn < NDIRECT){ - if(xint(din.addrs[fbn]) == 0){ - din.addrs[fbn] = xint(freeblock++); - } - x = xint(din.addrs[fbn]); - } else { - if(xint(din.addrs[NDIRECT]) == 0){ - din.addrs[NDIRECT] = xint(freeblock++); - } - rsect(xint(din.addrs[NDIRECT]), (char*)indirect); - if(indirect[fbn - NDIRECT] == 0){ - indirect[fbn - NDIRECT] = xint(freeblock++); - wsect(xint(din.addrs[NDIRECT]), (char*)indirect); - } - x = xint(indirect[fbn-NDIRECT]); - } - n1 = min(n, (fbn + 1) * BSIZE - off); - rsect(x, buf); - bcopy(p, buf + off - (fbn * BSIZE), n1); - wsect(x, buf); - n -= n1; - off += n1; - p += n1; - } - din.size = xint(off); - winode(inum, &din); + rinode(inum, &din); + off = xint(din.size); + // printf("append inum %d at off %d sz %d\n", inum, off, n); + while (n > 0) { + fbn = off / BSIZE; + assert(fbn < MAXFILE); + if (fbn < NDIRECT) { + if (xint(din.addrs[fbn]) == 0) { + din.addrs[fbn] = xint(freeblock++); + } + x = xint(din.addrs[fbn]); + } else { + if (xint(din.addrs[NDIRECT]) == 0) { + din.addrs[NDIRECT] = xint(freeblock++); + } + rsect(xint(din.addrs[NDIRECT]), (char *)indirect); + if (indirect[fbn - NDIRECT] == 0) { + indirect[fbn - NDIRECT] = xint(freeblock++); + wsect(xint(din.addrs[NDIRECT]), (char *)indirect); + } + x = xint(indirect[fbn - NDIRECT]); + } + n1 = min(n, (fbn + 1) * BSIZE - off); + rsect(x, buf); + bcopy(p, buf + off - (fbn * BSIZE), n1); + wsect(x, buf); + n -= n1; + off += n1; + p += n1; + } + din.size = xint(off); + winode(inum, &din); } -void -die(const char *s) -{ - perror(s); - exit(1); +void die(const char *s) { + perror(s); + exit(1); } diff --git a/user/cat.c b/user/cat.c index 598f005..5ebea75 100644 --- a/user/cat.c +++ b/user/cat.c @@ -4,40 +4,36 @@ char buf[512]; -void -cat(int fd) -{ - int n; +void cat(int fd) { + int n; - while((n = read(fd, buf, sizeof(buf))) > 0) { - if (write(1, buf, n) != n) { - fprintf(2, "cat: write error\n"); - exit(1); - } - } - if(n < 0){ - fprintf(2, "cat: read error\n"); - exit(1); - } + while ((n = read(fd, buf, sizeof(buf))) > 0) { + if (write(1, buf, n) != n) { + fprintf(2, "cat: write error\n"); + exit(1); + } + } + if (n < 0) { + fprintf(2, "cat: read error\n"); + exit(1); + } } -int -main(int argc, char *argv[]) -{ - int fd, i; +int main(int argc, char *argv[]) { + int fd, i; - if(argc <= 1){ - cat(0); - exit(0); - } + if (argc <= 1) { + cat(0); + exit(0); + } - for(i = 1; i < argc; i++){ - if((fd = open(argv[i], 0)) < 0){ - fprintf(2, "cat: cannot open %s\n", argv[i]); - exit(1); - } - cat(fd); - close(fd); - } - exit(0); + for (i = 1; i < argc; i++) { + if ((fd = open(argv[i], 0)) < 0) { + fprintf(2, "cat: cannot open %s\n", argv[i]); + exit(1); + } + cat(fd); + close(fd); + } + exit(0); } diff --git a/user/echo.c b/user/echo.c index 3f19cd7..07c5029 100644 --- a/user/echo.c +++ b/user/echo.c @@ -2,18 +2,16 @@ #include "kernel/stat.h" #include "user/user.h" -int -main(int argc, char *argv[]) -{ - int i; +int main(int argc, char *argv[]) { + int i; - for(i = 1; i < argc; i++){ - write(1, argv[i], strlen(argv[i])); - if(i + 1 < argc){ - write(1, " ", 1); - } else { - write(1, "\n", 1); - } - } - exit(0); + for (i = 1; i < argc; i++) { + write(1, argv[i], strlen(argv[i])); + if (i + 1 < argc) { + write(1, " ", 1); + } else { + write(1, "\n", 1); + } + } + exit(0); } diff --git a/user/forktest.c b/user/forktest.c index 384e75f..d429c26 100644 --- a/user/forktest.c +++ b/user/forktest.c @@ -5,52 +5,44 @@ #include "kernel/stat.h" #include "user/user.h" -#define N 1000 +#define N 1000 -void -print(const char *s) -{ - write(1, s, strlen(s)); +void print(const char *s) { write(1, s, strlen(s)); } + +void forktest(void) { + int n, pid; + + print("fork test\n"); + + for (n = 0; n < N; n++) { + pid = fork(); + if (pid < 0) + break; + if (pid == 0) + exit(0); + } + + if (n == N) { + print("fork claimed to work N times!\n"); + exit(1); + } + + for (; n > 0; n--) { + if (wait(0) < 0) { + print("wait stopped early\n"); + exit(1); + } + } + + if (wait(0) != -1) { + print("wait got too many\n"); + exit(1); + } + + print("fork test OK\n"); } -void -forktest(void) -{ - int n, pid; - - print("fork test\n"); - - for(n=0; n 0; n--){ - if(wait(0) < 0){ - print("wait stopped early\n"); - exit(1); - } - } - - if(wait(0) != -1){ - print("wait got too many\n"); - exit(1); - } - - print("fork test OK\n"); -} - -int -main(void) -{ - forktest(); - exit(0); +int main(void) { + forktest(); + exit(0); } diff --git a/user/grep.c b/user/grep.c index 2315a0c..44d09ee 100644 --- a/user/grep.c +++ b/user/grep.c @@ -5,102 +5,93 @@ #include "user/user.h" char buf[1024]; -int match(char*, char*); +int match(char *, char *); -void -grep(char *pattern, int fd) -{ - int n, m; - char *p, *q; +void grep(char *pattern, int fd) { + int n, m; + char *p, *q; - m = 0; - while((n = read(fd, buf+m, sizeof(buf)-m-1)) > 0){ - m += n; - buf[m] = '\0'; - p = buf; - while((q = strchr(p, '\n')) != 0){ - *q = 0; - if(match(pattern, p)){ - *q = '\n'; - write(1, p, q+1 - p); - } - p = q+1; - } - if(m > 0){ - m -= p - buf; - memmove(buf, p, m); - } - } + m = 0; + while ((n = read(fd, buf + m, sizeof(buf) - m - 1)) > 0) { + m += n; + buf[m] = '\0'; + p = buf; + while ((q = strchr(p, '\n')) != 0) { + *q = 0; + if (match(pattern, p)) { + *q = '\n'; + write(1, p, q + 1 - p); + } + p = q + 1; + } + if (m > 0) { + m -= p - buf; + memmove(buf, p, m); + } + } } -int -main(int argc, char *argv[]) -{ - int fd, i; - char *pattern; +int main(int argc, char *argv[]) { + int fd, i; + char *pattern; - if(argc <= 1){ - fprintf(2, "usage: grep pattern [file ...]\n"); - exit(1); - } - pattern = argv[1]; + if (argc <= 1) { + fprintf(2, "usage: grep pattern [file ...]\n"); + exit(1); + } + pattern = argv[1]; - if(argc <= 2){ - grep(pattern, 0); - exit(0); - } + if (argc <= 2) { + grep(pattern, 0); + exit(0); + } - for(i = 2; i < argc; i++){ - if((fd = open(argv[i], 0)) < 0){ - printf("grep: cannot open %s\n", argv[i]); - exit(1); - } - grep(pattern, fd); - close(fd); - } - exit(0); + for (i = 2; i < argc; i++) { + if ((fd = open(argv[i], 0)) < 0) { + printf("grep: cannot open %s\n", argv[i]); + exit(1); + } + grep(pattern, fd); + close(fd); + } + exit(0); } // Regexp matcher from Kernighan & Pike, // 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*); +int matchhere(char *, char *); +int matchstar(int, char *, char *); -int -match(char *re, char *text) -{ - if(re[0] == '^') - return matchhere(re+1, text); - do{ // must look at empty string - if(matchhere(re, text)) - return 1; - }while(*text++ != '\0'); - return 0; +int match(char *re, char *text) { + if (re[0] == '^') + return matchhere(re + 1, text); + do { // must look at empty string + if (matchhere(re, text)) + return 1; + } while (*text++ != '\0'); + return 0; } // matchhere: search for re at beginning of text -int matchhere(char *re, char *text) -{ - if(re[0] == '\0') - return 1; - if(re[1] == '*') - return matchstar(re[0], re+2, text); - if(re[0] == '$' && re[1] == '\0') - return *text == '\0'; - if(*text!='\0' && (re[0]=='.' || re[0]==*text)) - return matchhere(re+1, text+1); - return 0; +int matchhere(char *re, char *text) { + if (re[0] == '\0') + return 1; + if (re[1] == '*') + return matchstar(re[0], re + 2, text); + if (re[0] == '$' && re[1] == '\0') + return *text == '\0'; + if (*text != '\0' && (re[0] == '.' || re[0] == *text)) + return matchhere(re + 1, text + 1); + return 0; } // matchstar: search for c*re at beginning of text -int matchstar(int c, char *re, char *text) -{ - do{ // a * matches zero or more instances - if(matchhere(re, text)) - return 1; - }while(*text!='\0' && (*text++==c || c=='.')); - return 0; +int matchstar(int c, char *re, char *text) { + do { // a * matches zero or more instances + if (matchhere(re, text)) + return 1; + } while (*text != '\0' && (*text++ == c || c == '.')); + return 0; } - diff --git a/user/grind.c b/user/grind.c index 431ed19..9cd90c6 100644 --- a/user/grind.c +++ b/user/grind.c @@ -13,339 +13,328 @@ #include "kernel/riscv.h" // from FreeBSD. -int -do_rand(unsigned long *ctx) -{ -/* - * Compute x = (7^5 * x) mod (2^31 - 1) - * without overflowing 31 bits: - * (2^31 - 1) = 127773 * (7^5) + 2836 - * From "Random number generators: good ones are hard to find", - * Park and Miller, Communications of the ACM, vol. 31, no. 10, - * October 1988, p. 1195. - */ - long hi, lo, x; +int do_rand(unsigned long *ctx) { + /* + * Compute x = (7^5 * x) mod (2^31 - 1) + * without overflowing 31 bits: + * (2^31 - 1) = 127773 * (7^5) + 2836 + * From "Random number generators: good ones are hard to find", + * Park and Miller, Communications of the ACM, vol. 31, no. 10, + * October 1988, p. 1195. + */ + long hi, lo, x; - /* Transform to [1, 0x7ffffffe] range. */ - x = (*ctx % 0x7ffffffe) + 1; - hi = x / 127773; - lo = x % 127773; - x = 16807 * lo - 2836 * hi; - if (x < 0) - x += 0x7fffffff; - /* Transform to [0, 0x7ffffffd] range. */ - x--; - *ctx = x; - return (x); + /* Transform to [1, 0x7ffffffe] range. */ + x = (*ctx % 0x7ffffffe) + 1; + hi = x / 127773; + lo = x % 127773; + x = 16807 * lo - 2836 * hi; + if (x < 0) + x += 0x7fffffff; + /* Transform to [0, 0x7ffffffd] range. */ + x--; + *ctx = x; + return (x); } unsigned long rand_next = 1; -int -rand(void) -{ - return (do_rand(&rand_next)); +int rand(void) { return (do_rand(&rand_next)); } + +void go(int which_child) { + int fd = -1; + static char buf[999]; + char *break0 = sbrk(0); + uint64 iters = 0; + + mkdir("grindir"); + if (chdir("grindir") != 0) { + printf("grind: chdir grindir failed\n"); + exit(1); + } + chdir("/"); + + while (1) { + iters++; + if ((iters % 500) == 0) + write(1, which_child ? "B" : "A", 1); + int what = rand() % 23; + if (what == 1) { + close(open("grindir/../a", O_CREATE | O_RDWR)); + } else if (what == 2) { + close(open("grindir/../grindir/../b", O_CREATE | O_RDWR)); + } else if (what == 3) { + unlink("grindir/../a"); + } else if (what == 4) { + if (chdir("grindir") != 0) { + printf("grind: chdir grindir failed\n"); + exit(1); + } + unlink("../b"); + chdir("/"); + } else if (what == 5) { + close(fd); + fd = open("/grindir/../a", O_CREATE | O_RDWR); + } else if (what == 6) { + close(fd); + fd = open("/./grindir/./../b", O_CREATE | O_RDWR); + } else if (what == 7) { + write(fd, buf, sizeof(buf)); + } else if (what == 8) { + read(fd, buf, sizeof(buf)); + } else if (what == 9) { + mkdir("grindir/../a"); + close(open("a/../a/./a", O_CREATE | O_RDWR)); + unlink("a/a"); + } else if (what == 10) { + mkdir("/../b"); + close(open("grindir/../b/b", O_CREATE | O_RDWR)); + unlink("b/b"); + } else if (what == 11) { + unlink("b"); + link("../grindir/./../a", "../b"); + } else if (what == 12) { + unlink("../grindir/../a"); + link(".././b", "/grindir/../a"); + } else if (what == 13) { + int pid = fork(); + if (pid == 0) { + exit(0); + } else if (pid < 0) { + printf("grind: fork failed\n"); + exit(1); + } + wait(0); + } else if (what == 14) { + int pid = fork(); + if (pid == 0) { + fork(); + fork(); + exit(0); + } else if (pid < 0) { + printf("grind: fork failed\n"); + exit(1); + } + wait(0); + } else if (what == 15) { + sbrk(6011); + } else if (what == 16) { + if (sbrk(0) > break0) + sbrk(-(sbrk(0) - break0)); + } else if (what == 17) { + int pid = fork(); + if (pid == 0) { + close(open("a", O_CREATE | O_RDWR)); + exit(0); + } else if (pid < 0) { + printf("grind: fork failed\n"); + exit(1); + } + if (chdir("../grindir/..") != 0) { + printf("grind: chdir failed\n"); + exit(1); + } + kill(pid); + wait(0); + } else if (what == 18) { + int pid = fork(); + if (pid == 0) { + kill(getpid()); + exit(0); + } else if (pid < 0) { + printf("grind: fork failed\n"); + exit(1); + } + wait(0); + } else if (what == 19) { + int fds[2]; + if (pipe(fds) < 0) { + printf("grind: pipe failed\n"); + exit(1); + } + int pid = fork(); + if (pid == 0) { + fork(); + fork(); + if (write(fds[1], "x", 1) != 1) + printf("grind: pipe write failed\n"); + char c; + if (read(fds[0], &c, 1) != 1) + printf("grind: pipe read failed\n"); + exit(0); + } else if (pid < 0) { + printf("grind: fork failed\n"); + exit(1); + } + close(fds[0]); + close(fds[1]); + wait(0); + } else if (what == 20) { + int pid = fork(); + if (pid == 0) { + unlink("a"); + mkdir("a"); + chdir("a"); + unlink("../a"); + fd = open("x", O_CREATE | O_RDWR); + unlink("x"); + exit(0); + } else if (pid < 0) { + printf("grind: fork failed\n"); + exit(1); + } + wait(0); + } else if (what == 21) { + unlink("c"); + // should always succeed. check that there are free i-nodes, + // file descriptors, blocks. + int fd1 = open("c", O_CREATE | O_RDWR); + if (fd1 < 0) { + printf("grind: create c failed\n"); + exit(1); + } + if (write(fd1, "x", 1) != 1) { + printf("grind: write c failed\n"); + exit(1); + } + struct stat st; + if (fstat(fd1, &st) != 0) { + printf("grind: fstat failed\n"); + exit(1); + } + if (st.size != 1) { + printf("grind: fstat reports wrong size %d\n", (int)st.size); + exit(1); + } + if (st.ino > 200) { + printf("grind: fstat reports crazy i-number %d\n", st.ino); + exit(1); + } + close(fd1); + unlink("c"); + } else if (what == 22) { + // echo hi | cat + int aa[2], bb[2]; + if (pipe(aa) < 0) { + fprintf(2, "grind: pipe failed\n"); + exit(1); + } + if (pipe(bb) < 0) { + fprintf(2, "grind: pipe failed\n"); + exit(1); + } + int pid1 = fork(); + if (pid1 == 0) { + close(bb[0]); + close(bb[1]); + close(aa[0]); + close(1); + if (dup(aa[1]) != 1) { + fprintf(2, "grind: dup failed\n"); + exit(1); + } + close(aa[1]); + char *args[3] = {"echo", "hi", 0}; + exec("grindir/../echo", args); + fprintf(2, "grind: echo: not found\n"); + exit(2); + } else if (pid1 < 0) { + fprintf(2, "grind: fork failed\n"); + exit(3); + } + int pid2 = fork(); + if (pid2 == 0) { + close(aa[1]); + close(bb[0]); + close(0); + if (dup(aa[0]) != 0) { + fprintf(2, "grind: dup failed\n"); + exit(4); + } + close(aa[0]); + close(1); + if (dup(bb[1]) != 1) { + fprintf(2, "grind: dup failed\n"); + exit(5); + } + close(bb[1]); + char *args[2] = {"cat", 0}; + exec("/cat", args); + fprintf(2, "grind: cat: not found\n"); + exit(6); + } else if (pid2 < 0) { + fprintf(2, "grind: fork failed\n"); + exit(7); + } + close(aa[0]); + close(aa[1]); + close(bb[1]); + char buf[4] = {0, 0, 0, 0}; + read(bb[0], buf + 0, 1); + read(bb[0], buf + 1, 1); + read(bb[0], buf + 2, 1); + close(bb[0]); + int st1, st2; + wait(&st1); + wait(&st2); + if (st1 != 0 || st2 != 0 || strcmp(buf, "hi\n") != 0) { + printf("grind: exec pipeline failed %d %d \"%s\"\n", st1, st2, + buf); + exit(1); + } + } + } } -void -go(int which_child) -{ - int fd = -1; - static char buf[999]; - char *break0 = sbrk(0); - uint64 iters = 0; +void iter() { + unlink("a"); + unlink("b"); - mkdir("grindir"); - if(chdir("grindir") != 0){ - printf("grind: chdir grindir failed\n"); - exit(1); - } - chdir("/"); - - while(1){ - iters++; - if((iters % 500) == 0) - write(1, which_child?"B":"A", 1); - int what = rand() % 23; - if(what == 1){ - close(open("grindir/../a", O_CREATE|O_RDWR)); - } else if(what == 2){ - close(open("grindir/../grindir/../b", O_CREATE|O_RDWR)); - } else if(what == 3){ - unlink("grindir/../a"); - } else if(what == 4){ - if(chdir("grindir") != 0){ - printf("grind: chdir grindir failed\n"); - exit(1); - } - unlink("../b"); - chdir("/"); - } else if(what == 5){ - close(fd); - fd = open("/grindir/../a", O_CREATE|O_RDWR); - } else if(what == 6){ - close(fd); - fd = open("/./grindir/./../b", O_CREATE|O_RDWR); - } else if(what == 7){ - write(fd, buf, sizeof(buf)); - } else if(what == 8){ - read(fd, buf, sizeof(buf)); - } else if(what == 9){ - mkdir("grindir/../a"); - close(open("a/../a/./a", O_CREATE|O_RDWR)); - unlink("a/a"); - } else if(what == 10){ - mkdir("/../b"); - close(open("grindir/../b/b", O_CREATE|O_RDWR)); - unlink("b/b"); - } else if(what == 11){ - unlink("b"); - link("../grindir/./../a", "../b"); - } else if(what == 12){ - unlink("../grindir/../a"); - link(".././b", "/grindir/../a"); - } else if(what == 13){ - int pid = fork(); - if(pid == 0){ - exit(0); - } else if(pid < 0){ - printf("grind: fork failed\n"); - exit(1); - } - wait(0); - } else if(what == 14){ - int pid = fork(); - if(pid == 0){ - fork(); - fork(); - exit(0); - } else if(pid < 0){ - printf("grind: fork failed\n"); - exit(1); - } - wait(0); - } else if(what == 15){ - sbrk(6011); - } else if(what == 16){ - if(sbrk(0) > break0) - sbrk(-(sbrk(0) - break0)); - } else if(what == 17){ - int pid = fork(); - if(pid == 0){ - close(open("a", O_CREATE|O_RDWR)); - exit(0); - } else if(pid < 0){ - printf("grind: fork failed\n"); - exit(1); - } - if(chdir("../grindir/..") != 0){ - printf("grind: chdir failed\n"); - exit(1); - } - kill(pid); - wait(0); - } else if(what == 18){ - int pid = fork(); - if(pid == 0){ - kill(getpid()); - exit(0); - } else if(pid < 0){ - printf("grind: fork failed\n"); - exit(1); - } - wait(0); - } else if(what == 19){ - int fds[2]; - if(pipe(fds) < 0){ - printf("grind: pipe failed\n"); - exit(1); - } - int pid = fork(); - if(pid == 0){ - fork(); - fork(); - if(write(fds[1], "x", 1) != 1) - printf("grind: pipe write failed\n"); - char c; - if(read(fds[0], &c, 1) != 1) - printf("grind: pipe read failed\n"); - exit(0); - } else if(pid < 0){ - printf("grind: fork failed\n"); - exit(1); - } - close(fds[0]); - close(fds[1]); - wait(0); - } else if(what == 20){ - int pid = fork(); - if(pid == 0){ - unlink("a"); - mkdir("a"); - chdir("a"); - unlink("../a"); - fd = open("x", O_CREATE|O_RDWR); - unlink("x"); - exit(0); - } else if(pid < 0){ - printf("grind: fork failed\n"); - exit(1); - } - wait(0); - } else if(what == 21){ - unlink("c"); - // should always succeed. check that there are free i-nodes, - // file descriptors, blocks. - int fd1 = open("c", O_CREATE|O_RDWR); - if(fd1 < 0){ - printf("grind: create c failed\n"); - exit(1); - } - if(write(fd1, "x", 1) != 1){ - printf("grind: write c failed\n"); - exit(1); - } - struct stat st; - if(fstat(fd1, &st) != 0){ - printf("grind: fstat failed\n"); - exit(1); - } - if(st.size != 1){ - printf("grind: fstat reports wrong size %d\n", (int)st.size); - exit(1); - } - if(st.ino > 200){ - printf("grind: fstat reports crazy i-number %d\n", st.ino); - exit(1); - } - close(fd1); - unlink("c"); - } else if(what == 22){ - // echo hi | cat - int aa[2], bb[2]; - if(pipe(aa) < 0){ - fprintf(2, "grind: pipe failed\n"); - exit(1); - } - if(pipe(bb) < 0){ - fprintf(2, "grind: pipe failed\n"); - exit(1); - } - int pid1 = fork(); - if(pid1 == 0){ - close(bb[0]); - close(bb[1]); - close(aa[0]); - close(1); - if(dup(aa[1]) != 1){ - fprintf(2, "grind: dup failed\n"); - exit(1); - } - close(aa[1]); - char *args[3] = { "echo", "hi", 0 }; - exec("grindir/../echo", args); - fprintf(2, "grind: echo: not found\n"); - exit(2); - } else if(pid1 < 0){ - fprintf(2, "grind: fork failed\n"); - exit(3); - } - int pid2 = fork(); - if(pid2 == 0){ - close(aa[1]); - close(bb[0]); - close(0); - if(dup(aa[0]) != 0){ - fprintf(2, "grind: dup failed\n"); - exit(4); - } - close(aa[0]); - close(1); - if(dup(bb[1]) != 1){ - fprintf(2, "grind: dup failed\n"); - exit(5); - } - close(bb[1]); - char *args[2] = { "cat", 0 }; - exec("/cat", args); - fprintf(2, "grind: cat: not found\n"); - exit(6); - } else if(pid2 < 0){ - fprintf(2, "grind: fork failed\n"); - exit(7); - } - close(aa[0]); - close(aa[1]); - close(bb[1]); - char buf[4] = { 0, 0, 0, 0 }; - read(bb[0], buf+0, 1); - read(bb[0], buf+1, 1); - read(bb[0], buf+2, 1); - close(bb[0]); - int st1, st2; - wait(&st1); - wait(&st2); - if(st1 != 0 || st2 != 0 || strcmp(buf, "hi\n") != 0){ - printf("grind: exec pipeline failed %d %d \"%s\"\n", st1, st2, buf); - exit(1); - } - } - } + int pid1 = fork(); + if (pid1 < 0) { + printf("grind: fork failed\n"); + exit(1); + } + if (pid1 == 0) { + rand_next ^= 31; + go(0); + exit(0); + } + + int pid2 = fork(); + if (pid2 < 0) { + printf("grind: fork failed\n"); + exit(1); + } + if (pid2 == 0) { + rand_next ^= 7177; + go(1); + exit(0); + } + + int st1 = -1; + wait(&st1); + if (st1 != 0) { + kill(pid1); + kill(pid2); + } + int st2 = -1; + wait(&st2); + + exit(0); } -void -iter() -{ - unlink("a"); - unlink("b"); - - int pid1 = fork(); - if(pid1 < 0){ - printf("grind: fork failed\n"); - exit(1); - } - if(pid1 == 0){ - rand_next ^= 31; - go(0); - exit(0); - } - - int pid2 = fork(); - if(pid2 < 0){ - printf("grind: fork failed\n"); - exit(1); - } - if(pid2 == 0){ - rand_next ^= 7177; - go(1); - exit(0); - } - - int st1 = -1; - wait(&st1); - if(st1 != 0){ - kill(pid1); - kill(pid2); - } - int st2 = -1; - wait(&st2); - - exit(0); -} - -int -main() -{ - while(1){ - int pid = fork(); - if(pid == 0){ - iter(); - exit(0); - } - if(pid > 0){ - wait(0); - } - sleep(20); - rand_next += 1; - } +int main() { + while (1) { + int pid = fork(); + if (pid == 0) { + iter(); + exit(0); + } + if (pid > 0) { + wait(0); + } + sleep(20); + rand_next += 1; + } } diff --git a/user/init.c b/user/init.c index e0a5689..2960047 100644 --- a/user/init.c +++ b/user/init.c @@ -9,46 +9,44 @@ #include "user/user.h" #include "kernel/fcntl.h" -char *argv[] = { "sh", 0 }; +char *argv[] = {"sh", 0}; -int -main(void) -{ - int pid, wpid; +int main(void) { + int pid, wpid; - if(open("console", O_RDWR) < 0){ - mknod("console", CONSOLE, 0); - open("console", O_RDWR); - } - dup(0); // stdout - dup(0); // stderr + if (open("console", O_RDWR) < 0) { + mknod("console", CONSOLE, 0); + open("console", O_RDWR); + } + dup(0); // stdout + dup(0); // stderr - for(;;){ - printf("init: starting sh\n"); - pid = fork(); - if(pid < 0){ - printf("init: fork failed\n"); - exit(1); - } - if(pid == 0){ - exec("sh", argv); - printf("init: exec sh failed\n"); - exit(1); - } + for (;;) { + printf("init: starting sh\n"); + pid = fork(); + if (pid < 0) { + printf("init: fork failed\n"); + exit(1); + } + if (pid == 0) { + exec("sh", argv); + printf("init: exec sh failed\n"); + exit(1); + } - for(;;){ - // this call to wait() returns if the shell exits, - // or if a parentless process exits. - wpid = wait((int *) 0); - if(wpid == pid){ - // the shell exited; restart it. - break; - } else if(wpid < 0){ - printf("init: wait returned an error\n"); - exit(1); - } else { - // it was a parentless process; do nothing. - } - } - } + for (;;) { + // this call to wait() returns if the shell exits, + // or if a parentless process exits. + wpid = wait((int *)0); + if (wpid == pid) { + // the shell exited; restart it. + break; + } else if (wpid < 0) { + printf("init: wait returned an error\n"); + exit(1); + } else { + // it was a parentless process; do nothing. + } + } + } } diff --git a/user/kill.c b/user/kill.c index 1b0253b..4fd4abb 100644 --- a/user/kill.c +++ b/user/kill.c @@ -2,16 +2,14 @@ #include "kernel/stat.h" #include "user/user.h" -int -main(int argc, char **argv) -{ - int i; +int main(int argc, char **argv) { + int i; - if(argc < 2){ - fprintf(2, "usage: kill pid...\n"); - exit(1); - } - for(i=1; i= path && *p != '/'; p--) - ; - p++; + // Find first character after last slash. + for (p = path + strlen(path); p >= path && *p != '/'; p--) + ; + p++; - // Return blank-padded name. - if(strlen(p) >= DIRSIZ) - return p; - memmove(buf, p, strlen(p)); - memset(buf+strlen(p), ' ', DIRSIZ-strlen(p)); - return buf; + // Return blank-padded name. + if (strlen(p) >= DIRSIZ) + return p; + memmove(buf, p, strlen(p)); + memset(buf + strlen(p), ' ', DIRSIZ - strlen(p)); + return buf; } -void -ls(char *path) -{ - char buf[512], *p; - int fd; - struct dirent de; - struct stat st; +void ls(char *path) { + char buf[512], *p; + int fd; + struct dirent de; + struct stat st; - if((fd = open(path, 0)) < 0){ - fprintf(2, "ls: cannot open %s\n", path); - return; - } + if ((fd = open(path, 0)) < 0) { + fprintf(2, "ls: cannot open %s\n", path); + return; + } - if(fstat(fd, &st) < 0){ - fprintf(2, "ls: cannot stat %s\n", path); - close(fd); - return; - } + if (fstat(fd, &st) < 0) { + fprintf(2, "ls: cannot stat %s\n", path); + close(fd); + return; + } - switch(st.type){ - case T_DEVICE: - case T_FILE: - printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size); - break; + switch (st.type) { + case T_DEVICE: + case T_FILE: + printf("%s %d %d %l\n", fmtname(path), st.type, st.ino, st.size); + break; - case T_DIR: - if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){ - printf("ls: path too long\n"); - break; - } - strcpy(buf, path); - p = buf+strlen(buf); - *p++ = '/'; - while(read(fd, &de, sizeof(de)) == sizeof(de)){ - if(de.inum == 0) - continue; - memmove(p, de.name, DIRSIZ); - p[DIRSIZ] = 0; - if(stat(buf, &st) < 0){ - printf("ls: cannot stat %s\n", buf); - continue; - } - printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size); - } - break; - } - close(fd); + case T_DIR: + if (strlen(path) + 1 + DIRSIZ + 1 > sizeof buf) { + printf("ls: path too long\n"); + break; + } + strcpy(buf, path); + p = buf + strlen(buf); + *p++ = '/'; + while (read(fd, &de, sizeof(de)) == sizeof(de)) { + if (de.inum == 0) + continue; + memmove(p, de.name, DIRSIZ); + p[DIRSIZ] = 0; + if (stat(buf, &st) < 0) { + printf("ls: cannot stat %s\n", buf); + continue; + } + printf("%s %d %d %d\n", fmtname(buf), st.type, st.ino, st.size); + } + break; + } + close(fd); } -int -main(int argc, char *argv[]) -{ - int i; +int main(int argc, char *argv[]) { + int i; - if(argc < 2){ - ls("."); - exit(0); - } - for(i=1; i= 0) + putc(fd, buf[i]); } -static void -printint(int fd, int xx, int base, int sgn) -{ - char buf[16]; - int i, neg; - uint x; - - neg = 0; - if(sgn && xx < 0){ - neg = 1; - x = -xx; - } else { - x = xx; - } - - i = 0; - do{ - buf[i++] = digits[x % base]; - }while((x /= base) != 0); - if(neg) - buf[i++] = '-'; - - while(--i >= 0) - putc(fd, buf[i]); -} - -static void -printptr(int fd, uint64 x) { - int i; - putc(fd, '0'); - putc(fd, 'x'); - for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) - putc(fd, digits[x >> (sizeof(uint64) * 8 - 4)]); +static void printptr(int fd, uint64 x) { + int i; + putc(fd, '0'); + putc(fd, 'x'); + for (i = 0; i < (sizeof(uint64) * 2); i++, x <<= 4) + putc(fd, digits[x >> (sizeof(uint64) * 8 - 4)]); } // Print to the given fd. Only understands %d, %x, %p, %s. -void -vprintf(int fd, const char *fmt, va_list ap) -{ - char *s; - int c, i, state; +void vprintf(int fd, const char *fmt, va_list ap) { + char *s; + int c, i, state; - state = 0; - for(i = 0; fmt[i]; i++){ - c = fmt[i] & 0xff; - if(state == 0){ - if(c == '%'){ - state = '%'; - } else { - putc(fd, c); - } - } else if(state == '%'){ - if(c == 'd'){ - printint(fd, va_arg(ap, int), 10, 1); - } else if(c == 'l') { - printint(fd, va_arg(ap, uint64), 10, 0); - } else if(c == 'x') { - printint(fd, va_arg(ap, int), 16, 0); - } else if(c == 'p') { - printptr(fd, va_arg(ap, uint64)); - } else if(c == 's'){ - s = va_arg(ap, char*); - if(s == 0) - s = "(null)"; - while(*s != 0){ - putc(fd, *s); - s++; - } - } else if(c == 'c'){ - putc(fd, va_arg(ap, uint)); - } else if(c == '%'){ - putc(fd, c); - } else { - // Unknown % sequence. Print it to draw attention. - putc(fd, '%'); - putc(fd, c); - } - state = 0; - } - } + state = 0; + for (i = 0; fmt[i]; i++) { + c = fmt[i] & 0xff; + if (state == 0) { + if (c == '%') { + state = '%'; + } else { + putc(fd, c); + } + } else if (state == '%') { + if (c == 'd') { + printint(fd, va_arg(ap, int), 10, 1); + } else if (c == 'l') { + printint(fd, va_arg(ap, uint64), 10, 0); + } else if (c == 'x') { + printint(fd, va_arg(ap, int), 16, 0); + } else if (c == 'p') { + printptr(fd, va_arg(ap, uint64)); + } else if (c == 's') { + s = va_arg(ap, char *); + if (s == 0) + s = "(null)"; + while (*s != 0) { + putc(fd, *s); + s++; + } + } else if (c == 'c') { + putc(fd, va_arg(ap, uint)); + } else if (c == '%') { + putc(fd, c); + } else { + // Unknown % sequence. Print it to draw attention. + putc(fd, '%'); + putc(fd, c); + } + state = 0; + } + } } -void -fprintf(int fd, const char *fmt, ...) -{ - va_list ap; +void fprintf(int fd, const char *fmt, ...) { + va_list ap; - va_start(ap, fmt); - vprintf(fd, fmt, ap); + va_start(ap, fmt); + vprintf(fd, fmt, ap); } -void -printf(const char *fmt, ...) -{ - va_list ap; +void printf(const char *fmt, ...) { + va_list ap; - va_start(ap, fmt); - vprintf(1, fmt, ap); + va_start(ap, fmt); + vprintf(1, fmt, ap); } diff --git a/user/rm.c b/user/rm.c index 26b8f1f..0cbe11b 100644 --- a/user/rm.c +++ b/user/rm.c @@ -2,22 +2,20 @@ #include "kernel/stat.h" #include "user/user.h" -int -main(int argc, char *argv[]) -{ - int i; +int main(int argc, char *argv[]) { + int i; - if(argc < 2){ - fprintf(2, "Usage: rm files...\n"); - exit(1); - } + if (argc < 2) { + fprintf(2, "Usage: rm files...\n"); + exit(1); + } - for(i = 1; i < argc; i++){ - if(unlink(argv[i]) < 0){ - fprintf(2, "rm: %s failed to delete\n", argv[i]); - break; - } - } + for (i = 1; i < argc; i++) { + if (unlink(argv[i]) < 0) { + fprintf(2, "rm: %s failed to delete\n", argv[i]); + break; + } + } - exit(0); + exit(0); } diff --git a/user/sh.c b/user/sh.c index 836ebcb..03dbe21 100644 --- a/user/sh.c +++ b/user/sh.c @@ -5,490 +5,453 @@ #include "kernel/fcntl.h" // Parsed command representation -#define EXEC 1 +#define EXEC 1 #define REDIR 2 -#define PIPE 3 -#define LIST 4 -#define BACK 5 +#define PIPE 3 +#define LIST 4 +#define BACK 5 #define MAXARGS 10 struct cmd { - int type; + int type; }; struct execcmd { - int type; - char *argv[MAXARGS]; - char *eargv[MAXARGS]; + int type; + char *argv[MAXARGS]; + char *eargv[MAXARGS]; }; struct redircmd { - int type; - struct cmd *cmd; - char *file; - char *efile; - int mode; - int fd; + int type; + struct cmd *cmd; + char *file; + char *efile; + int mode; + int fd; }; struct pipecmd { - int type; - struct cmd *left; - struct cmd *right; + int type; + struct cmd *left; + struct cmd *right; }; struct listcmd { - int type; - struct cmd *left; - struct cmd *right; + int type; + struct cmd *left; + struct cmd *right; }; struct backcmd { - int type; - struct cmd *cmd; + int type; + struct cmd *cmd; }; -int fork1(void); // Fork but panics on failure. -void panic(char*); -struct cmd *parsecmd(char*); -void runcmd(struct cmd*) __attribute__((noreturn)); +int fork1(void); // Fork but panics on failure. +void panic(char *); +struct cmd *parsecmd(char *); +void runcmd(struct cmd *) __attribute__((noreturn)); // Execute cmd. Never returns. -void -runcmd(struct cmd *cmd) -{ - int p[2]; - struct backcmd *bcmd; - struct execcmd *ecmd; - struct listcmd *lcmd; - struct pipecmd *pcmd; - struct redircmd *rcmd; +void runcmd(struct cmd *cmd) { + int p[2]; + struct backcmd *bcmd; + struct execcmd *ecmd; + struct listcmd *lcmd; + struct pipecmd *pcmd; + struct redircmd *rcmd; - if(cmd == 0) - exit(1); + if (cmd == 0) + exit(1); - switch(cmd->type){ - default: - panic("runcmd"); + switch (cmd->type) { + default: + panic("runcmd"); - case EXEC: - ecmd = (struct execcmd*)cmd; - if(ecmd->argv[0] == 0) - exit(1); - exec(ecmd->argv[0], ecmd->argv); - fprintf(2, "exec %s failed\n", ecmd->argv[0]); - break; + case EXEC: + ecmd = (struct execcmd *)cmd; + if (ecmd->argv[0] == 0) + exit(1); + exec(ecmd->argv[0], ecmd->argv); + fprintf(2, "exec %s failed\n", ecmd->argv[0]); + break; - case REDIR: - rcmd = (struct redircmd*)cmd; - close(rcmd->fd); - if(open(rcmd->file, rcmd->mode) < 0){ - fprintf(2, "open %s failed\n", rcmd->file); - exit(1); - } - runcmd(rcmd->cmd); - break; + case REDIR: + rcmd = (struct redircmd *)cmd; + close(rcmd->fd); + if (open(rcmd->file, rcmd->mode) < 0) { + fprintf(2, "open %s failed\n", rcmd->file); + exit(1); + } + runcmd(rcmd->cmd); + break; - case LIST: - lcmd = (struct listcmd*)cmd; - if(fork1() == 0) - runcmd(lcmd->left); - wait(0); - runcmd(lcmd->right); - break; + case LIST: + lcmd = (struct listcmd *)cmd; + if (fork1() == 0) + runcmd(lcmd->left); + wait(0); + runcmd(lcmd->right); + break; - case PIPE: - pcmd = (struct pipecmd*)cmd; - if(pipe(p) < 0) - panic("pipe"); - if(fork1() == 0){ - close(1); - dup(p[1]); - close(p[0]); - close(p[1]); - runcmd(pcmd->left); - } - if(fork1() == 0){ - close(0); - dup(p[0]); - close(p[0]); - close(p[1]); - runcmd(pcmd->right); - } - close(p[0]); - close(p[1]); - wait(0); - wait(0); - break; + case PIPE: + pcmd = (struct pipecmd *)cmd; + if (pipe(p) < 0) + panic("pipe"); + if (fork1() == 0) { + close(1); + dup(p[1]); + close(p[0]); + close(p[1]); + runcmd(pcmd->left); + } + if (fork1() == 0) { + close(0); + dup(p[0]); + close(p[0]); + close(p[1]); + runcmd(pcmd->right); + } + close(p[0]); + close(p[1]); + wait(0); + wait(0); + break; - case BACK: - bcmd = (struct backcmd*)cmd; - if(fork1() == 0) - runcmd(bcmd->cmd); - break; - } - exit(0); + case BACK: + bcmd = (struct backcmd *)cmd; + if (fork1() == 0) + runcmd(bcmd->cmd); + break; + } + exit(0); } -int -getcmd(char *buf, int nbuf) -{ - write(2, "$ ", 2); - memset(buf, 0, nbuf); - gets(buf, nbuf); - if(buf[0] == 0) // EOF - return -1; - return 0; +int getcmd(char *buf, int nbuf) { + write(2, "$ ", 2); + memset(buf, 0, nbuf); + gets(buf, nbuf); + if (buf[0] == 0) // EOF + return -1; + return 0; } -int -main(void) -{ - static char buf[100]; - int fd; +int main(void) { + static char buf[100]; + int fd; - // Ensure that three file descriptors are open. - while((fd = open("console", O_RDWR)) >= 0){ - if(fd >= 3){ - close(fd); - break; - } - } + // Ensure that three file descriptors are open. + while ((fd = open("console", O_RDWR)) >= 0) { + if (fd >= 3) { + close(fd); + break; + } + } - // Read and run input commands. - while(getcmd(buf, sizeof(buf)) >= 0){ - if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){ - // Chdir must be called by the parent, not the child. - buf[strlen(buf)-1] = 0; // chop \n - if(chdir(buf+3) < 0) - fprintf(2, "cannot cd %s\n", buf+3); - continue; - } - if(fork1() == 0) - runcmd(parsecmd(buf)); - wait(0); - } - exit(0); + // Read and run input commands. + while (getcmd(buf, sizeof(buf)) >= 0) { + if (buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ') { + // Chdir must be called by the parent, not the child. + buf[strlen(buf) - 1] = 0; // chop \n + if (chdir(buf + 3) < 0) + fprintf(2, "cannot cd %s\n", buf + 3); + continue; + } + if (fork1() == 0) + runcmd(parsecmd(buf)); + wait(0); + } + exit(0); } -void -panic(char *s) -{ - fprintf(2, "%s\n", s); - exit(1); +void panic(char *s) { + fprintf(2, "%s\n", s); + exit(1); } -int -fork1(void) -{ - int pid; +int fork1(void) { + int pid; - pid = fork(); - if(pid == -1) - panic("fork"); - return pid; + pid = fork(); + if (pid == -1) + panic("fork"); + return pid; } -//PAGEBREAK! -// Constructors +// PAGEBREAK! +// Constructors -struct cmd* -execcmd(void) -{ - struct execcmd *cmd; +struct cmd *execcmd(void) { + struct execcmd *cmd; - cmd = malloc(sizeof(*cmd)); - memset(cmd, 0, sizeof(*cmd)); - cmd->type = EXEC; - return (struct cmd*)cmd; + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = EXEC; + return (struct cmd *)cmd; } -struct cmd* -redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd) -{ - struct redircmd *cmd; +struct cmd *redircmd(struct cmd *subcmd, char *file, char *efile, int mode, + int fd) { + struct redircmd *cmd; - cmd = malloc(sizeof(*cmd)); - memset(cmd, 0, sizeof(*cmd)); - cmd->type = REDIR; - cmd->cmd = subcmd; - cmd->file = file; - cmd->efile = efile; - cmd->mode = mode; - cmd->fd = fd; - return (struct cmd*)cmd; + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = REDIR; + cmd->cmd = subcmd; + cmd->file = file; + cmd->efile = efile; + cmd->mode = mode; + cmd->fd = fd; + return (struct cmd *)cmd; } -struct cmd* -pipecmd(struct cmd *left, struct cmd *right) -{ - struct pipecmd *cmd; +struct cmd *pipecmd(struct cmd *left, struct cmd *right) { + struct pipecmd *cmd; - cmd = malloc(sizeof(*cmd)); - memset(cmd, 0, sizeof(*cmd)); - cmd->type = PIPE; - cmd->left = left; - cmd->right = right; - return (struct cmd*)cmd; + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = PIPE; + cmd->left = left; + cmd->right = right; + return (struct cmd *)cmd; } -struct cmd* -listcmd(struct cmd *left, struct cmd *right) -{ - struct listcmd *cmd; +struct cmd *listcmd(struct cmd *left, struct cmd *right) { + struct listcmd *cmd; - cmd = malloc(sizeof(*cmd)); - memset(cmd, 0, sizeof(*cmd)); - cmd->type = LIST; - cmd->left = left; - cmd->right = right; - return (struct cmd*)cmd; + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = LIST; + cmd->left = left; + cmd->right = right; + return (struct cmd *)cmd; } -struct cmd* -backcmd(struct cmd *subcmd) -{ - struct backcmd *cmd; +struct cmd *backcmd(struct cmd *subcmd) { + struct backcmd *cmd; - cmd = malloc(sizeof(*cmd)); - memset(cmd, 0, sizeof(*cmd)); - cmd->type = BACK; - cmd->cmd = subcmd; - return (struct cmd*)cmd; + cmd = malloc(sizeof(*cmd)); + memset(cmd, 0, sizeof(*cmd)); + cmd->type = BACK; + cmd->cmd = subcmd; + return (struct cmd *)cmd; } -//PAGEBREAK! -// Parsing +// PAGEBREAK! +// Parsing char whitespace[] = " \t\r\n\v"; char symbols[] = "<|>&;()"; -int -gettoken(char **ps, char *es, char **q, char **eq) -{ - char *s; - int ret; +int gettoken(char **ps, char *es, char **q, char **eq) { + char *s; + int ret; - s = *ps; - while(s < es && strchr(whitespace, *s)) - s++; - if(q) - *q = s; - ret = *s; - switch(*s){ - case 0: - break; - case '|': - case '(': - case ')': - case ';': - case '&': - case '<': - s++; - break; - case '>': - s++; - if(*s == '>'){ - ret = '+'; - s++; - } - break; - default: - ret = 'a'; - while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s)) - s++; - break; - } - if(eq) - *eq = s; + s = *ps; + while (s < es && strchr(whitespace, *s)) + s++; + if (q) + *q = s; + ret = *s; + switch (*s) { + case 0: + break; + case '|': + case '(': + case ')': + case ';': + case '&': + case '<': + s++; + break; + case '>': + s++; + if (*s == '>') { + ret = '+'; + s++; + } + break; + default: + ret = 'a'; + while (s < es && !strchr(whitespace, *s) && !strchr(symbols, *s)) + s++; + break; + } + if (eq) + *eq = s; - while(s < es && strchr(whitespace, *s)) - s++; - *ps = s; - return ret; + while (s < es && strchr(whitespace, *s)) + s++; + *ps = s; + return ret; } -int -peek(char **ps, char *es, char *toks) -{ - char *s; +int peek(char **ps, char *es, char *toks) { + char *s; - s = *ps; - while(s < es && strchr(whitespace, *s)) - s++; - *ps = s; - return *s && strchr(toks, *s); + s = *ps; + while (s < es && strchr(whitespace, *s)) + s++; + *ps = s; + return *s && strchr(toks, *s); } -struct cmd *parseline(char**, char*); -struct cmd *parsepipe(char**, char*); -struct cmd *parseexec(char**, char*); -struct cmd *nulterminate(struct cmd*); +struct cmd *parseline(char **, char *); +struct cmd *parsepipe(char **, char *); +struct cmd *parseexec(char **, char *); +struct cmd *nulterminate(struct cmd *); -struct cmd* -parsecmd(char *s) -{ - char *es; - struct cmd *cmd; +struct cmd *parsecmd(char *s) { + char *es; + struct cmd *cmd; - es = s + strlen(s); - cmd = parseline(&s, es); - peek(&s, es, ""); - if(s != es){ - fprintf(2, "leftovers: %s\n", s); - panic("syntax"); - } - nulterminate(cmd); - return cmd; + es = s + strlen(s); + cmd = parseline(&s, es); + peek(&s, es, ""); + if (s != es) { + fprintf(2, "leftovers: %s\n", s); + panic("syntax"); + } + nulterminate(cmd); + return cmd; } -struct cmd* -parseline(char **ps, char *es) -{ - struct cmd *cmd; +struct cmd *parseline(char **ps, char *es) { + struct cmd *cmd; - cmd = parsepipe(ps, es); - while(peek(ps, es, "&")){ - gettoken(ps, es, 0, 0); - cmd = backcmd(cmd); - } - if(peek(ps, es, ";")){ - gettoken(ps, es, 0, 0); - cmd = listcmd(cmd, parseline(ps, es)); - } - return cmd; + cmd = parsepipe(ps, es); + while (peek(ps, es, "&")) { + gettoken(ps, es, 0, 0); + cmd = backcmd(cmd); + } + if (peek(ps, es, ";")) { + gettoken(ps, es, 0, 0); + cmd = listcmd(cmd, parseline(ps, es)); + } + return cmd; } -struct cmd* -parsepipe(char **ps, char *es) -{ - struct cmd *cmd; +struct cmd *parsepipe(char **ps, char *es) { + struct cmd *cmd; - cmd = parseexec(ps, es); - if(peek(ps, es, "|")){ - gettoken(ps, es, 0, 0); - cmd = pipecmd(cmd, parsepipe(ps, es)); - } - return cmd; + cmd = parseexec(ps, es); + if (peek(ps, es, "|")) { + gettoken(ps, es, 0, 0); + cmd = pipecmd(cmd, parsepipe(ps, es)); + } + return cmd; } -struct cmd* -parseredirs(struct cmd *cmd, char **ps, char *es) -{ - int tok; - char *q, *eq; +struct cmd *parseredirs(struct cmd *cmd, char **ps, char *es) { + int tok; + char *q, *eq; - while(peek(ps, es, "<>")){ - tok = gettoken(ps, es, 0, 0); - if(gettoken(ps, es, &q, &eq) != 'a') - panic("missing file for redirection"); - switch(tok){ - case '<': - cmd = redircmd(cmd, q, eq, O_RDONLY, 0); - break; - case '>': - cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE|O_TRUNC, 1); - break; - case '+': // >> - cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1); - break; - } - } - return cmd; + while (peek(ps, es, "<>")) { + tok = gettoken(ps, es, 0, 0); + if (gettoken(ps, es, &q, &eq) != 'a') + panic("missing file for redirection"); + switch (tok) { + case '<': + cmd = redircmd(cmd, q, eq, O_RDONLY, 0); + break; + case '>': + cmd = redircmd(cmd, q, eq, O_WRONLY | O_CREATE | O_TRUNC, 1); + break; + case '+': // >> + cmd = redircmd(cmd, q, eq, O_WRONLY | O_CREATE, 1); + break; + } + } + return cmd; } -struct cmd* -parseblock(char **ps, char *es) -{ - struct cmd *cmd; +struct cmd *parseblock(char **ps, char *es) { + struct cmd *cmd; - if(!peek(ps, es, "(")) - panic("parseblock"); - gettoken(ps, es, 0, 0); - cmd = parseline(ps, es); - if(!peek(ps, es, ")")) - panic("syntax - missing )"); - gettoken(ps, es, 0, 0); - cmd = parseredirs(cmd, ps, es); - return cmd; + if (!peek(ps, es, "(")) + panic("parseblock"); + gettoken(ps, es, 0, 0); + cmd = parseline(ps, es); + if (!peek(ps, es, ")")) + panic("syntax - missing )"); + gettoken(ps, es, 0, 0); + cmd = parseredirs(cmd, ps, es); + return cmd; } -struct cmd* -parseexec(char **ps, char *es) -{ - char *q, *eq; - int tok, argc; - struct execcmd *cmd; - struct cmd *ret; +struct cmd *parseexec(char **ps, char *es) { + char *q, *eq; + int tok, argc; + struct execcmd *cmd; + struct cmd *ret; - if(peek(ps, es, "(")) - return parseblock(ps, es); + if (peek(ps, es, "(")) + return parseblock(ps, es); - ret = execcmd(); - cmd = (struct execcmd*)ret; + ret = execcmd(); + cmd = (struct execcmd *)ret; - argc = 0; - ret = parseredirs(ret, ps, es); - while(!peek(ps, es, "|)&;")){ - if((tok=gettoken(ps, es, &q, &eq)) == 0) - break; - if(tok != 'a') - panic("syntax"); - cmd->argv[argc] = q; - cmd->eargv[argc] = eq; - argc++; - if(argc >= MAXARGS) - panic("too many args"); - ret = parseredirs(ret, ps, es); - } - cmd->argv[argc] = 0; - cmd->eargv[argc] = 0; - return ret; + argc = 0; + ret = parseredirs(ret, ps, es); + while (!peek(ps, es, "|)&;")) { + if ((tok = gettoken(ps, es, &q, &eq)) == 0) + break; + if (tok != 'a') + panic("syntax"); + cmd->argv[argc] = q; + cmd->eargv[argc] = eq; + argc++; + if (argc >= MAXARGS) + panic("too many args"); + ret = parseredirs(ret, ps, es); + } + cmd->argv[argc] = 0; + cmd->eargv[argc] = 0; + return ret; } // NUL-terminate all the counted strings. -struct cmd* -nulterminate(struct cmd *cmd) -{ - int i; - struct backcmd *bcmd; - struct execcmd *ecmd; - struct listcmd *lcmd; - struct pipecmd *pcmd; - struct redircmd *rcmd; +struct cmd *nulterminate(struct cmd *cmd) { + int i; + struct backcmd *bcmd; + struct execcmd *ecmd; + struct listcmd *lcmd; + struct pipecmd *pcmd; + struct redircmd *rcmd; - if(cmd == 0) - return 0; + if (cmd == 0) + return 0; - switch(cmd->type){ - case EXEC: - ecmd = (struct execcmd*)cmd; - for(i=0; ecmd->argv[i]; i++) - *ecmd->eargv[i] = 0; - break; + switch (cmd->type) { + case EXEC: + ecmd = (struct execcmd *)cmd; + for (i = 0; ecmd->argv[i]; i++) + *ecmd->eargv[i] = 0; + break; - case REDIR: - rcmd = (struct redircmd*)cmd; - nulterminate(rcmd->cmd); - *rcmd->efile = 0; - break; + case REDIR: + rcmd = (struct redircmd *)cmd; + nulterminate(rcmd->cmd); + *rcmd->efile = 0; + break; - case PIPE: - pcmd = (struct pipecmd*)cmd; - nulterminate(pcmd->left); - nulterminate(pcmd->right); - break; + case PIPE: + pcmd = (struct pipecmd *)cmd; + nulterminate(pcmd->left); + nulterminate(pcmd->right); + break; - case LIST: - lcmd = (struct listcmd*)cmd; - nulterminate(lcmd->left); - nulterminate(lcmd->right); - break; + case LIST: + lcmd = (struct listcmd *)cmd; + nulterminate(lcmd->left); + nulterminate(lcmd->right); + break; - case BACK: - bcmd = (struct backcmd*)cmd; - nulterminate(bcmd->cmd); - break; - } - return cmd; + case BACK: + bcmd = (struct backcmd *)cmd; + nulterminate(bcmd->cmd); + break; + } + return cmd; } diff --git a/user/stressfs.c b/user/stressfs.c index 247a7a5..b3689c6 100644 --- a/user/stressfs.c +++ b/user/stressfs.c @@ -13,37 +13,35 @@ #include "kernel/fs.h" #include "kernel/fcntl.h" -int -main(int argc, char *argv[]) -{ - int fd, i; - char path[] = "stressfs0"; - char data[512]; +int main(int argc, char *argv[]) { + int fd, i; + char path[] = "stressfs0"; + char data[512]; - printf("stressfs starting\n"); - memset(data, 'a', sizeof(data)); + printf("stressfs starting\n"); + memset(data, 'a', sizeof(data)); - for(i = 0; i < 4; i++) - if(fork() > 0) - break; + for (i = 0; i < 4; i++) + if (fork() > 0) + break; - printf("write %d\n", i); + printf("write %d\n", i); - path[8] += i; - fd = open(path, O_CREATE | O_RDWR); - for(i = 0; i < 20; i++) -// printf(fd, "%d\n", i); - write(fd, data, sizeof(data)); - close(fd); + path[8] += i; + fd = open(path, O_CREATE | O_RDWR); + for (i = 0; i < 20; i++) + // printf(fd, "%d\n", i); + write(fd, data, sizeof(data)); + close(fd); - printf("read\n"); + printf("read\n"); - fd = open(path, O_RDONLY); - for (i = 0; i < 20; i++) - read(fd, data, sizeof(data)); - close(fd); + fd = open(path, O_RDONLY); + for (i = 0; i < 20; i++) + read(fd, data, sizeof(data)); + close(fd); - wait(0); + wait(0); - exit(0); + exit(0); } diff --git a/user/ulib.c b/user/ulib.c index c7b66c4..dd17e9e 100644 --- a/user/ulib.c +++ b/user/ulib.c @@ -6,142 +6,118 @@ // // wrapper so that it's OK if main() does not call exit(). // -void -_main() -{ - extern int main(); - main(); - exit(0); +void _main() { + extern int main(); + main(); + exit(0); } -char* -strcpy(char *s, const char *t) -{ - char *os; +char *strcpy(char *s, const char *t) { + char *os; - os = s; - while((*s++ = *t++) != 0) - ; - return os; + os = s; + while ((*s++ = *t++) != 0) + ; + return os; } -int -strcmp(const char *p, const char *q) -{ - while(*p && *p == *q) - p++, q++; - return (uchar)*p - (uchar)*q; +int strcmp(const char *p, const char *q) { + while (*p && *p == *q) + p++, q++; + return (uchar)*p - (uchar)*q; } -uint -strlen(const char *s) -{ - int n; +uint strlen(const char *s) { + int n; - for(n = 0; s[n]; n++) - ; - return n; + for (n = 0; s[n]; n++) + ; + return n; } -void* -memset(void *dst, int c, uint n) -{ - char *cdst = (char *) dst; - int i; - for(i = 0; i < n; i++){ - cdst[i] = c; - } - return dst; +void *memset(void *dst, int c, uint n) { + char *cdst = (char *)dst; + int i; + for (i = 0; i < n; i++) { + cdst[i] = c; + } + return dst; } -char* -strchr(const char *s, char c) -{ - for(; *s; s++) - if(*s == c) - return (char*)s; - return 0; +char *strchr(const char *s, char c) { + for (; *s; s++) + if (*s == c) + return (char *)s; + return 0; } -char* -gets(char *buf, int max) -{ - int i, cc; - char c; +char *gets(char *buf, int max) { + int i, cc; + char c; - for(i=0; i+1 < max; ){ - cc = read(0, &c, 1); - if(cc < 1) - break; - buf[i++] = c; - if(c == '\n' || c == '\r') - break; - } - buf[i] = '\0'; - return buf; + for (i = 0; i + 1 < max;) { + cc = read(0, &c, 1); + if (cc < 1) + break; + buf[i++] = c; + if (c == '\n' || c == '\r') + break; + } + buf[i] = '\0'; + return buf; } -int -stat(const char *n, struct stat *st) -{ - int fd; - int r; +int stat(const char *n, struct stat *st) { + int fd; + int r; - fd = open(n, O_RDONLY); - if(fd < 0) - return -1; - r = fstat(fd, st); - close(fd); - return r; + fd = open(n, O_RDONLY); + if (fd < 0) + return -1; + r = fstat(fd, st); + close(fd); + return r; } -int -atoi(const char *s) -{ - int n; +int atoi(const char *s) { + int n; - n = 0; - while('0' <= *s && *s <= '9') - n = n*10 + *s++ - '0'; - return n; + n = 0; + while ('0' <= *s && *s <= '9') + n = n * 10 + *s++ - '0'; + return n; } -void* -memmove(void *vdst, const void *vsrc, int n) -{ - char *dst; - const char *src; +void *memmove(void *vdst, const void *vsrc, int n) { + char *dst; + const char *src; - dst = vdst; - src = vsrc; - if (src > dst) { - while(n-- > 0) - *dst++ = *src++; - } else { - dst += n; - src += n; - while(n-- > 0) - *--dst = *--src; - } - return vdst; + dst = vdst; + src = vsrc; + if (src > dst) { + while (n-- > 0) + *dst++ = *src++; + } else { + dst += n; + src += n; + while (n-- > 0) + *--dst = *--src; + } + return vdst; } -int -memcmp(const void *s1, const void *s2, uint n) -{ - const char *p1 = s1, *p2 = s2; - while (n-- > 0) { - if (*p1 != *p2) { - return *p1 - *p2; - } - p1++; - p2++; - } - return 0; +int memcmp(const void *s1, const void *s2, uint n) { + const char *p1 = s1, *p2 = s2; + while (n-- > 0) { + if (*p1 != *p2) { + return *p1 - *p2; + } + p1++; + p2++; + } + return 0; } -void * -memcpy(void *dst, const void *src, uint n) -{ - return memmove(dst, src, n); +void *memcpy(void *dst, const void *src, uint n) { + return memmove(dst, src, n); } diff --git a/user/umalloc.c b/user/umalloc.c index 2092a32..0f5542b 100644 --- a/user/umalloc.c +++ b/user/umalloc.c @@ -9,11 +9,11 @@ typedef long Align; union header { - struct { - union header *ptr; - uint size; - } s; - Align x; + struct { + union header *ptr; + uint size; + } s; + Align x; }; typedef union header Header; @@ -21,70 +21,64 @@ typedef union header Header; static Header base; static Header *freep; -void -free(void *ap) -{ - Header *bp, *p; +void free(void *ap) { + Header *bp, *p; - bp = (Header*)ap - 1; - for(p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) - if(p >= p->s.ptr && (bp > p || bp < p->s.ptr)) - break; - if(bp + bp->s.size == p->s.ptr){ - bp->s.size += p->s.ptr->s.size; - bp->s.ptr = p->s.ptr->s.ptr; - } else - bp->s.ptr = p->s.ptr; - if(p + p->s.size == bp){ - p->s.size += bp->s.size; - p->s.ptr = bp->s.ptr; - } else - p->s.ptr = bp; - freep = p; + bp = (Header *)ap - 1; + for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) + if (p >= p->s.ptr && (bp > p || bp < p->s.ptr)) + break; + if (bp + bp->s.size == p->s.ptr) { + bp->s.size += p->s.ptr->s.size; + bp->s.ptr = p->s.ptr->s.ptr; + } else + bp->s.ptr = p->s.ptr; + if (p + p->s.size == bp) { + p->s.size += bp->s.size; + p->s.ptr = bp->s.ptr; + } else + p->s.ptr = bp; + freep = p; } -static Header* -morecore(uint nu) -{ - char *p; - Header *hp; +static Header *morecore(uint nu) { + char *p; + Header *hp; - if(nu < 4096) - nu = 4096; - p = sbrk(nu * sizeof(Header)); - if(p == (char*)-1) - return 0; - hp = (Header*)p; - hp->s.size = nu; - free((void*)(hp + 1)); - return freep; + if (nu < 4096) + nu = 4096; + p = sbrk(nu * sizeof(Header)); + if (p == (char *)-1) + return 0; + hp = (Header *)p; + hp->s.size = nu; + free((void *)(hp + 1)); + return freep; } -void* -malloc(uint nbytes) -{ - Header *p, *prevp; - uint nunits; +void *malloc(uint nbytes) { + Header *p, *prevp; + uint nunits; - nunits = (nbytes + sizeof(Header) - 1)/sizeof(Header) + 1; - if((prevp = freep) == 0){ - base.s.ptr = freep = prevp = &base; - base.s.size = 0; - } - for(p = prevp->s.ptr; ; prevp = p, p = p->s.ptr){ - if(p->s.size >= nunits){ - if(p->s.size == nunits) - prevp->s.ptr = p->s.ptr; - else { - p->s.size -= nunits; - p += p->s.size; - p->s.size = nunits; - } - freep = prevp; - return (void*)(p + 1); - } - if(p == freep) - if((p = morecore(nunits)) == 0) - return 0; - } + nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; + if ((prevp = freep) == 0) { + base.s.ptr = freep = prevp = &base; + base.s.size = 0; + } + for (p = prevp->s.ptr;; prevp = p, p = p->s.ptr) { + if (p->s.size >= nunits) { + if (p->s.size == nunits) + prevp->s.ptr = p->s.ptr; + else { + p->s.size -= nunits; + p += p->s.size; + p->s.size = nunits; + } + freep = prevp; + return (void *)(p + 1); + } + if (p == freep) + if ((p = morecore(nunits)) == 0) + return 0; + } } diff --git a/user/usertests.c b/user/usertests.c index 7d3e9bc..d58816f 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -17,7 +17,7 @@ // prints "OK". // -#define BUFSZ ((MAXOPBLOCKS+2)*BSIZE) +#define BUFSZ ((MAXOPBLOCKS + 2) * BSIZE) char buf[BUFSZ]; @@ -29,447 +29,424 @@ char buf[BUFSZ]; // what if you pass ridiculous pointers to system calls // that read user memory with copyin? -void -copyin(char *s) -{ - uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff }; +void copyin(char *s) { + uint64 addrs[] = {0x80000000LL, 0xffffffffffffffff}; - for(int ai = 0; ai < 2; ai++){ - uint64 addr = addrs[ai]; - - int fd = open("copyin1", O_CREATE|O_WRONLY); - if(fd < 0){ - printf("open(copyin1) failed\n"); - exit(1); - } - int n = write(fd, (void*)addr, 8192); - if(n >= 0){ - printf("write(fd, %p, 8192) returned %d, not -1\n", addr, n); - exit(1); - } - close(fd); - unlink("copyin1"); - - n = write(1, (char*)addr, 8192); - if(n > 0){ - printf("write(1, %p, 8192) returned %d, not -1 or 0\n", addr, n); - exit(1); - } - - int fds[2]; - if(pipe(fds) < 0){ - printf("pipe() failed\n"); - exit(1); - } - n = write(fds[1], (char*)addr, 8192); - if(n > 0){ - printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n); - exit(1); - } - close(fds[0]); - close(fds[1]); - } + for (int ai = 0; ai < 2; ai++) { + uint64 addr = addrs[ai]; + + int fd = open("copyin1", O_CREATE | O_WRONLY); + if (fd < 0) { + printf("open(copyin1) failed\n"); + exit(1); + } + int n = write(fd, (void *)addr, 8192); + if (n >= 0) { + printf("write(fd, %p, 8192) returned %d, not -1\n", addr, n); + exit(1); + } + close(fd); + unlink("copyin1"); + + n = write(1, (char *)addr, 8192); + if (n > 0) { + printf("write(1, %p, 8192) returned %d, not -1 or 0\n", addr, n); + exit(1); + } + + int fds[2]; + if (pipe(fds) < 0) { + printf("pipe() failed\n"); + exit(1); + } + n = write(fds[1], (char *)addr, 8192); + if (n > 0) { + printf("write(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n); + exit(1); + } + close(fds[0]); + close(fds[1]); + } } // what if you pass ridiculous pointers to system calls // that write user memory with copyout? -void -copyout(char *s) -{ - uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff }; +void copyout(char *s) { + uint64 addrs[] = {0x80000000LL, 0xffffffffffffffff}; - for(int ai = 0; ai < 2; ai++){ - uint64 addr = addrs[ai]; + for (int ai = 0; ai < 2; ai++) { + uint64 addr = addrs[ai]; - int fd = open("README", 0); - if(fd < 0){ - printf("open(README) failed\n"); - exit(1); - } - int n = read(fd, (void*)addr, 8192); - if(n > 0){ - printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", addr, n); - exit(1); - } - close(fd); + int fd = open("README", 0); + if (fd < 0) { + printf("open(README) failed\n"); + exit(1); + } + int n = read(fd, (void *)addr, 8192); + if (n > 0) { + printf("read(fd, %p, 8192) returned %d, not -1 or 0\n", addr, n); + exit(1); + } + close(fd); - int fds[2]; - if(pipe(fds) < 0){ - printf("pipe() failed\n"); - exit(1); - } - n = write(fds[1], "x", 1); - if(n != 1){ - printf("pipe write failed\n"); - exit(1); - } - n = read(fds[0], (void*)addr, 8192); - if(n > 0){ - printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n); - exit(1); - } - close(fds[0]); - close(fds[1]); - } + int fds[2]; + if (pipe(fds) < 0) { + printf("pipe() failed\n"); + exit(1); + } + n = write(fds[1], "x", 1); + if (n != 1) { + printf("pipe write failed\n"); + exit(1); + } + n = read(fds[0], (void *)addr, 8192); + if (n > 0) { + printf("read(pipe, %p, 8192) returned %d, not -1 or 0\n", addr, n); + exit(1); + } + close(fds[0]); + close(fds[1]); + } } // what if you pass ridiculous string pointers to system calls? -void -copyinstr1(char *s) -{ - uint64 addrs[] = { 0x80000000LL, 0xffffffffffffffff }; +void copyinstr1(char *s) { + uint64 addrs[] = {0x80000000LL, 0xffffffffffffffff}; - for(int ai = 0; ai < 2; ai++){ - uint64 addr = addrs[ai]; + for (int ai = 0; ai < 2; ai++) { + uint64 addr = addrs[ai]; - int fd = open((char *)addr, O_CREATE|O_WRONLY); - if(fd >= 0){ - printf("open(%p) returned %d, not -1\n", addr, fd); - exit(1); - } - } + int fd = open((char *)addr, O_CREATE | O_WRONLY); + if (fd >= 0) { + printf("open(%p) returned %d, not -1\n", addr, fd); + exit(1); + } + } } // what if a string system call argument is exactly the size // of the kernel buffer it is copied into, so that the null // would fall just beyond the end of the kernel buffer? -void -copyinstr2(char *s) -{ - char b[MAXPATH+1]; +void copyinstr2(char *s) { + char b[MAXPATH + 1]; - for(int i = 0; i < MAXPATH; i++) - b[i] = 'x'; - b[MAXPATH] = '\0'; - - int ret = unlink(b); - if(ret != -1){ - printf("unlink(%s) returned %d, not -1\n", b, ret); - exit(1); - } + for (int i = 0; i < MAXPATH; i++) + b[i] = 'x'; + b[MAXPATH] = '\0'; - int fd = open(b, O_CREATE | O_WRONLY); - if(fd != -1){ - printf("open(%s) returned %d, not -1\n", b, fd); - exit(1); - } + int ret = unlink(b); + if (ret != -1) { + printf("unlink(%s) returned %d, not -1\n", b, ret); + exit(1); + } - ret = link(b, b); - if(ret != -1){ - printf("link(%s, %s) returned %d, not -1\n", b, b, ret); - exit(1); - } + int fd = open(b, O_CREATE | O_WRONLY); + if (fd != -1) { + printf("open(%s) returned %d, not -1\n", b, fd); + exit(1); + } - char *args[] = { "xx", 0 }; - ret = exec(b, args); - if(ret != -1){ - printf("exec(%s) returned %d, not -1\n", b, fd); - exit(1); - } + ret = link(b, b); + if (ret != -1) { + printf("link(%s, %s) returned %d, not -1\n", b, b, ret); + exit(1); + } - int pid = fork(); - if(pid < 0){ - printf("fork failed\n"); - exit(1); - } - if(pid == 0){ - static char big[PGSIZE+1]; - for(int i = 0; i < PGSIZE; i++) - big[i] = 'x'; - big[PGSIZE] = '\0'; - char *args2[] = { big, big, big, 0 }; - ret = exec("echo", args2); - if(ret != -1){ - printf("exec(echo, BIG) returned %d, not -1\n", fd); - exit(1); - } - exit(747); // OK - } + char *args[] = {"xx", 0}; + ret = exec(b, args); + if (ret != -1) { + printf("exec(%s) returned %d, not -1\n", b, fd); + exit(1); + } - int st = 0; - wait(&st); - if(st != 747){ - printf("exec(echo, BIG) succeeded, should have failed\n"); - exit(1); - } + int pid = fork(); + if (pid < 0) { + printf("fork failed\n"); + exit(1); + } + if (pid == 0) { + static char big[PGSIZE + 1]; + for (int i = 0; i < PGSIZE; i++) + big[i] = 'x'; + big[PGSIZE] = '\0'; + char *args2[] = {big, big, big, 0}; + ret = exec("echo", args2); + if (ret != -1) { + printf("exec(echo, BIG) returned %d, not -1\n", fd); + exit(1); + } + exit(747); // OK + } + + int st = 0; + wait(&st); + if (st != 747) { + printf("exec(echo, BIG) succeeded, should have failed\n"); + exit(1); + } } // what if a string argument crosses over the end of last user page? -void -copyinstr3(char *s) -{ - sbrk(8192); - uint64 top = (uint64) sbrk(0); - if((top % PGSIZE) != 0){ - sbrk(PGSIZE - (top % PGSIZE)); - } - top = (uint64) sbrk(0); - if(top % PGSIZE){ - printf("oops\n"); - exit(1); - } +void copyinstr3(char *s) { + sbrk(8192); + uint64 top = (uint64)sbrk(0); + if ((top % PGSIZE) != 0) { + sbrk(PGSIZE - (top % PGSIZE)); + } + top = (uint64)sbrk(0); + if (top % PGSIZE) { + printf("oops\n"); + exit(1); + } - char *b = (char *) (top - 1); - *b = 'x'; + char *b = (char *)(top - 1); + *b = 'x'; - int ret = unlink(b); - if(ret != -1){ - printf("unlink(%s) returned %d, not -1\n", b, ret); - exit(1); - } + int ret = unlink(b); + if (ret != -1) { + printf("unlink(%s) returned %d, not -1\n", b, ret); + exit(1); + } - int fd = open(b, O_CREATE | O_WRONLY); - if(fd != -1){ - printf("open(%s) returned %d, not -1\n", b, fd); - exit(1); - } + int fd = open(b, O_CREATE | O_WRONLY); + if (fd != -1) { + printf("open(%s) returned %d, not -1\n", b, fd); + exit(1); + } - ret = link(b, b); - if(ret != -1){ - printf("link(%s, %s) returned %d, not -1\n", b, b, ret); - exit(1); - } + ret = link(b, b); + if (ret != -1) { + printf("link(%s, %s) returned %d, not -1\n", b, b, ret); + exit(1); + } - char *args[] = { "xx", 0 }; - ret = exec(b, args); - if(ret != -1){ - printf("exec(%s) returned %d, not -1\n", b, fd); - exit(1); - } + char *args[] = {"xx", 0}; + ret = exec(b, args); + if (ret != -1) { + printf("exec(%s) returned %d, not -1\n", b, fd); + exit(1); + } } // See if the kernel refuses to read/write user memory that the // application doesn't have anymore, because it returned it. -void -rwsbrk() -{ - int fd, n; - - uint64 a = (uint64) sbrk(8192); +void rwsbrk() { + int fd, n; - if(a == 0xffffffffffffffffLL) { - printf("sbrk(rwsbrk) failed\n"); - exit(1); - } - - if ((uint64) sbrk(-8192) == 0xffffffffffffffffLL) { - printf("sbrk(rwsbrk) shrink failed\n"); - exit(1); - } + uint64 a = (uint64)sbrk(8192); - fd = open("rwsbrk", O_CREATE|O_WRONLY); - if(fd < 0){ - printf("open(rwsbrk) failed\n"); - exit(1); - } - n = write(fd, (void*)(a+4096), 1024); - if(n >= 0){ - printf("write(fd, %p, 1024) returned %d, not -1\n", a+4096, n); - exit(1); - } - close(fd); - unlink("rwsbrk"); + if (a == 0xffffffffffffffffLL) { + printf("sbrk(rwsbrk) failed\n"); + exit(1); + } - fd = open("README", O_RDONLY); - if(fd < 0){ - printf("open(rwsbrk) failed\n"); - exit(1); - } - n = read(fd, (void*)(a+4096), 10); - if(n >= 0){ - printf("read(fd, %p, 10) returned %d, not -1\n", a+4096, n); - exit(1); - } - close(fd); - - exit(0); + if ((uint64)sbrk(-8192) == 0xffffffffffffffffLL) { + printf("sbrk(rwsbrk) shrink failed\n"); + exit(1); + } + + fd = open("rwsbrk", O_CREATE | O_WRONLY); + if (fd < 0) { + printf("open(rwsbrk) failed\n"); + exit(1); + } + n = write(fd, (void *)(a + 4096), 1024); + if (n >= 0) { + printf("write(fd, %p, 1024) returned %d, not -1\n", a + 4096, n); + exit(1); + } + close(fd); + unlink("rwsbrk"); + + fd = open("README", O_RDONLY); + if (fd < 0) { + printf("open(rwsbrk) failed\n"); + exit(1); + } + n = read(fd, (void *)(a + 4096), 10); + if (n >= 0) { + printf("read(fd, %p, 10) returned %d, not -1\n", a + 4096, n); + exit(1); + } + close(fd); + + exit(0); } // test O_TRUNC. -void -truncate1(char *s) -{ - char buf[32]; - - unlink("truncfile"); - int fd1 = open("truncfile", O_CREATE|O_WRONLY|O_TRUNC); - write(fd1, "abcd", 4); - close(fd1); +void truncate1(char *s) { + char buf[32]; - int fd2 = open("truncfile", O_RDONLY); - int n = read(fd2, buf, sizeof(buf)); - if(n != 4){ - printf("%s: read %d bytes, wanted 4\n", s, n); - exit(1); - } + unlink("truncfile"); + int fd1 = open("truncfile", O_CREATE | O_WRONLY | O_TRUNC); + write(fd1, "abcd", 4); + close(fd1); - fd1 = open("truncfile", O_WRONLY|O_TRUNC); + int fd2 = open("truncfile", O_RDONLY); + int n = read(fd2, buf, sizeof(buf)); + if (n != 4) { + printf("%s: read %d bytes, wanted 4\n", s, n); + exit(1); + } - int fd3 = open("truncfile", O_RDONLY); - n = read(fd3, buf, sizeof(buf)); - if(n != 0){ - printf("aaa fd3=%d\n", fd3); - printf("%s: read %d bytes, wanted 0\n", s, n); - exit(1); - } + fd1 = open("truncfile", O_WRONLY | O_TRUNC); - n = read(fd2, buf, sizeof(buf)); - if(n != 0){ - printf("bbb fd2=%d\n", fd2); - printf("%s: read %d bytes, wanted 0\n", s, n); - exit(1); - } - - write(fd1, "abcdef", 6); + int fd3 = open("truncfile", O_RDONLY); + n = read(fd3, buf, sizeof(buf)); + if (n != 0) { + printf("aaa fd3=%d\n", fd3); + printf("%s: read %d bytes, wanted 0\n", s, n); + exit(1); + } - n = read(fd3, buf, sizeof(buf)); - if(n != 6){ - printf("%s: read %d bytes, wanted 6\n", s, n); - exit(1); - } + n = read(fd2, buf, sizeof(buf)); + if (n != 0) { + printf("bbb fd2=%d\n", fd2); + printf("%s: read %d bytes, wanted 0\n", s, n); + exit(1); + } - n = read(fd2, buf, sizeof(buf)); - if(n != 2){ - printf("%s: read %d bytes, wanted 2\n", s, n); - exit(1); - } + write(fd1, "abcdef", 6); - unlink("truncfile"); + n = read(fd3, buf, sizeof(buf)); + if (n != 6) { + printf("%s: read %d bytes, wanted 6\n", s, n); + exit(1); + } - close(fd1); - close(fd2); - close(fd3); + n = read(fd2, buf, sizeof(buf)); + if (n != 2) { + printf("%s: read %d bytes, wanted 2\n", s, n); + exit(1); + } + + unlink("truncfile"); + + close(fd1); + close(fd2); + close(fd3); } // write to an open FD whose file has just been truncated. // this causes a write at an offset beyond the end of the file. // such writes fail on xv6 (unlike POSIX) but at least // they don't crash. -void -truncate2(char *s) -{ - unlink("truncfile"); +void truncate2(char *s) { + unlink("truncfile"); - int fd1 = open("truncfile", O_CREATE|O_TRUNC|O_WRONLY); - write(fd1, "abcd", 4); + int fd1 = open("truncfile", O_CREATE | O_TRUNC | O_WRONLY); + write(fd1, "abcd", 4); - int fd2 = open("truncfile", O_TRUNC|O_WRONLY); + int fd2 = open("truncfile", O_TRUNC | O_WRONLY); - int n = write(fd1, "x", 1); - if(n != -1){ - printf("%s: write returned %d, expected -1\n", s, n); - exit(1); - } + int n = write(fd1, "x", 1); + if (n != -1) { + printf("%s: write returned %d, expected -1\n", s, n); + exit(1); + } - unlink("truncfile"); - close(fd1); - close(fd2); + unlink("truncfile"); + close(fd1); + close(fd2); } -void -truncate3(char *s) -{ - int pid, xstatus; +void truncate3(char *s) { + int pid, xstatus; - close(open("truncfile", O_CREATE|O_TRUNC|O_WRONLY)); - - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } + close(open("truncfile", O_CREATE | O_TRUNC | O_WRONLY)); - if(pid == 0){ - for(int i = 0; i < 100; i++){ - char buf[32]; - int fd = open("truncfile", O_WRONLY); - if(fd < 0){ - printf("%s: open failed\n", s); - exit(1); - } - int n = write(fd, "1234567890", 10); - if(n != 10){ - printf("%s: write got %d, expected 10\n", s, n); - exit(1); - } - close(fd); - fd = open("truncfile", O_RDONLY); - read(fd, buf, sizeof(buf)); - close(fd); - } - exit(0); - } + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } - for(int i = 0; i < 150; i++){ - int fd = open("truncfile", O_CREATE|O_WRONLY|O_TRUNC); - if(fd < 0){ - printf("%s: open failed\n", s); - exit(1); - } - int n = write(fd, "xxx", 3); - if(n != 3){ - printf("%s: write got %d, expected 3\n", s, n); - exit(1); - } - close(fd); - } + if (pid == 0) { + for (int i = 0; i < 100; i++) { + char buf[32]; + int fd = open("truncfile", O_WRONLY); + if (fd < 0) { + printf("%s: open failed\n", s); + exit(1); + } + int n = write(fd, "1234567890", 10); + if (n != 10) { + printf("%s: write got %d, expected 10\n", s, n); + exit(1); + } + close(fd); + fd = open("truncfile", O_RDONLY); + read(fd, buf, sizeof(buf)); + close(fd); + } + exit(0); + } - wait(&xstatus); - unlink("truncfile"); - exit(xstatus); + for (int i = 0; i < 150; i++) { + int fd = open("truncfile", O_CREATE | O_WRONLY | O_TRUNC); + if (fd < 0) { + printf("%s: open failed\n", s); + exit(1); + } + int n = write(fd, "xxx", 3); + if (n != 3) { + printf("%s: write got %d, expected 3\n", s, n); + exit(1); + } + close(fd); + } + + wait(&xstatus); + unlink("truncfile"); + exit(xstatus); } - // does chdir() call iput(p->cwd) in a transaction? -void -iputtest(char *s) -{ - if(mkdir("iputdir") < 0){ - printf("%s: mkdir failed\n", s); - exit(1); - } - if(chdir("iputdir") < 0){ - printf("%s: chdir iputdir failed\n", s); - exit(1); - } - if(unlink("../iputdir") < 0){ - printf("%s: unlink ../iputdir failed\n", s); - exit(1); - } - if(chdir("/") < 0){ - printf("%s: chdir / failed\n", s); - exit(1); - } +void iputtest(char *s) { + if (mkdir("iputdir") < 0) { + printf("%s: mkdir failed\n", s); + exit(1); + } + if (chdir("iputdir") < 0) { + printf("%s: chdir iputdir failed\n", s); + exit(1); + } + if (unlink("../iputdir") < 0) { + printf("%s: unlink ../iputdir failed\n", s); + exit(1); + } + if (chdir("/") < 0) { + printf("%s: chdir / failed\n", s); + exit(1); + } } // does exit() call iput(p->cwd) in a transaction? -void -exitiputtest(char *s) -{ - int pid, xstatus; +void exitiputtest(char *s) { + int pid, xstatus; - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid == 0){ - if(mkdir("iputdir") < 0){ - printf("%s: mkdir failed\n", s); - exit(1); - } - if(chdir("iputdir") < 0){ - printf("%s: child chdir failed\n", s); - exit(1); - } - if(unlink("../iputdir") < 0){ - printf("%s: unlink ../iputdir failed\n", s); - exit(1); - } - exit(0); - } - wait(&xstatus); - exit(xstatus); + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid == 0) { + if (mkdir("iputdir") < 0) { + printf("%s: mkdir failed\n", s); + exit(1); + } + if (chdir("iputdir") < 0) { + printf("%s: child chdir failed\n", s); + exit(1); + } + if (unlink("../iputdir") < 0) { + printf("%s: unlink ../iputdir failed\n", s); + exit(1); + } + exit(0); + } + wait(&xstatus); + exit(xstatus); } // does the error path in open() for attempt to write a @@ -483,545 +460,514 @@ exitiputtest(char *s) // for(i = 0; i < 10000; i++) // yield(); // } -void -openiputtest(char *s) -{ - int pid, xstatus; +void openiputtest(char *s) { + int pid, xstatus; - if(mkdir("oidir") < 0){ - printf("%s: mkdir oidir failed\n", s); - exit(1); - } - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid == 0){ - int fd = open("oidir", O_RDWR); - if(fd >= 0){ - printf("%s: open directory for write succeeded\n", s); - exit(1); - } - exit(0); - } - sleep(1); - if(unlink("oidir") != 0){ - printf("%s: unlink failed\n", s); - exit(1); - } - wait(&xstatus); - exit(xstatus); + if (mkdir("oidir") < 0) { + printf("%s: mkdir oidir failed\n", s); + exit(1); + } + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid == 0) { + int fd = open("oidir", O_RDWR); + if (fd >= 0) { + printf("%s: open directory for write succeeded\n", s); + exit(1); + } + exit(0); + } + sleep(1); + if (unlink("oidir") != 0) { + printf("%s: unlink failed\n", s); + exit(1); + } + wait(&xstatus); + exit(xstatus); } // simple file system tests -void -opentest(char *s) -{ - int fd; +void opentest(char *s) { + int fd; - fd = open("echo", 0); - if(fd < 0){ - printf("%s: open echo failed!\n", s); - exit(1); - } - close(fd); - fd = open("doesnotexist", 0); - if(fd >= 0){ - printf("%s: open doesnotexist succeeded!\n", s); - exit(1); - } + fd = open("echo", 0); + if (fd < 0) { + printf("%s: open echo failed!\n", s); + exit(1); + } + close(fd); + fd = open("doesnotexist", 0); + if (fd >= 0) { + printf("%s: open doesnotexist succeeded!\n", s); + exit(1); + } } -void -writetest(char *s) -{ - int fd; - int i; - enum { N=100, SZ=10 }; - - fd = open("small", O_CREATE|O_RDWR); - if(fd < 0){ - printf("%s: error: creat small failed!\n", s); - exit(1); - } - for(i = 0; i < N; i++){ - if(write(fd, "aaaaaaaaaa", SZ) != SZ){ - printf("%s: error: write aa %d new file failed\n", s, i); - exit(1); - } - if(write(fd, "bbbbbbbbbb", SZ) != SZ){ - printf("%s: error: write bb %d new file failed\n", s, i); - exit(1); - } - } - close(fd); - fd = open("small", O_RDONLY); - if(fd < 0){ - printf("%s: error: open small failed!\n", s); - exit(1); - } - i = read(fd, buf, N*SZ*2); - if(i != N*SZ*2){ - printf("%s: read failed\n", s); - exit(1); - } - close(fd); +void writetest(char *s) { + int fd; + int i; + enum { N = 100, SZ = 10 }; - if(unlink("small") < 0){ - printf("%s: unlink small failed\n", s); - exit(1); - } + fd = open("small", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: error: creat small failed!\n", s); + exit(1); + } + for (i = 0; i < N; i++) { + if (write(fd, "aaaaaaaaaa", SZ) != SZ) { + printf("%s: error: write aa %d new file failed\n", s, i); + exit(1); + } + if (write(fd, "bbbbbbbbbb", SZ) != SZ) { + printf("%s: error: write bb %d new file failed\n", s, i); + exit(1); + } + } + close(fd); + fd = open("small", O_RDONLY); + if (fd < 0) { + printf("%s: error: open small failed!\n", s); + exit(1); + } + i = read(fd, buf, N * SZ * 2); + if (i != N * SZ * 2) { + printf("%s: read failed\n", s); + exit(1); + } + close(fd); + + if (unlink("small") < 0) { + printf("%s: unlink small failed\n", s); + exit(1); + } } -void -writebig(char *s) -{ - int i, fd, n; +void writebig(char *s) { + int i, fd, n; - fd = open("big", O_CREATE|O_RDWR); - if(fd < 0){ - printf("%s: error: creat big failed!\n", s); - exit(1); - } + fd = open("big", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: error: creat big failed!\n", s); + exit(1); + } - for(i = 0; i < MAXFILE; i++){ - ((int*)buf)[0] = i; - if(write(fd, buf, BSIZE) != BSIZE){ - printf("%s: error: write big file failed\n", s, i); - exit(1); - } - } + for (i = 0; i < MAXFILE; i++) { + ((int *)buf)[0] = i; + if (write(fd, buf, BSIZE) != BSIZE) { + printf("%s: error: write big file failed\n", s, i); + exit(1); + } + } - close(fd); + close(fd); - fd = open("big", O_RDONLY); - if(fd < 0){ - printf("%s: error: open big failed!\n", s); - exit(1); - } + fd = open("big", O_RDONLY); + if (fd < 0) { + printf("%s: error: open big failed!\n", s); + exit(1); + } - n = 0; - for(;;){ - i = read(fd, buf, BSIZE); - if(i == 0){ - if(n == MAXFILE - 1){ - printf("%s: read only %d blocks from big", s, n); - exit(1); - } - break; - } else if(i != BSIZE){ - printf("%s: read failed %d\n", s, i); - exit(1); - } - if(((int*)buf)[0] != n){ - printf("%s: read content of block %d is %d\n", s, - n, ((int*)buf)[0]); - exit(1); - } - n++; - } - close(fd); - if(unlink("big") < 0){ - printf("%s: unlink big failed\n", s); - exit(1); - } + n = 0; + for (;;) { + i = read(fd, buf, BSIZE); + if (i == 0) { + if (n == MAXFILE - 1) { + printf("%s: read only %d blocks from big", s, n); + exit(1); + } + break; + } else if (i != BSIZE) { + printf("%s: read failed %d\n", s, i); + exit(1); + } + if (((int *)buf)[0] != n) { + printf("%s: read content of block %d is %d\n", s, n, + ((int *)buf)[0]); + exit(1); + } + n++; + } + close(fd); + if (unlink("big") < 0) { + printf("%s: unlink big failed\n", s); + exit(1); + } } // many creates, followed by unlink test -void -createtest(char *s) -{ - int i, fd; - enum { N=52 }; +void createtest(char *s) { + int i, fd; + enum { N = 52 }; - char name[3]; - name[0] = 'a'; - name[2] = '\0'; - for(i = 0; i < N; i++){ - name[1] = '0' + i; - fd = open(name, O_CREATE|O_RDWR); - close(fd); - } - name[0] = 'a'; - name[2] = '\0'; - for(i = 0; i < N; i++){ - name[1] = '0' + i; - unlink(name); - } + char name[3]; + name[0] = 'a'; + name[2] = '\0'; + for (i = 0; i < N; i++) { + name[1] = '0' + i; + fd = open(name, O_CREATE | O_RDWR); + close(fd); + } + name[0] = 'a'; + name[2] = '\0'; + for (i = 0; i < N; i++) { + name[1] = '0' + i; + unlink(name); + } } -void dirtest(char *s) -{ - if(mkdir("dir0") < 0){ - printf("%s: mkdir failed\n", s); - exit(1); - } +void dirtest(char *s) { + if (mkdir("dir0") < 0) { + printf("%s: mkdir failed\n", s); + exit(1); + } - if(chdir("dir0") < 0){ - printf("%s: chdir dir0 failed\n", s); - exit(1); - } + if (chdir("dir0") < 0) { + printf("%s: chdir dir0 failed\n", s); + exit(1); + } - if(chdir("..") < 0){ - printf("%s: chdir .. failed\n", s); - exit(1); - } + if (chdir("..") < 0) { + printf("%s: chdir .. failed\n", s); + exit(1); + } - if(unlink("dir0") < 0){ - printf("%s: unlink dir0 failed\n", s); - exit(1); - } + if (unlink("dir0") < 0) { + printf("%s: unlink dir0 failed\n", s); + exit(1); + } } -void -exectest(char *s) -{ - int fd, xstatus, pid; - char *echoargv[] = { "echo", "OK", 0 }; - char buf[3]; +void exectest(char *s) { + int fd, xstatus, pid; + char *echoargv[] = {"echo", "OK", 0}; + char buf[3]; - unlink("echo-ok"); - pid = fork(); - if(pid < 0) { - printf("%s: fork failed\n", s); - exit(1); - } - if(pid == 0) { - close(1); - fd = open("echo-ok", O_CREATE|O_WRONLY); - if(fd < 0) { - printf("%s: create failed\n", s); - exit(1); - } - if(fd != 1) { - printf("%s: wrong fd\n", s); - exit(1); - } - if(exec("echo", echoargv) < 0){ - printf("%s: exec echo failed\n", s); - exit(1); - } - // won't get to here - } - if (wait(&xstatus) != pid) { - printf("%s: wait failed!\n", s); - } - if(xstatus != 0) - exit(xstatus); - - fd = open("echo-ok", O_RDONLY); - if(fd < 0) { - printf("%s: open failed\n", s); - exit(1); - } - if (read(fd, buf, 2) != 2) { - printf("%s: read failed\n", s); - exit(1); - } - unlink("echo-ok"); - if(buf[0] == 'O' && buf[1] == 'K') - exit(0); - else { - printf("%s: wrong output\n", s); - exit(1); - } + unlink("echo-ok"); + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid == 0) { + close(1); + fd = open("echo-ok", O_CREATE | O_WRONLY); + if (fd < 0) { + printf("%s: create failed\n", s); + exit(1); + } + if (fd != 1) { + printf("%s: wrong fd\n", s); + exit(1); + } + if (exec("echo", echoargv) < 0) { + printf("%s: exec echo failed\n", s); + exit(1); + } + // won't get to here + } + if (wait(&xstatus) != pid) { + printf("%s: wait failed!\n", s); + } + if (xstatus != 0) + exit(xstatus); + fd = open("echo-ok", O_RDONLY); + if (fd < 0) { + printf("%s: open failed\n", s); + exit(1); + } + if (read(fd, buf, 2) != 2) { + printf("%s: read failed\n", s); + exit(1); + } + unlink("echo-ok"); + if (buf[0] == 'O' && buf[1] == 'K') + exit(0); + else { + printf("%s: wrong output\n", s); + exit(1); + } } // simple fork and pipe read/write -void -pipe1(char *s) -{ - int fds[2], pid, xstatus; - int seq, i, n, cc, total; - enum { N=5, SZ=1033 }; - - if(pipe(fds) != 0){ - printf("%s: pipe() failed\n", s); - exit(1); - } - pid = fork(); - seq = 0; - if(pid == 0){ - close(fds[0]); - for(n = 0; n < N; n++){ - for(i = 0; i < SZ; i++) - buf[i] = seq++; - if(write(fds[1], buf, SZ) != SZ){ - printf("%s: pipe1 oops 1\n", s); - exit(1); - } - } - exit(0); - } else if(pid > 0){ - close(fds[1]); - total = 0; - cc = 1; - while((n = read(fds[0], buf, cc)) > 0){ - for(i = 0; i < n; i++){ - if((buf[i] & 0xff) != (seq++ & 0xff)){ - printf("%s: pipe1 oops 2\n", s); - return; - } - } - total += n; - cc = cc * 2; - if(cc > sizeof(buf)) - cc = sizeof(buf); - } - if(total != N * SZ){ - printf("%s: pipe1 oops 3 total %d\n", total); - exit(1); - } - close(fds[0]); - wait(&xstatus); - exit(xstatus); - } else { - printf("%s: fork() failed\n", s); - exit(1); - } +void pipe1(char *s) { + int fds[2], pid, xstatus; + int seq, i, n, cc, total; + enum { N = 5, SZ = 1033 }; + + if (pipe(fds) != 0) { + printf("%s: pipe() failed\n", s); + exit(1); + } + pid = fork(); + seq = 0; + if (pid == 0) { + close(fds[0]); + for (n = 0; n < N; n++) { + for (i = 0; i < SZ; i++) + buf[i] = seq++; + if (write(fds[1], buf, SZ) != SZ) { + printf("%s: pipe1 oops 1\n", s); + exit(1); + } + } + exit(0); + } else if (pid > 0) { + close(fds[1]); + total = 0; + cc = 1; + while ((n = read(fds[0], buf, cc)) > 0) { + for (i = 0; i < n; i++) { + if ((buf[i] & 0xff) != (seq++ & 0xff)) { + printf("%s: pipe1 oops 2\n", s); + return; + } + } + total += n; + cc = cc * 2; + if (cc > sizeof(buf)) + cc = sizeof(buf); + } + if (total != N * SZ) { + printf("%s: pipe1 oops 3 total %d\n", total); + exit(1); + } + close(fds[0]); + wait(&xstatus); + exit(xstatus); + } else { + printf("%s: fork() failed\n", s); + exit(1); + } } - // test if child is killed (status = -1) -void -killstatus(char *s) -{ - int xst; - - for(int i = 0; i < 100; i++){ - int pid1 = fork(); - if(pid1 < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid1 == 0){ - while(1) { - getpid(); - } - exit(0); - } - sleep(1); - kill(pid1); - wait(&xst); - if(xst != -1) { - printf("%s: status should be -1\n", s); - exit(1); - } - } - exit(0); +void killstatus(char *s) { + int xst; + + for (int i = 0; i < 100; i++) { + int pid1 = fork(); + if (pid1 < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid1 == 0) { + while (1) { + getpid(); + } + exit(0); + } + sleep(1); + kill(pid1); + wait(&xst); + if (xst != -1) { + printf("%s: status should be -1\n", s); + exit(1); + } + } + exit(0); } // meant to be run w/ at most two CPUs -void -preempt(char *s) -{ - int pid1, pid2, pid3; - int pfds[2]; +void preempt(char *s) { + int pid1, pid2, pid3; + int pfds[2]; - pid1 = fork(); - if(pid1 < 0) { - printf("%s: fork failed", s); - exit(1); - } - if(pid1 == 0) - for(;;) - ; + pid1 = fork(); + if (pid1 < 0) { + printf("%s: fork failed", s); + exit(1); + } + if (pid1 == 0) + for (;;) + ; - pid2 = fork(); - if(pid2 < 0) { - printf("%s: fork failed\n", s); - exit(1); - } - if(pid2 == 0) - for(;;) - ; + pid2 = fork(); + if (pid2 < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid2 == 0) + for (;;) + ; - pipe(pfds); - pid3 = fork(); - if(pid3 < 0) { - printf("%s: fork failed\n", s); - exit(1); - } - if(pid3 == 0){ - close(pfds[0]); - if(write(pfds[1], "x", 1) != 1) - printf("%s: preempt write error", s); - close(pfds[1]); - for(;;) - ; - } + pipe(pfds); + pid3 = fork(); + if (pid3 < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid3 == 0) { + close(pfds[0]); + if (write(pfds[1], "x", 1) != 1) + printf("%s: preempt write error", s); + close(pfds[1]); + for (;;) + ; + } - close(pfds[1]); - if(read(pfds[0], buf, sizeof(buf)) != 1){ - printf("%s: preempt read error", s); - return; - } - close(pfds[0]); - printf("kill... "); - kill(pid1); - kill(pid2); - kill(pid3); - printf("wait... "); - wait(0); - wait(0); - wait(0); + close(pfds[1]); + if (read(pfds[0], buf, sizeof(buf)) != 1) { + printf("%s: preempt read error", s); + return; + } + close(pfds[0]); + printf("kill... "); + kill(pid1); + kill(pid2); + kill(pid3); + printf("wait... "); + wait(0); + wait(0); + wait(0); } // try to find any races between exit and wait -void -exitwait(char *s) -{ - int i, pid; +void exitwait(char *s) { + int i, pid; - for(i = 0; i < 100; i++){ - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid){ - int xstate; - if(wait(&xstate) != pid){ - printf("%s: wait wrong pid\n", s); - exit(1); - } - if(i != xstate) { - printf("%s: wait wrong exit status\n", s); - exit(1); - } - } else { - exit(i); - } - } + for (i = 0; i < 100; i++) { + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid) { + int xstate; + if (wait(&xstate) != pid) { + printf("%s: wait wrong pid\n", s); + exit(1); + } + if (i != xstate) { + printf("%s: wait wrong exit status\n", s); + exit(1); + } + } else { + exit(i); + } + } } // try to find races in the reparenting // code that handles a parent exiting // when it still has live children. -void -reparent(char *s) -{ - int master_pid = getpid(); - for(int i = 0; i < 200; i++){ - int pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid){ - if(wait(0) != pid){ - printf("%s: wait wrong pid\n", s); - exit(1); - } - } else { - int pid2 = fork(); - if(pid2 < 0){ - kill(master_pid); - exit(1); - } - exit(0); - } - } - exit(0); +void reparent(char *s) { + int master_pid = getpid(); + for (int i = 0; i < 200; i++) { + int pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid) { + if (wait(0) != pid) { + printf("%s: wait wrong pid\n", s); + exit(1); + } + } else { + int pid2 = fork(); + if (pid2 < 0) { + kill(master_pid); + exit(1); + } + exit(0); + } + } + exit(0); } // what if two children exit() at the same time? -void -twochildren(char *s) -{ - for(int i = 0; i < 1000; i++){ - int pid1 = fork(); - if(pid1 < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid1 == 0){ - exit(0); - } else { - int pid2 = fork(); - if(pid2 < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid2 == 0){ - exit(0); - } else { - wait(0); - wait(0); - } - } - } +void twochildren(char *s) { + for (int i = 0; i < 1000; i++) { + int pid1 = fork(); + if (pid1 < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid1 == 0) { + exit(0); + } else { + int pid2 = fork(); + if (pid2 < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid2 == 0) { + exit(0); + } else { + wait(0); + wait(0); + } + } + } } // concurrent forks to try to expose locking bugs. -void -forkfork(char *s) -{ - enum { N=2 }; - - for(int i = 0; i < N; i++){ - int pid = fork(); - if(pid < 0){ - printf("%s: fork failed", s); - exit(1); - } - if(pid == 0){ - for(int j = 0; j < 200; j++){ - int pid1 = fork(); - if(pid1 < 0){ - exit(1); - } - if(pid1 == 0){ - exit(0); - } - wait(0); - } - exit(0); - } - } +void forkfork(char *s) { + enum { N = 2 }; - int xstatus; - for(int i = 0; i < N; i++){ - wait(&xstatus); - if(xstatus != 0) { - printf("%s: fork in child failed", s); - exit(1); - } - } + for (int i = 0; i < N; i++) { + int pid = fork(); + if (pid < 0) { + printf("%s: fork failed", s); + exit(1); + } + if (pid == 0) { + for (int j = 0; j < 200; j++) { + int pid1 = fork(); + if (pid1 < 0) { + exit(1); + } + if (pid1 == 0) { + exit(0); + } + wait(0); + } + exit(0); + } + } + + int xstatus; + for (int i = 0; i < N; i++) { + wait(&xstatus); + if (xstatus != 0) { + printf("%s: fork in child failed", s); + exit(1); + } + } } -void -forkforkfork(char *s) -{ - unlink("stopforking"); +void forkforkfork(char *s) { + unlink("stopforking"); - int pid = fork(); - if(pid < 0){ - printf("%s: fork failed", s); - exit(1); - } - if(pid == 0){ - while(1){ - int fd = open("stopforking", 0); - if(fd >= 0){ - exit(0); - } - if(fork() < 0){ - close(open("stopforking", O_CREATE|O_RDWR)); - } - } + int pid = fork(); + if (pid < 0) { + printf("%s: fork failed", s); + exit(1); + } + if (pid == 0) { + while (1) { + int fd = open("stopforking", 0); + if (fd >= 0) { + exit(0); + } + if (fork() < 0) { + close(open("stopforking", O_CREATE | O_RDWR)); + } + } - exit(0); - } + exit(0); + } - sleep(20); // two seconds - close(open("stopforking", O_CREATE|O_RDWR)); - wait(0); - sleep(10); // one second + sleep(20); // two seconds + close(open("stopforking", O_CREATE | O_RDWR)); + wait(0); + sleep(10); // one second } // regression test. does reparent() violate the parent-then-child @@ -1029,1614 +975,1548 @@ forkforkfork(char *s) // deadlocks against init's wait()? also used to trigger a "panic: // release" due to exit() releasing a different p->parent->lock than // it acquired. -void -reparent2(char *s) -{ - for(int i = 0; i < 800; i++){ - int pid1 = fork(); - if(pid1 < 0){ - printf("fork failed\n"); - exit(1); - } - if(pid1 == 0){ - fork(); - fork(); - exit(0); - } - wait(0); - } +void reparent2(char *s) { + for (int i = 0; i < 800; i++) { + int pid1 = fork(); + if (pid1 < 0) { + printf("fork failed\n"); + exit(1); + } + if (pid1 == 0) { + fork(); + fork(); + exit(0); + } + wait(0); + } - exit(0); + exit(0); } // allocate all mem, free it, and allocate again -void -mem(char *s) -{ - void *m1, *m2; - int pid; +void mem(char *s) { + void *m1, *m2; + int pid; - if((pid = fork()) == 0){ - m1 = 0; - while((m2 = malloc(10001)) != 0){ - *(char**)m2 = m1; - m1 = m2; - } - while(m1){ - m2 = *(char**)m1; - free(m1); - m1 = m2; - } - m1 = malloc(1024*20); - if(m1 == 0){ - printf("couldn't allocate mem?!!\n", s); - exit(1); - } - free(m1); - exit(0); - } else { - int xstatus; - wait(&xstatus); - if(xstatus == -1){ - // probably page fault, so might be lazy lab, - // so OK. - exit(0); - } - exit(xstatus); - } + if ((pid = fork()) == 0) { + m1 = 0; + while ((m2 = malloc(10001)) != 0) { + *(char **)m2 = m1; + m1 = m2; + } + while (m1) { + m2 = *(char **)m1; + free(m1); + m1 = m2; + } + m1 = malloc(1024 * 20); + if (m1 == 0) { + printf("couldn't allocate mem?!!\n", s); + exit(1); + } + free(m1); + exit(0); + } else { + int xstatus; + wait(&xstatus); + if (xstatus == -1) { + // probably page fault, so might be lazy lab, + // so OK. + exit(0); + } + exit(xstatus); + } } // More file system tests // two processes write to the same file descriptor // is the offset shared? does inode locking work? -void -sharedfd(char *s) -{ - int fd, pid, i, n, nc, np; - enum { N = 1000, SZ=10}; - char buf[SZ]; +void sharedfd(char *s) { + int fd, pid, i, n, nc, np; + enum { N = 1000, SZ = 10 }; + char buf[SZ]; - unlink("sharedfd"); - fd = open("sharedfd", O_CREATE|O_RDWR); - if(fd < 0){ - printf("%s: cannot open sharedfd for writing", s); - exit(1); - } - pid = fork(); - memset(buf, pid==0?'c':'p', sizeof(buf)); - for(i = 0; i < N; i++){ - if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ - printf("%s: write sharedfd failed\n", s); - exit(1); - } - } - if(pid == 0) { - exit(0); - } else { - int xstatus; - wait(&xstatus); - if(xstatus != 0) - exit(xstatus); - } - - close(fd); - fd = open("sharedfd", 0); - if(fd < 0){ - printf("%s: cannot open sharedfd for reading\n", s); - exit(1); - } - nc = np = 0; - while((n = read(fd, buf, sizeof(buf))) > 0){ - for(i = 0; i < sizeof(buf); i++){ - if(buf[i] == 'c') - nc++; - if(buf[i] == 'p') - np++; - } - } - close(fd); - unlink("sharedfd"); - if(nc == N*SZ && np == N*SZ){ - exit(0); - } else { - printf("%s: nc/np test fails\n", s); - exit(1); - } + unlink("sharedfd"); + fd = open("sharedfd", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: cannot open sharedfd for writing", s); + exit(1); + } + pid = fork(); + memset(buf, pid == 0 ? 'c' : 'p', sizeof(buf)); + for (i = 0; i < N; i++) { + if (write(fd, buf, sizeof(buf)) != sizeof(buf)) { + printf("%s: write sharedfd failed\n", s); + exit(1); + } + } + if (pid == 0) { + exit(0); + } else { + int xstatus; + wait(&xstatus); + if (xstatus != 0) + exit(xstatus); + } + + close(fd); + fd = open("sharedfd", 0); + if (fd < 0) { + printf("%s: cannot open sharedfd for reading\n", s); + exit(1); + } + nc = np = 0; + while ((n = read(fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < sizeof(buf); i++) { + if (buf[i] == 'c') + nc++; + if (buf[i] == 'p') + np++; + } + } + close(fd); + unlink("sharedfd"); + if (nc == N * SZ && np == N * SZ) { + exit(0); + } else { + printf("%s: nc/np test fails\n", s); + exit(1); + } } // four processes write different files at the same // time, to test block allocation. -void -fourfiles(char *s) -{ - int fd, pid, i, j, n, total, pi; - char *names[] = { "f0", "f1", "f2", "f3" }; - char *fname; - enum { N=12, NCHILD=4, SZ=500 }; - - for(pi = 0; pi < NCHILD; pi++){ - fname = names[pi]; - unlink(fname); +void fourfiles(char *s) { + int fd, pid, i, j, n, total, pi; + char *names[] = {"f0", "f1", "f2", "f3"}; + char *fname; + enum { N = 12, NCHILD = 4, SZ = 500 }; - pid = fork(); - if(pid < 0){ - printf("fork failed\n", s); - exit(1); - } + for (pi = 0; pi < NCHILD; pi++) { + fname = names[pi]; + unlink(fname); - if(pid == 0){ - fd = open(fname, O_CREATE | O_RDWR); - if(fd < 0){ - printf("create failed\n", s); - exit(1); - } + pid = fork(); + if (pid < 0) { + printf("fork failed\n", s); + exit(1); + } - memset(buf, '0'+pi, SZ); - for(i = 0; i < N; i++){ - if((n = write(fd, buf, SZ)) != SZ){ - printf("write failed %d\n", n); - exit(1); - } - } - exit(0); - } - } + if (pid == 0) { + fd = open(fname, O_CREATE | O_RDWR); + if (fd < 0) { + printf("create failed\n", s); + exit(1); + } - int xstatus; - for(pi = 0; pi < NCHILD; pi++){ - wait(&xstatus); - if(xstatus != 0) - exit(xstatus); - } + memset(buf, '0' + pi, SZ); + for (i = 0; i < N; i++) { + if ((n = write(fd, buf, SZ)) != SZ) { + printf("write failed %d\n", n); + exit(1); + } + } + exit(0); + } + } - for(i = 0; i < NCHILD; i++){ - fname = names[i]; - fd = open(fname, 0); - total = 0; - while((n = read(fd, buf, sizeof(buf))) > 0){ - for(j = 0; j < n; j++){ - if(buf[j] != '0'+i){ - printf("wrong char\n", s); - exit(1); - } - } - total += n; - } - close(fd); - if(total != N*SZ){ - printf("wrong length %d\n", total); - exit(1); - } - unlink(fname); - } + int xstatus; + for (pi = 0; pi < NCHILD; pi++) { + wait(&xstatus); + if (xstatus != 0) + exit(xstatus); + } + + for (i = 0; i < NCHILD; i++) { + fname = names[i]; + fd = open(fname, 0); + total = 0; + while ((n = read(fd, buf, sizeof(buf))) > 0) { + for (j = 0; j < n; j++) { + if (buf[j] != '0' + i) { + printf("wrong char\n", s); + exit(1); + } + } + total += n; + } + close(fd); + if (total != N * SZ) { + printf("wrong length %d\n", total); + exit(1); + } + unlink(fname); + } } // four processes create and delete different files in same directory -void -createdelete(char *s) -{ - enum { N = 20, NCHILD=4 }; - int pid, i, fd, pi; - char name[32]; +void createdelete(char *s) { + enum { N = 20, NCHILD = 4 }; + int pid, i, fd, pi; + char name[32]; - for(pi = 0; pi < NCHILD; pi++){ - pid = fork(); - if(pid < 0){ - printf("fork failed\n", s); - exit(1); - } + for (pi = 0; pi < NCHILD; pi++) { + pid = fork(); + if (pid < 0) { + printf("fork failed\n", s); + exit(1); + } - if(pid == 0){ - name[0] = 'p' + pi; - name[2] = '\0'; - for(i = 0; i < N; i++){ - name[1] = '0' + i; - fd = open(name, O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: create failed\n", s); - exit(1); - } - close(fd); - if(i > 0 && (i % 2 ) == 0){ - name[1] = '0' + (i / 2); - if(unlink(name) < 0){ - printf("%s: unlink failed\n", s); - exit(1); - } - } - } - exit(0); - } - } + if (pid == 0) { + name[0] = 'p' + pi; + name[2] = '\0'; + for (i = 0; i < N; i++) { + name[1] = '0' + i; + fd = open(name, O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: create failed\n", s); + exit(1); + } + close(fd); + if (i > 0 && (i % 2) == 0) { + name[1] = '0' + (i / 2); + if (unlink(name) < 0) { + printf("%s: unlink failed\n", s); + exit(1); + } + } + } + exit(0); + } + } - int xstatus; - for(pi = 0; pi < NCHILD; pi++){ - wait(&xstatus); - if(xstatus != 0) - exit(1); - } + int xstatus; + for (pi = 0; pi < NCHILD; pi++) { + wait(&xstatus); + if (xstatus != 0) + exit(1); + } - name[0] = name[1] = name[2] = 0; - for(i = 0; i < N; i++){ - for(pi = 0; pi < NCHILD; pi++){ - name[0] = 'p' + pi; - name[1] = '0' + i; - fd = open(name, 0); - if((i == 0 || i >= N/2) && fd < 0){ - printf("%s: oops createdelete %s didn't exist\n", s, name); - exit(1); - } else if((i >= 1 && i < N/2) && fd >= 0){ - printf("%s: oops createdelete %s did exist\n", s, name); - exit(1); - } - if(fd >= 0) - close(fd); - } - } + name[0] = name[1] = name[2] = 0; + for (i = 0; i < N; i++) { + for (pi = 0; pi < NCHILD; pi++) { + name[0] = 'p' + pi; + name[1] = '0' + i; + fd = open(name, 0); + if ((i == 0 || i >= N / 2) && fd < 0) { + printf("%s: oops createdelete %s didn't exist\n", s, name); + exit(1); + } else if ((i >= 1 && i < N / 2) && fd >= 0) { + printf("%s: oops createdelete %s did exist\n", s, name); + exit(1); + } + if (fd >= 0) + close(fd); + } + } - for(i = 0; i < N; i++){ - for(pi = 0; pi < NCHILD; pi++){ - name[0] = 'p' + i; - name[1] = '0' + i; - unlink(name); - } - } + for (i = 0; i < N; i++) { + for (pi = 0; pi < NCHILD; pi++) { + name[0] = 'p' + i; + name[1] = '0' + i; + unlink(name); + } + } } // can I unlink a file and still read it? -void -unlinkread(char *s) -{ - enum { SZ = 5 }; - int fd, fd1; +void unlinkread(char *s) { + enum { SZ = 5 }; + int fd, fd1; - fd = open("unlinkread", O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: create unlinkread failed\n", s); - exit(1); - } - write(fd, "hello", SZ); - close(fd); + fd = open("unlinkread", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: create unlinkread failed\n", s); + exit(1); + } + write(fd, "hello", SZ); + close(fd); - fd = open("unlinkread", O_RDWR); - if(fd < 0){ - printf("%s: open unlinkread failed\n", s); - exit(1); - } - if(unlink("unlinkread") != 0){ - printf("%s: unlink unlinkread failed\n", s); - exit(1); - } + fd = open("unlinkread", O_RDWR); + if (fd < 0) { + printf("%s: open unlinkread failed\n", s); + exit(1); + } + if (unlink("unlinkread") != 0) { + printf("%s: unlink unlinkread failed\n", s); + exit(1); + } - fd1 = open("unlinkread", O_CREATE | O_RDWR); - write(fd1, "yyy", 3); - close(fd1); + fd1 = open("unlinkread", O_CREATE | O_RDWR); + write(fd1, "yyy", 3); + close(fd1); - if(read(fd, buf, sizeof(buf)) != SZ){ - printf("%s: unlinkread read failed", s); - exit(1); - } - if(buf[0] != 'h'){ - printf("%s: unlinkread wrong data\n", s); - exit(1); - } - if(write(fd, buf, 10) != 10){ - printf("%s: unlinkread write failed\n", s); - exit(1); - } - close(fd); - unlink("unlinkread"); + if (read(fd, buf, sizeof(buf)) != SZ) { + printf("%s: unlinkread read failed", s); + exit(1); + } + if (buf[0] != 'h') { + printf("%s: unlinkread wrong data\n", s); + exit(1); + } + if (write(fd, buf, 10) != 10) { + printf("%s: unlinkread write failed\n", s); + exit(1); + } + close(fd); + unlink("unlinkread"); } -void -linktest(char *s) -{ - enum { SZ = 5 }; - int fd; +void linktest(char *s) { + enum { SZ = 5 }; + int fd; - unlink("lf1"); - unlink("lf2"); + unlink("lf1"); + unlink("lf2"); - fd = open("lf1", O_CREATE|O_RDWR); - if(fd < 0){ - printf("%s: create lf1 failed\n", s); - exit(1); - } - if(write(fd, "hello", SZ) != SZ){ - printf("%s: write lf1 failed\n", s); - exit(1); - } - close(fd); + fd = open("lf1", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: create lf1 failed\n", s); + exit(1); + } + if (write(fd, "hello", SZ) != SZ) { + printf("%s: write lf1 failed\n", s); + exit(1); + } + close(fd); - if(link("lf1", "lf2") < 0){ - printf("%s: link lf1 lf2 failed\n", s); - exit(1); - } - unlink("lf1"); + if (link("lf1", "lf2") < 0) { + printf("%s: link lf1 lf2 failed\n", s); + exit(1); + } + unlink("lf1"); - if(open("lf1", 0) >= 0){ - printf("%s: unlinked lf1 but it is still there!\n", s); - exit(1); - } + if (open("lf1", 0) >= 0) { + printf("%s: unlinked lf1 but it is still there!\n", s); + exit(1); + } - fd = open("lf2", 0); - if(fd < 0){ - printf("%s: open lf2 failed\n", s); - exit(1); - } - if(read(fd, buf, sizeof(buf)) != SZ){ - printf("%s: read lf2 failed\n", s); - exit(1); - } - close(fd); + fd = open("lf2", 0); + if (fd < 0) { + printf("%s: open lf2 failed\n", s); + exit(1); + } + if (read(fd, buf, sizeof(buf)) != SZ) { + printf("%s: read lf2 failed\n", s); + exit(1); + } + close(fd); - if(link("lf2", "lf2") >= 0){ - printf("%s: link lf2 lf2 succeeded! oops\n", s); - exit(1); - } + if (link("lf2", "lf2") >= 0) { + printf("%s: link lf2 lf2 succeeded! oops\n", s); + exit(1); + } - unlink("lf2"); - if(link("lf2", "lf1") >= 0){ - printf("%s: link non-existent succeeded! oops\n", s); - exit(1); - } + unlink("lf2"); + if (link("lf2", "lf1") >= 0) { + printf("%s: link non-existent succeeded! oops\n", s); + exit(1); + } - if(link(".", "lf1") >= 0){ - printf("%s: link . lf1 succeeded! oops\n", s); - exit(1); - } + if (link(".", "lf1") >= 0) { + printf("%s: link . lf1 succeeded! oops\n", s); + exit(1); + } } // test concurrent create/link/unlink of the same file -void -concreate(char *s) -{ - enum { N = 40 }; - char file[3]; - int i, pid, n, fd; - char fa[N]; - struct { - ushort inum; - char name[DIRSIZ]; - } de; +void concreate(char *s) { + enum { N = 40 }; + char file[3]; + int i, pid, n, fd; + char fa[N]; + struct { + ushort inum; + char name[DIRSIZ]; + } de; - file[0] = 'C'; - file[2] = '\0'; - for(i = 0; i < N; i++){ - file[1] = '0' + i; - unlink(file); - pid = fork(); - if(pid && (i % 3) == 1){ - link("C0", file); - } else if(pid == 0 && (i % 5) == 1){ - link("C0", file); - } else { - fd = open(file, O_CREATE | O_RDWR); - if(fd < 0){ - printf("concreate create %s failed\n", file); - exit(1); - } - close(fd); - } - if(pid == 0) { - exit(0); - } else { - int xstatus; - wait(&xstatus); - if(xstatus != 0) - exit(1); - } - } + file[0] = 'C'; + file[2] = '\0'; + for (i = 0; i < N; i++) { + file[1] = '0' + i; + unlink(file); + pid = fork(); + if (pid && (i % 3) == 1) { + link("C0", file); + } else if (pid == 0 && (i % 5) == 1) { + link("C0", file); + } else { + fd = open(file, O_CREATE | O_RDWR); + if (fd < 0) { + printf("concreate create %s failed\n", file); + exit(1); + } + close(fd); + } + if (pid == 0) { + exit(0); + } else { + int xstatus; + wait(&xstatus); + if (xstatus != 0) + exit(1); + } + } - memset(fa, 0, sizeof(fa)); - fd = open(".", 0); - n = 0; - while(read(fd, &de, sizeof(de)) > 0){ - if(de.inum == 0) - continue; - if(de.name[0] == 'C' && de.name[2] == '\0'){ - i = de.name[1] - '0'; - if(i < 0 || i >= sizeof(fa)){ - printf("%s: concreate weird file %s\n", s, de.name); - exit(1); - } - if(fa[i]){ - printf("%s: concreate duplicate file %s\n", s, de.name); - exit(1); - } - fa[i] = 1; - n++; - } - } - close(fd); + memset(fa, 0, sizeof(fa)); + fd = open(".", 0); + n = 0; + while (read(fd, &de, sizeof(de)) > 0) { + if (de.inum == 0) + continue; + if (de.name[0] == 'C' && de.name[2] == '\0') { + i = de.name[1] - '0'; + if (i < 0 || i >= sizeof(fa)) { + printf("%s: concreate weird file %s\n", s, de.name); + exit(1); + } + if (fa[i]) { + printf("%s: concreate duplicate file %s\n", s, de.name); + exit(1); + } + fa[i] = 1; + n++; + } + } + close(fd); - if(n != N){ - printf("%s: concreate not enough files in directory listing\n", s); - exit(1); - } + if (n != N) { + printf("%s: concreate not enough files in directory listing\n", s); + exit(1); + } - for(i = 0; i < N; i++){ - file[1] = '0' + i; - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(((i % 3) == 0 && pid == 0) || - ((i % 3) == 1 && pid != 0)){ - close(open(file, 0)); - close(open(file, 0)); - close(open(file, 0)); - close(open(file, 0)); - close(open(file, 0)); - close(open(file, 0)); - } else { - unlink(file); - unlink(file); - unlink(file); - unlink(file); - unlink(file); - unlink(file); - } - if(pid == 0) - exit(0); - else - wait(0); - } + for (i = 0; i < N; i++) { + file[1] = '0' + i; + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (((i % 3) == 0 && pid == 0) || ((i % 3) == 1 && pid != 0)) { + close(open(file, 0)); + close(open(file, 0)); + close(open(file, 0)); + close(open(file, 0)); + close(open(file, 0)); + close(open(file, 0)); + } else { + unlink(file); + unlink(file); + unlink(file); + unlink(file); + unlink(file); + unlink(file); + } + if (pid == 0) + exit(0); + else + wait(0); + } } // another concurrent link/unlink/create test, // to look for deadlocks. -void -linkunlink(char *s) -{ - int pid, i; +void linkunlink(char *s) { + int pid, i; - unlink("x"); - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } + unlink("x"); + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } - unsigned int x = (pid ? 1 : 97); - for(i = 0; i < 100; i++){ - x = x * 1103515245 + 12345; - if((x % 3) == 0){ - close(open("x", O_RDWR | O_CREATE)); - } else if((x % 3) == 1){ - link("cat", "x"); - } else { - unlink("x"); - } - } + unsigned int x = (pid ? 1 : 97); + for (i = 0; i < 100; i++) { + x = x * 1103515245 + 12345; + if ((x % 3) == 0) { + close(open("x", O_RDWR | O_CREATE)); + } else if ((x % 3) == 1) { + link("cat", "x"); + } else { + unlink("x"); + } + } - if(pid) - wait(0); - else - exit(0); + if (pid) + wait(0); + else + exit(0); } +void subdir(char *s) { + int fd, cc; -void -subdir(char *s) -{ - int fd, cc; + unlink("ff"); + if (mkdir("dd") != 0) { + printf("%s: mkdir dd failed\n", s); + exit(1); + } - unlink("ff"); - if(mkdir("dd") != 0){ - printf("%s: mkdir dd failed\n", s); - exit(1); - } + fd = open("dd/ff", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: create dd/ff failed\n", s); + exit(1); + } + write(fd, "ff", 2); + close(fd); - fd = open("dd/ff", O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: create dd/ff failed\n", s); - exit(1); - } - write(fd, "ff", 2); - close(fd); + if (unlink("dd") >= 0) { + printf("%s: unlink dd (non-empty dir) succeeded!\n", s); + exit(1); + } - if(unlink("dd") >= 0){ - printf("%s: unlink dd (non-empty dir) succeeded!\n", s); - exit(1); - } + if (mkdir("/dd/dd") != 0) { + printf("subdir mkdir dd/dd failed\n", s); + exit(1); + } - if(mkdir("/dd/dd") != 0){ - printf("subdir mkdir dd/dd failed\n", s); - exit(1); - } + fd = open("dd/dd/ff", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: create dd/dd/ff failed\n", s); + exit(1); + } + write(fd, "FF", 2); + close(fd); - fd = open("dd/dd/ff", O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: create dd/dd/ff failed\n", s); - exit(1); - } - write(fd, "FF", 2); - close(fd); + fd = open("dd/dd/../ff", 0); + if (fd < 0) { + printf("%s: open dd/dd/../ff failed\n", s); + exit(1); + } + cc = read(fd, buf, sizeof(buf)); + if (cc != 2 || buf[0] != 'f') { + printf("%s: dd/dd/../ff wrong content\n", s); + exit(1); + } + close(fd); - fd = open("dd/dd/../ff", 0); - if(fd < 0){ - printf("%s: open dd/dd/../ff failed\n", s); - exit(1); - } - cc = read(fd, buf, sizeof(buf)); - if(cc != 2 || buf[0] != 'f'){ - printf("%s: dd/dd/../ff wrong content\n", s); - exit(1); - } - close(fd); + if (link("dd/dd/ff", "dd/dd/ffff") != 0) { + printf("link dd/dd/ff dd/dd/ffff failed\n", s); + exit(1); + } - if(link("dd/dd/ff", "dd/dd/ffff") != 0){ - printf("link dd/dd/ff dd/dd/ffff failed\n", s); - exit(1); - } + if (unlink("dd/dd/ff") != 0) { + printf("%s: unlink dd/dd/ff failed\n", s); + exit(1); + } + if (open("dd/dd/ff", O_RDONLY) >= 0) { + printf("%s: open (unlinked) dd/dd/ff succeeded\n", s); + exit(1); + } - if(unlink("dd/dd/ff") != 0){ - printf("%s: unlink dd/dd/ff failed\n", s); - exit(1); - } - if(open("dd/dd/ff", O_RDONLY) >= 0){ - printf("%s: open (unlinked) dd/dd/ff succeeded\n", s); - exit(1); - } + if (chdir("dd") != 0) { + printf("%s: chdir dd failed\n", s); + exit(1); + } + if (chdir("dd/../../dd") != 0) { + printf("%s: chdir dd/../../dd failed\n", s); + exit(1); + } + if (chdir("dd/../../../dd") != 0) { + printf("chdir dd/../../dd failed\n", s); + exit(1); + } + if (chdir("./..") != 0) { + printf("%s: chdir ./.. failed\n", s); + exit(1); + } - if(chdir("dd") != 0){ - printf("%s: chdir dd failed\n", s); - exit(1); - } - if(chdir("dd/../../dd") != 0){ - printf("%s: chdir dd/../../dd failed\n", s); - exit(1); - } - if(chdir("dd/../../../dd") != 0){ - printf("chdir dd/../../dd failed\n", s); - exit(1); - } - if(chdir("./..") != 0){ - printf("%s: chdir ./.. failed\n", s); - exit(1); - } + fd = open("dd/dd/ffff", 0); + if (fd < 0) { + printf("%s: open dd/dd/ffff failed\n", s); + exit(1); + } + if (read(fd, buf, sizeof(buf)) != 2) { + printf("%s: read dd/dd/ffff wrong len\n", s); + exit(1); + } + close(fd); - fd = open("dd/dd/ffff", 0); - if(fd < 0){ - printf("%s: open dd/dd/ffff failed\n", s); - exit(1); - } - if(read(fd, buf, sizeof(buf)) != 2){ - printf("%s: read dd/dd/ffff wrong len\n", s); - exit(1); - } - close(fd); + if (open("dd/dd/ff", O_RDONLY) >= 0) { + printf("%s: open (unlinked) dd/dd/ff succeeded!\n", s); + exit(1); + } - if(open("dd/dd/ff", O_RDONLY) >= 0){ - printf("%s: open (unlinked) dd/dd/ff succeeded!\n", s); - exit(1); - } + if (open("dd/ff/ff", O_CREATE | O_RDWR) >= 0) { + printf("%s: create dd/ff/ff succeeded!\n", s); + exit(1); + } + if (open("dd/xx/ff", O_CREATE | O_RDWR) >= 0) { + printf("%s: create dd/xx/ff succeeded!\n", s); + exit(1); + } + if (open("dd", O_CREATE) >= 0) { + printf("%s: create dd succeeded!\n", s); + exit(1); + } + if (open("dd", O_RDWR) >= 0) { + printf("%s: open dd rdwr succeeded!\n", s); + exit(1); + } + if (open("dd", O_WRONLY) >= 0) { + printf("%s: open dd wronly succeeded!\n", s); + exit(1); + } + if (link("dd/ff/ff", "dd/dd/xx") == 0) { + printf("%s: link dd/ff/ff dd/dd/xx succeeded!\n", s); + exit(1); + } + if (link("dd/xx/ff", "dd/dd/xx") == 0) { + printf("%s: link dd/xx/ff dd/dd/xx succeeded!\n", s); + exit(1); + } + if (link("dd/ff", "dd/dd/ffff") == 0) { + printf("%s: link dd/ff dd/dd/ffff succeeded!\n", s); + exit(1); + } + if (mkdir("dd/ff/ff") == 0) { + printf("%s: mkdir dd/ff/ff succeeded!\n", s); + exit(1); + } + if (mkdir("dd/xx/ff") == 0) { + printf("%s: mkdir dd/xx/ff succeeded!\n", s); + exit(1); + } + if (mkdir("dd/dd/ffff") == 0) { + printf("%s: mkdir dd/dd/ffff succeeded!\n", s); + exit(1); + } + if (unlink("dd/xx/ff") == 0) { + printf("%s: unlink dd/xx/ff succeeded!\n", s); + exit(1); + } + if (unlink("dd/ff/ff") == 0) { + printf("%s: unlink dd/ff/ff succeeded!\n", s); + exit(1); + } + if (chdir("dd/ff") == 0) { + printf("%s: chdir dd/ff succeeded!\n", s); + exit(1); + } + if (chdir("dd/xx") == 0) { + printf("%s: chdir dd/xx succeeded!\n", s); + exit(1); + } - if(open("dd/ff/ff", O_CREATE|O_RDWR) >= 0){ - printf("%s: create dd/ff/ff succeeded!\n", s); - exit(1); - } - if(open("dd/xx/ff", O_CREATE|O_RDWR) >= 0){ - printf("%s: create dd/xx/ff succeeded!\n", s); - exit(1); - } - if(open("dd", O_CREATE) >= 0){ - printf("%s: create dd succeeded!\n", s); - exit(1); - } - if(open("dd", O_RDWR) >= 0){ - printf("%s: open dd rdwr succeeded!\n", s); - exit(1); - } - if(open("dd", O_WRONLY) >= 0){ - printf("%s: open dd wronly succeeded!\n", s); - exit(1); - } - if(link("dd/ff/ff", "dd/dd/xx") == 0){ - printf("%s: link dd/ff/ff dd/dd/xx succeeded!\n", s); - exit(1); - } - if(link("dd/xx/ff", "dd/dd/xx") == 0){ - printf("%s: link dd/xx/ff dd/dd/xx succeeded!\n", s); - exit(1); - } - if(link("dd/ff", "dd/dd/ffff") == 0){ - printf("%s: link dd/ff dd/dd/ffff succeeded!\n", s); - exit(1); - } - if(mkdir("dd/ff/ff") == 0){ - printf("%s: mkdir dd/ff/ff succeeded!\n", s); - exit(1); - } - if(mkdir("dd/xx/ff") == 0){ - printf("%s: mkdir dd/xx/ff succeeded!\n", s); - exit(1); - } - if(mkdir("dd/dd/ffff") == 0){ - printf("%s: mkdir dd/dd/ffff succeeded!\n", s); - exit(1); - } - if(unlink("dd/xx/ff") == 0){ - printf("%s: unlink dd/xx/ff succeeded!\n", s); - exit(1); - } - if(unlink("dd/ff/ff") == 0){ - printf("%s: unlink dd/ff/ff succeeded!\n", s); - exit(1); - } - if(chdir("dd/ff") == 0){ - printf("%s: chdir dd/ff succeeded!\n", s); - exit(1); - } - if(chdir("dd/xx") == 0){ - printf("%s: chdir dd/xx succeeded!\n", s); - exit(1); - } - - if(unlink("dd/dd/ffff") != 0){ - printf("%s: unlink dd/dd/ff failed\n", s); - exit(1); - } - if(unlink("dd/ff") != 0){ - printf("%s: unlink dd/ff failed\n", s); - exit(1); - } - if(unlink("dd") == 0){ - printf("%s: unlink non-empty dd succeeded!\n", s); - exit(1); - } - if(unlink("dd/dd") < 0){ - printf("%s: unlink dd/dd failed\n", s); - exit(1); - } - if(unlink("dd") < 0){ - printf("%s: unlink dd failed\n", s); - exit(1); - } + if (unlink("dd/dd/ffff") != 0) { + printf("%s: unlink dd/dd/ff failed\n", s); + exit(1); + } + if (unlink("dd/ff") != 0) { + printf("%s: unlink dd/ff failed\n", s); + exit(1); + } + if (unlink("dd") == 0) { + printf("%s: unlink non-empty dd succeeded!\n", s); + exit(1); + } + if (unlink("dd/dd") < 0) { + printf("%s: unlink dd/dd failed\n", s); + exit(1); + } + if (unlink("dd") < 0) { + printf("%s: unlink dd failed\n", s); + exit(1); + } } // test writes that are larger than the log. -void -bigwrite(char *s) -{ - int fd, sz; +void bigwrite(char *s) { + int fd, sz; - unlink("bigwrite"); - for(sz = 499; sz < (MAXOPBLOCKS+2)*BSIZE; sz += 471){ - fd = open("bigwrite", O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: cannot create bigwrite\n", s); - exit(1); - } - int i; - for(i = 0; i < 2; i++){ - int cc = write(fd, buf, sz); - if(cc != sz){ - printf("%s: write(%d) ret %d\n", s, sz, cc); - exit(1); - } - } - close(fd); - unlink("bigwrite"); - } + unlink("bigwrite"); + for (sz = 499; sz < (MAXOPBLOCKS + 2) * BSIZE; sz += 471) { + fd = open("bigwrite", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: cannot create bigwrite\n", s); + exit(1); + } + int i; + for (i = 0; i < 2; i++) { + int cc = write(fd, buf, sz); + if (cc != sz) { + printf("%s: write(%d) ret %d\n", s, sz, cc); + exit(1); + } + } + close(fd); + unlink("bigwrite"); + } } +void bigfile(char *s) { + enum { N = 20, SZ = 600 }; + int fd, i, total, cc; -void -bigfile(char *s) -{ - enum { N = 20, SZ=600 }; - int fd, i, total, cc; + unlink("bigfile.dat"); + fd = open("bigfile.dat", O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: cannot create bigfile", s); + exit(1); + } + for (i = 0; i < N; i++) { + memset(buf, i, SZ); + if (write(fd, buf, SZ) != SZ) { + printf("%s: write bigfile failed\n", s); + exit(1); + } + } + close(fd); - unlink("bigfile.dat"); - fd = open("bigfile.dat", O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: cannot create bigfile", s); - exit(1); - } - for(i = 0; i < N; i++){ - memset(buf, i, SZ); - if(write(fd, buf, SZ) != SZ){ - printf("%s: write bigfile failed\n", s); - exit(1); - } - } - close(fd); - - fd = open("bigfile.dat", 0); - if(fd < 0){ - printf("%s: cannot open bigfile\n", s); - exit(1); - } - total = 0; - for(i = 0; ; i++){ - cc = read(fd, buf, SZ/2); - if(cc < 0){ - printf("%s: read bigfile failed\n", s); - exit(1); - } - if(cc == 0) - break; - if(cc != SZ/2){ - printf("%s: short read bigfile\n", s); - exit(1); - } - if(buf[0] != i/2 || buf[SZ/2-1] != i/2){ - printf("%s: read bigfile wrong data\n", s); - exit(1); - } - total += cc; - } - close(fd); - if(total != N*SZ){ - printf("%s: read bigfile wrong total\n", s); - exit(1); - } - unlink("bigfile.dat"); + fd = open("bigfile.dat", 0); + if (fd < 0) { + printf("%s: cannot open bigfile\n", s); + exit(1); + } + total = 0; + for (i = 0;; i++) { + cc = read(fd, buf, SZ / 2); + if (cc < 0) { + printf("%s: read bigfile failed\n", s); + exit(1); + } + if (cc == 0) + break; + if (cc != SZ / 2) { + printf("%s: short read bigfile\n", s); + exit(1); + } + if (buf[0] != i / 2 || buf[SZ / 2 - 1] != i / 2) { + printf("%s: read bigfile wrong data\n", s); + exit(1); + } + total += cc; + } + close(fd); + if (total != N * SZ) { + printf("%s: read bigfile wrong total\n", s); + exit(1); + } + unlink("bigfile.dat"); } -void -fourteen(char *s) -{ - int fd; +void fourteen(char *s) { + int fd; - // DIRSIZ is 14. + // DIRSIZ is 14. - if(mkdir("12345678901234") != 0){ - printf("%s: mkdir 12345678901234 failed\n", s); - exit(1); - } - if(mkdir("12345678901234/123456789012345") != 0){ - printf("%s: mkdir 12345678901234/123456789012345 failed\n", s); - exit(1); - } - fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); - if(fd < 0){ - printf("%s: create 123456789012345/123456789012345/123456789012345 failed\n", s); - exit(1); - } - close(fd); - fd = open("12345678901234/12345678901234/12345678901234", 0); - if(fd < 0){ - printf("%s: open 12345678901234/12345678901234/12345678901234 failed\n", s); - exit(1); - } - close(fd); + if (mkdir("12345678901234") != 0) { + printf("%s: mkdir 12345678901234 failed\n", s); + exit(1); + } + if (mkdir("12345678901234/123456789012345") != 0) { + printf("%s: mkdir 12345678901234/123456789012345 failed\n", s); + exit(1); + } + fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); + if (fd < 0) { + printf("%s: create 123456789012345/123456789012345/123456789012345 " + "failed\n", + s); + exit(1); + } + close(fd); + fd = open("12345678901234/12345678901234/12345678901234", 0); + if (fd < 0) { + printf("%s: open 12345678901234/12345678901234/12345678901234 failed\n", + s); + exit(1); + } + close(fd); - if(mkdir("12345678901234/12345678901234") == 0){ - printf("%s: mkdir 12345678901234/12345678901234 succeeded!\n", s); - exit(1); - } - if(mkdir("123456789012345/12345678901234") == 0){ - printf("%s: mkdir 12345678901234/123456789012345 succeeded!\n", s); - exit(1); - } + if (mkdir("12345678901234/12345678901234") == 0) { + printf("%s: mkdir 12345678901234/12345678901234 succeeded!\n", s); + exit(1); + } + if (mkdir("123456789012345/12345678901234") == 0) { + printf("%s: mkdir 12345678901234/123456789012345 succeeded!\n", s); + exit(1); + } - // clean up - unlink("123456789012345/12345678901234"); - unlink("12345678901234/12345678901234"); - unlink("12345678901234/12345678901234/12345678901234"); - unlink("123456789012345/123456789012345/123456789012345"); - unlink("12345678901234/123456789012345"); - unlink("12345678901234"); + // clean up + unlink("123456789012345/12345678901234"); + unlink("12345678901234/12345678901234"); + unlink("12345678901234/12345678901234/12345678901234"); + unlink("123456789012345/123456789012345/123456789012345"); + unlink("12345678901234/123456789012345"); + unlink("12345678901234"); } -void -rmdot(char *s) -{ - if(mkdir("dots") != 0){ - printf("%s: mkdir dots failed\n", s); - exit(1); - } - if(chdir("dots") != 0){ - printf("%s: chdir dots failed\n", s); - exit(1); - } - if(unlink(".") == 0){ - printf("%s: rm . worked!\n", s); - exit(1); - } - if(unlink("..") == 0){ - printf("%s: rm .. worked!\n", s); - exit(1); - } - if(chdir("/") != 0){ - printf("%s: chdir / failed\n", s); - exit(1); - } - if(unlink("dots/.") == 0){ - printf("%s: unlink dots/. worked!\n", s); - exit(1); - } - if(unlink("dots/..") == 0){ - printf("%s: unlink dots/.. worked!\n", s); - exit(1); - } - if(unlink("dots") != 0){ - printf("%s: unlink dots failed!\n", s); - exit(1); - } +void rmdot(char *s) { + if (mkdir("dots") != 0) { + printf("%s: mkdir dots failed\n", s); + exit(1); + } + if (chdir("dots") != 0) { + printf("%s: chdir dots failed\n", s); + exit(1); + } + if (unlink(".") == 0) { + printf("%s: rm . worked!\n", s); + exit(1); + } + if (unlink("..") == 0) { + printf("%s: rm .. worked!\n", s); + exit(1); + } + if (chdir("/") != 0) { + printf("%s: chdir / failed\n", s); + exit(1); + } + if (unlink("dots/.") == 0) { + printf("%s: unlink dots/. worked!\n", s); + exit(1); + } + if (unlink("dots/..") == 0) { + printf("%s: unlink dots/.. worked!\n", s); + exit(1); + } + if (unlink("dots") != 0) { + printf("%s: unlink dots failed!\n", s); + exit(1); + } } -void -dirfile(char *s) -{ - int fd; +void dirfile(char *s) { + int fd; - fd = open("dirfile", O_CREATE); - if(fd < 0){ - printf("%s: create dirfile failed\n", s); - exit(1); - } - close(fd); - if(chdir("dirfile") == 0){ - printf("%s: chdir dirfile succeeded!\n", s); - exit(1); - } - fd = open("dirfile/xx", 0); - if(fd >= 0){ - printf("%s: create dirfile/xx succeeded!\n", s); - exit(1); - } - fd = open("dirfile/xx", O_CREATE); - if(fd >= 0){ - printf("%s: create dirfile/xx succeeded!\n", s); - exit(1); - } - if(mkdir("dirfile/xx") == 0){ - printf("%s: mkdir dirfile/xx succeeded!\n", s); - exit(1); - } - if(unlink("dirfile/xx") == 0){ - printf("%s: unlink dirfile/xx succeeded!\n", s); - exit(1); - } - if(link("README", "dirfile/xx") == 0){ - printf("%s: link to dirfile/xx succeeded!\n", s); - exit(1); - } - if(unlink("dirfile") != 0){ - printf("%s: unlink dirfile failed!\n", s); - exit(1); - } + fd = open("dirfile", O_CREATE); + if (fd < 0) { + printf("%s: create dirfile failed\n", s); + exit(1); + } + close(fd); + if (chdir("dirfile") == 0) { + printf("%s: chdir dirfile succeeded!\n", s); + exit(1); + } + fd = open("dirfile/xx", 0); + if (fd >= 0) { + printf("%s: create dirfile/xx succeeded!\n", s); + exit(1); + } + fd = open("dirfile/xx", O_CREATE); + if (fd >= 0) { + printf("%s: create dirfile/xx succeeded!\n", s); + exit(1); + } + if (mkdir("dirfile/xx") == 0) { + printf("%s: mkdir dirfile/xx succeeded!\n", s); + exit(1); + } + if (unlink("dirfile/xx") == 0) { + printf("%s: unlink dirfile/xx succeeded!\n", s); + exit(1); + } + if (link("README", "dirfile/xx") == 0) { + printf("%s: link to dirfile/xx succeeded!\n", s); + exit(1); + } + if (unlink("dirfile") != 0) { + printf("%s: unlink dirfile failed!\n", s); + exit(1); + } - fd = open(".", O_RDWR); - if(fd >= 0){ - printf("%s: open . for writing succeeded!\n", s); - exit(1); - } - fd = open(".", 0); - if(write(fd, "x", 1) > 0){ - printf("%s: write . succeeded!\n", s); - exit(1); - } - close(fd); + fd = open(".", O_RDWR); + if (fd >= 0) { + printf("%s: open . for writing succeeded!\n", s); + exit(1); + } + fd = open(".", 0); + if (write(fd, "x", 1) > 0) { + printf("%s: write . succeeded!\n", s); + exit(1); + } + close(fd); } // test that iput() is called at the end of _namei(). // also tests empty file names. -void -iref(char *s) -{ - int i, fd; +void iref(char *s) { + int i, fd; - for(i = 0; i < NINODE + 1; i++){ - if(mkdir("irefd") != 0){ - printf("%s: mkdir irefd failed\n", s); - exit(1); - } - if(chdir("irefd") != 0){ - printf("%s: chdir irefd failed\n", s); - exit(1); - } + for (i = 0; i < NINODE + 1; i++) { + if (mkdir("irefd") != 0) { + printf("%s: mkdir irefd failed\n", s); + exit(1); + } + if (chdir("irefd") != 0) { + printf("%s: chdir irefd failed\n", s); + exit(1); + } - mkdir(""); - link("README", ""); - fd = open("", O_CREATE); - if(fd >= 0) - close(fd); - fd = open("xx", O_CREATE); - if(fd >= 0) - close(fd); - unlink("xx"); - } + mkdir(""); + link("README", ""); + fd = open("", O_CREATE); + if (fd >= 0) + close(fd); + fd = open("xx", O_CREATE); + if (fd >= 0) + close(fd); + unlink("xx"); + } - // clean up - for(i = 0; i < NINODE + 1; i++){ - chdir(".."); - unlink("irefd"); - } + // clean up + for (i = 0; i < NINODE + 1; i++) { + chdir(".."); + unlink("irefd"); + } - chdir("/"); + chdir("/"); } // test that fork fails gracefully // the forktest binary also does this, but it runs out of proc entries first. // inside the bigger usertests binary, we run out of memory first. -void -forktest(char *s) -{ - enum{ N = 1000 }; - int n, pid; +void forktest(char *s) { + enum { N = 1000 }; + int n, pid; - for(n=0; n 0; n--){ - if(wait(0) < 0){ - printf("%s: wait stopped early\n", s); - exit(1); - } - } + for (; n > 0; n--) { + if (wait(0) < 0) { + printf("%s: wait stopped early\n", s); + exit(1); + } + } - if(wait(0) != -1){ - printf("%s: wait got too many\n", s); - exit(1); - } + if (wait(0) != -1) { + printf("%s: wait got too many\n", s); + exit(1); + } } -void -sbrkbasic(char *s) -{ - enum { TOOMUCH=1024*1024*1024}; - int i, pid, xstatus; - char *c, *a, *b; +void sbrkbasic(char *s) { + enum { TOOMUCH = 1024 * 1024 * 1024 }; + int i, pid, xstatus; + char *c, *a, *b; - // does sbrk() return the expected failure value? - pid = fork(); - if(pid < 0){ - printf("fork failed in sbrkbasic\n"); - exit(1); - } - if(pid == 0){ - a = sbrk(TOOMUCH); - if(a == (char*)0xffffffffffffffffL){ - // it's OK if this fails. - exit(0); - } - - for(b = a; b < a+TOOMUCH; b += 4096){ - *b = 99; - } - - // we should not get here! either sbrk(TOOMUCH) - // should have failed, or (with lazy allocation) - // a pagefault should have killed this process. - exit(1); - } + // does sbrk() return the expected failure value? + pid = fork(); + if (pid < 0) { + printf("fork failed in sbrkbasic\n"); + exit(1); + } + if (pid == 0) { + a = sbrk(TOOMUCH); + if (a == (char *)0xffffffffffffffffL) { + // it's OK if this fails. + exit(0); + } - wait(&xstatus); - if(xstatus == 1){ - printf("%s: too much memory allocated!\n", s); - exit(1); - } + for (b = a; b < a + TOOMUCH; b += 4096) { + *b = 99; + } - // can one sbrk() less than a page? - a = sbrk(0); - for(i = 0; i < 5000; i++){ - b = sbrk(1); - if(b != a){ - printf("%s: sbrk test failed %d %x %x\n", s, i, a, b); - exit(1); - } - *b = 1; - a = b + 1; - } - pid = fork(); - if(pid < 0){ - printf("%s: sbrk test fork failed\n", s); - exit(1); - } - c = sbrk(1); - c = sbrk(1); - if(c != a + 1){ - printf("%s: sbrk test failed post-fork\n", s); - exit(1); - } - if(pid == 0) - exit(0); - wait(&xstatus); - exit(xstatus); + // we should not get here! either sbrk(TOOMUCH) + // should have failed, or (with lazy allocation) + // a pagefault should have killed this process. + exit(1); + } + + wait(&xstatus); + if (xstatus == 1) { + printf("%s: too much memory allocated!\n", s); + exit(1); + } + + // can one sbrk() less than a page? + a = sbrk(0); + for (i = 0; i < 5000; i++) { + b = sbrk(1); + if (b != a) { + printf("%s: sbrk test failed %d %x %x\n", s, i, a, b); + exit(1); + } + *b = 1; + a = b + 1; + } + pid = fork(); + if (pid < 0) { + printf("%s: sbrk test fork failed\n", s); + exit(1); + } + c = sbrk(1); + c = sbrk(1); + if (c != a + 1) { + printf("%s: sbrk test failed post-fork\n", s); + exit(1); + } + if (pid == 0) + exit(0); + wait(&xstatus); + exit(xstatus); } -void -sbrkmuch(char *s) -{ - enum { BIG=100*1024*1024 }; - char *c, *oldbrk, *a, *lastaddr, *p; - uint64 amt; +void sbrkmuch(char *s) { + enum { BIG = 100 * 1024 * 1024 }; + char *c, *oldbrk, *a, *lastaddr, *p; + uint64 amt; - oldbrk = sbrk(0); + oldbrk = sbrk(0); - // can one grow address space to something big? - a = sbrk(0); - amt = BIG - (uint64)a; - p = sbrk(amt); - if (p != a) { - printf("%s: sbrk test failed to grow big address space; enough phys mem?\n", s); - exit(1); - } + // can one grow address space to something big? + a = sbrk(0); + amt = BIG - (uint64)a; + p = sbrk(amt); + if (p != a) { + printf("%s: sbrk test failed to grow big address space; enough phys " + "mem?\n", + s); + exit(1); + } - // touch each page to make sure it exists. - char *eee = sbrk(0); - for(char *pp = a; pp < eee; pp += 4096) - *pp = 1; + // touch each page to make sure it exists. + char *eee = sbrk(0); + for (char *pp = a; pp < eee; pp += 4096) + *pp = 1; - lastaddr = (char*) (BIG-1); - *lastaddr = 99; + lastaddr = (char *)(BIG - 1); + *lastaddr = 99; - // can one de-allocate? - a = sbrk(0); - c = sbrk(-PGSIZE); - if(c == (char*)0xffffffffffffffffL){ - printf("%s: sbrk could not deallocate\n", s); - exit(1); - } - c = sbrk(0); - if(c != a - PGSIZE){ - printf("%s: sbrk deallocation produced wrong address, a %x c %x\n", s, a, c); - exit(1); - } + // can one de-allocate? + a = sbrk(0); + c = sbrk(-PGSIZE); + if (c == (char *)0xffffffffffffffffL) { + printf("%s: sbrk could not deallocate\n", s); + exit(1); + } + c = sbrk(0); + if (c != a - PGSIZE) { + printf("%s: sbrk deallocation produced wrong address, a %x c %x\n", s, + a, c); + exit(1); + } - // can one re-allocate that page? - a = sbrk(0); - c = sbrk(PGSIZE); - if(c != a || sbrk(0) != a + PGSIZE){ - printf("%s: sbrk re-allocation failed, a %x c %x\n", s, a, c); - exit(1); - } - if(*lastaddr == 99){ - // should be zero - printf("%s: sbrk de-allocation didn't really deallocate\n", s); - exit(1); - } + // can one re-allocate that page? + a = sbrk(0); + c = sbrk(PGSIZE); + if (c != a || sbrk(0) != a + PGSIZE) { + printf("%s: sbrk re-allocation failed, a %x c %x\n", s, a, c); + exit(1); + } + if (*lastaddr == 99) { + // should be zero + printf("%s: sbrk de-allocation didn't really deallocate\n", s); + exit(1); + } - a = sbrk(0); - c = sbrk(-(sbrk(0) - oldbrk)); - if(c != a){ - printf("%s: sbrk downsize failed, a %x c %x\n", s, a, c); - exit(1); - } + a = sbrk(0); + c = sbrk(-(sbrk(0) - oldbrk)); + if (c != a) { + printf("%s: sbrk downsize failed, a %x c %x\n", s, a, c); + exit(1); + } } // can we read the kernel's memory? -void -kernmem(char *s) -{ - char *a; - int pid; +void kernmem(char *s) { + char *a; + int pid; - for(a = (char*)(KERNBASE); a < (char*) (KERNBASE+2000000); a += 50000){ - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid == 0){ - printf("%s: oops could read %x = %x\n", s, a, *a); - exit(1); - } - int xstatus; - wait(&xstatus); - if(xstatus != -1) // did kernel kill child? - exit(1); - } + for (a = (char *)(KERNBASE); a < (char *)(KERNBASE + 2000000); a += 50000) { + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid == 0) { + printf("%s: oops could read %x = %x\n", s, a, *a); + exit(1); + } + int xstatus; + wait(&xstatus); + if (xstatus != -1) // did kernel kill child? + exit(1); + } } // user code should not be able to write to addresses above MAXVA. -void -MAXVAplus(char *s) -{ - volatile uint64 a = MAXVA; - for( ; a != 0; a <<= 1){ - int pid; - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid == 0){ - *(char*)a = 99; - printf("%s: oops wrote %x\n", s, a); - exit(1); - } - int xstatus; - wait(&xstatus); - if(xstatus != -1) // did kernel kill child? - exit(1); - } +void MAXVAplus(char *s) { + volatile uint64 a = MAXVA; + for (; a != 0; a <<= 1) { + int pid; + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid == 0) { + *(char *)a = 99; + printf("%s: oops wrote %x\n", s, a); + exit(1); + } + int xstatus; + wait(&xstatus); + if (xstatus != -1) // did kernel kill child? + exit(1); + } } // if we run the system out of memory, does it clean up the last // failed allocation? -void -sbrkfail(char *s) -{ - enum { BIG=100*1024*1024 }; - int i, xstatus; - int fds[2]; - char scratch; - char *c, *a; - int pids[10]; - int pid; - - if(pipe(fds) != 0){ - printf("%s: pipe() failed\n", s); - exit(1); - } - for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ - if((pids[i] = fork()) == 0){ - // allocate a lot of memory - sbrk(BIG - (uint64)sbrk(0)); - write(fds[1], "x", 1); - // sit around until killed - for(;;) sleep(1000); - } - if(pids[i] != -1) - read(fds[0], &scratch, 1); - } +void sbrkfail(char *s) { + enum { BIG = 100 * 1024 * 1024 }; + int i, xstatus; + int fds[2]; + char scratch; + char *c, *a; + int pids[10]; + int pid; - // if those failed allocations freed up the pages they did allocate, - // we'll be able to allocate here - c = sbrk(PGSIZE); - for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ - if(pids[i] == -1) - continue; - kill(pids[i]); - wait(0); - } - if(c == (char*)0xffffffffffffffffL){ - printf("%s: failed sbrk leaked memory\n", s); - exit(1); - } + if (pipe(fds) != 0) { + printf("%s: pipe() failed\n", s); + exit(1); + } + for (i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) { + if ((pids[i] = fork()) == 0) { + // allocate a lot of memory + sbrk(BIG - (uint64)sbrk(0)); + write(fds[1], "x", 1); + // sit around until killed + for (;;) + sleep(1000); + } + if (pids[i] != -1) + read(fds[0], &scratch, 1); + } - // test running fork with the above allocated page - pid = fork(); - if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - if(pid == 0){ - // allocate a lot of memory. - // this should produce a page fault, - // and thus not complete. - a = sbrk(0); - sbrk(10*BIG); - int n = 0; - for (i = 0; i < 10*BIG; i += PGSIZE) { - n += *(a+i); - } - // print n so the compiler doesn't optimize away - // the for loop. - printf("%s: allocate a lot of memory succeeded %d\n", s, n); - exit(1); - } - wait(&xstatus); - if(xstatus != -1 && xstatus != 2) - exit(1); + // if those failed allocations freed up the pages they did allocate, + // we'll be able to allocate here + c = sbrk(PGSIZE); + for (i = 0; i < sizeof(pids) / sizeof(pids[0]); i++) { + if (pids[i] == -1) + continue; + kill(pids[i]); + wait(0); + } + if (c == (char *)0xffffffffffffffffL) { + printf("%s: failed sbrk leaked memory\n", s); + exit(1); + } + + // test running fork with the above allocated page + pid = fork(); + if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + if (pid == 0) { + // allocate a lot of memory. + // this should produce a page fault, + // and thus not complete. + a = sbrk(0); + sbrk(10 * BIG); + int n = 0; + for (i = 0; i < 10 * BIG; i += PGSIZE) { + n += *(a + i); + } + // print n so the compiler doesn't optimize away + // the for loop. + printf("%s: allocate a lot of memory succeeded %d\n", s, n); + exit(1); + } + wait(&xstatus); + if (xstatus != -1 && xstatus != 2) + exit(1); } - // test reads/writes from/to allocated memory -void -sbrkarg(char *s) -{ - char *a; - int fd, n; +void sbrkarg(char *s) { + char *a; + int fd, n; - a = sbrk(PGSIZE); - fd = open("sbrk", O_CREATE|O_WRONLY); - unlink("sbrk"); - if(fd < 0) { - printf("%s: open sbrk failed\n", s); - exit(1); - } - if ((n = write(fd, a, PGSIZE)) < 0) { - printf("%s: write sbrk failed\n", s); - exit(1); - } - close(fd); + a = sbrk(PGSIZE); + fd = open("sbrk", O_CREATE | O_WRONLY); + unlink("sbrk"); + if (fd < 0) { + printf("%s: open sbrk failed\n", s); + exit(1); + } + if ((n = write(fd, a, PGSIZE)) < 0) { + printf("%s: write sbrk failed\n", s); + exit(1); + } + close(fd); - // test writes to allocated memory - a = sbrk(PGSIZE); - if(pipe((int *) a) != 0){ - printf("%s: pipe() failed\n", s); - exit(1); - } + // test writes to allocated memory + a = sbrk(PGSIZE); + if (pipe((int *)a) != 0) { + printf("%s: pipe() failed\n", s); + exit(1); + } } -void -validatetest(char *s) -{ - int hi; - uint64 p; +void validatetest(char *s) { + int hi; + uint64 p; - hi = 1100*1024; - for(p = 0; p <= (uint)hi; p += PGSIZE){ - // try to crash the kernel by passing in a bad string pointer - if(link("nosuchfile", (char*)p) != -1){ - printf("%s: link should not succeed\n", s); - exit(1); - } - } + hi = 1100 * 1024; + for (p = 0; p <= (uint)hi; p += PGSIZE) { + // try to crash the kernel by passing in a bad string pointer + if (link("nosuchfile", (char *)p) != -1) { + printf("%s: link should not succeed\n", s); + exit(1); + } + } } // does uninitialized data start out zero? char uninit[10000]; -void -bsstest(char *s) -{ - int i; +void bsstest(char *s) { + int i; - for(i = 0; i < sizeof(uninit); i++){ - if(uninit[i] != '\0'){ - printf("%s: bss test failed\n", s); - exit(1); - } - } + for (i = 0; i < sizeof(uninit); i++) { + if (uninit[i] != '\0') { + printf("%s: bss test failed\n", s); + exit(1); + } + } } // does exec return an error if the arguments // are larger than a page? or does it write // below the stack and wreck the instructions/data? -void -bigargtest(char *s) -{ - int pid, fd, xstatus; +void bigargtest(char *s) { + int pid, fd, xstatus; - unlink("bigarg-ok"); - pid = fork(); - if(pid == 0){ - static char *args[MAXARG]; - int i; - for(i = 0; i < MAXARG-1; i++) - args[i] = "bigargs test: failed\n "; - args[MAXARG-1] = 0; - exec("echo", args); - fd = open("bigarg-ok", O_CREATE); - close(fd); - exit(0); - } else if(pid < 0){ - printf("%s: bigargtest: fork failed\n", s); - exit(1); - } - - wait(&xstatus); - if(xstatus != 0) - exit(xstatus); - fd = open("bigarg-ok", 0); - if(fd < 0){ - printf("%s: bigarg test failed!\n", s); - exit(1); - } - close(fd); + unlink("bigarg-ok"); + pid = fork(); + if (pid == 0) { + static char *args[MAXARG]; + int i; + for (i = 0; i < MAXARG - 1; i++) + args[i] = "bigargs test: failed\n " + " " + " " + " "; + args[MAXARG - 1] = 0; + exec("echo", args); + fd = open("bigarg-ok", O_CREATE); + close(fd); + exit(0); + } else if (pid < 0) { + printf("%s: bigargtest: fork failed\n", s); + exit(1); + } + + wait(&xstatus); + if (xstatus != 0) + exit(xstatus); + fd = open("bigarg-ok", 0); + if (fd < 0) { + printf("%s: bigarg test failed!\n", s); + exit(1); + } + close(fd); } // what happens when the file system runs out of blocks? // answer: balloc panics, so this test is not useful. -void -fsfull() -{ - int nfiles; - int fsblocks = 0; +void fsfull() { + int nfiles; + int fsblocks = 0; - printf("fsfull test\n"); + printf("fsfull test\n"); - for(nfiles = 0; ; nfiles++){ - char name[64]; - name[0] = 'f'; - name[1] = '0' + nfiles / 1000; - name[2] = '0' + (nfiles % 1000) / 100; - name[3] = '0' + (nfiles % 100) / 10; - name[4] = '0' + (nfiles % 10); - name[5] = '\0'; - printf("writing %s\n", name); - int fd = open(name, O_CREATE|O_RDWR); - if(fd < 0){ - printf("open %s failed\n", name); - break; - } - int total = 0; - while(1){ - int cc = write(fd, buf, BSIZE); - if(cc < BSIZE) - break; - total += cc; - fsblocks++; - } - printf("wrote %d bytes\n", total); - close(fd); - if(total == 0) - break; - } + for (nfiles = 0;; nfiles++) { + char name[64]; + name[0] = 'f'; + name[1] = '0' + nfiles / 1000; + name[2] = '0' + (nfiles % 1000) / 100; + name[3] = '0' + (nfiles % 100) / 10; + name[4] = '0' + (nfiles % 10); + name[5] = '\0'; + printf("writing %s\n", name); + int fd = open(name, O_CREATE | O_RDWR); + if (fd < 0) { + printf("open %s failed\n", name); + break; + } + int total = 0; + while (1) { + int cc = write(fd, buf, BSIZE); + if (cc < BSIZE) + break; + total += cc; + fsblocks++; + } + printf("wrote %d bytes\n", total); + close(fd); + if (total == 0) + break; + } - while(nfiles >= 0){ - char name[64]; - name[0] = 'f'; - name[1] = '0' + nfiles / 1000; - name[2] = '0' + (nfiles % 1000) / 100; - name[3] = '0' + (nfiles % 100) / 10; - name[4] = '0' + (nfiles % 10); - name[5] = '\0'; - unlink(name); - nfiles--; - } + while (nfiles >= 0) { + char name[64]; + name[0] = 'f'; + name[1] = '0' + nfiles / 1000; + name[2] = '0' + (nfiles % 1000) / 100; + name[3] = '0' + (nfiles % 100) / 10; + name[4] = '0' + (nfiles % 10); + name[5] = '\0'; + unlink(name); + nfiles--; + } - printf("fsfull test finished\n"); + printf("fsfull test finished\n"); } -void argptest(char *s) -{ - int fd; - fd = open("init", O_RDONLY); - if (fd < 0) { - printf("%s: open failed\n", s); - exit(1); - } - read(fd, sbrk(0) - 1, -1); - close(fd); +void argptest(char *s) { + int fd; + fd = open("init", O_RDONLY); + if (fd < 0) { + printf("%s: open failed\n", s); + exit(1); + } + read(fd, sbrk(0) - 1, -1); + close(fd); } // check that there's an invalid page beneath // the user stack, to catch stack overflow. -void -stacktest(char *s) -{ - int pid; - int xstatus; - - pid = fork(); - if(pid == 0) { - char *sp = (char *) r_sp(); - sp -= PGSIZE; - // the *sp should cause a trap. - printf("%s: stacktest: read below stack %p\n", s, *sp); - exit(1); - } else if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - wait(&xstatus); - if(xstatus == -1) // kernel killed child? - exit(0); - else - exit(xstatus); +void stacktest(char *s) { + int pid; + int xstatus; + + pid = fork(); + if (pid == 0) { + char *sp = (char *)r_sp(); + sp -= PGSIZE; + // the *sp should cause a trap. + printf("%s: stacktest: read below stack %p\n", s, *sp); + exit(1); + } else if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + wait(&xstatus); + if (xstatus == -1) // kernel killed child? + exit(0); + else + exit(xstatus); } // check that writes to text segment fault -void -textwrite(char *s) -{ - int pid; - int xstatus; - - pid = fork(); - if(pid == 0) { - volatile int *addr = (int *) 0; - *addr = 10; - exit(1); - } else if(pid < 0){ - printf("%s: fork failed\n", s); - exit(1); - } - wait(&xstatus); - if(xstatus == -1) // kernel killed child? - exit(0); - else - exit(xstatus); +void textwrite(char *s) { + int pid; + int xstatus; + + pid = fork(); + if (pid == 0) { + volatile int *addr = (int *)0; + *addr = 10; + exit(1); + } else if (pid < 0) { + printf("%s: fork failed\n", s); + exit(1); + } + wait(&xstatus); + if (xstatus == -1) // kernel killed child? + exit(0); + else + exit(xstatus); } // regression test. copyin(), copyout(), and copyinstr() used to cast // the virtual page address to uint, which (with certain wild system // call arguments) resulted in a kernel page faults. -void *big = (void*) 0xeaeb0b5b00002f5e; -void -pgbug(char *s) -{ - char *argv[1]; - argv[0] = 0; - exec(big, argv); - pipe(big); +void *big = (void *)0xeaeb0b5b00002f5e; +void pgbug(char *s) { + char *argv[1]; + argv[0] = 0; + exec(big, argv); + pipe(big); - exit(0); + exit(0); } // regression test. does the kernel panic if a process sbrk()s its // size to be less than a page, or zero, or reduces the break by an // amount too small to cause a page to be freed? -void -sbrkbugs(char *s) -{ - int pid = fork(); - if(pid < 0){ - printf("fork failed\n"); - exit(1); - } - if(pid == 0){ - int sz = (uint64) sbrk(0); - // free all user memory; there used to be a bug that - // would not adjust p->sz correctly in this case, - // causing exit() to panic. - sbrk(-sz); - // user page fault here. - exit(0); - } - wait(0); +void sbrkbugs(char *s) { + int pid = fork(); + if (pid < 0) { + printf("fork failed\n"); + exit(1); + } + if (pid == 0) { + int sz = (uint64)sbrk(0); + // free all user memory; there used to be a bug that + // would not adjust p->sz correctly in this case, + // causing exit() to panic. + sbrk(-sz); + // user page fault here. + exit(0); + } + wait(0); - pid = fork(); - if(pid < 0){ - printf("fork failed\n"); - exit(1); - } - if(pid == 0){ - int sz = (uint64) sbrk(0); - // set the break to somewhere in the very first - // page; there used to be a bug that would incorrectly - // free the first page. - sbrk(-(sz - 3500)); - exit(0); - } - wait(0); + pid = fork(); + if (pid < 0) { + printf("fork failed\n"); + exit(1); + } + if (pid == 0) { + int sz = (uint64)sbrk(0); + // set the break to somewhere in the very first + // page; there used to be a bug that would incorrectly + // free the first page. + sbrk(-(sz - 3500)); + exit(0); + } + wait(0); - pid = fork(); - if(pid < 0){ - printf("fork failed\n"); - exit(1); - } - if(pid == 0){ - // set the break in the middle of a page. - sbrk((10*4096 + 2048) - (uint64)sbrk(0)); + pid = fork(); + if (pid < 0) { + printf("fork failed\n"); + exit(1); + } + if (pid == 0) { + // set the break in the middle of a page. + sbrk((10 * 4096 + 2048) - (uint64)sbrk(0)); - // reduce the break a bit, but not enough to - // cause a page to be freed. this used to cause - // a panic. - sbrk(-10); + // reduce the break a bit, but not enough to + // cause a page to be freed. this used to cause + // a panic. + sbrk(-10); - exit(0); - } - wait(0); + exit(0); + } + wait(0); - exit(0); + exit(0); } // if process size was somewhat more than a page boundary, and then // shrunk to be somewhat less than that page boundary, can the kernel // still copyin() from addresses in the last page? -void -sbrklast(char *s) -{ - uint64 top = (uint64) sbrk(0); - if((top % 4096) != 0) - sbrk(4096 - (top % 4096)); - sbrk(4096); - sbrk(10); - sbrk(-20); - top = (uint64) sbrk(0); - char *p = (char *) (top - 64); - p[0] = 'x'; - p[1] = '\0'; - int fd = open(p, O_RDWR|O_CREATE); - write(fd, p, 1); - close(fd); - fd = open(p, O_RDWR); - p[0] = '\0'; - read(fd, p, 1); - if(p[0] != 'x') - exit(1); +void sbrklast(char *s) { + uint64 top = (uint64)sbrk(0); + if ((top % 4096) != 0) + sbrk(4096 - (top % 4096)); + sbrk(4096); + sbrk(10); + sbrk(-20); + top = (uint64)sbrk(0); + char *p = (char *)(top - 64); + p[0] = 'x'; + p[1] = '\0'; + int fd = open(p, O_RDWR | O_CREATE); + write(fd, p, 1); + close(fd); + fd = open(p, O_RDWR); + p[0] = '\0'; + read(fd, p, 1); + if (p[0] != 'x') + exit(1); } - // does sbrk handle signed int32 wrap-around with // negative arguments? -void -sbrk8000(char *s) -{ - sbrk(0x80000004); - volatile char *top = sbrk(0); - *(top-1) = *(top-1) + 1; +void sbrk8000(char *s) { + sbrk(0x80000004); + volatile char *top = sbrk(0); + *(top - 1) = *(top - 1) + 1; } - - // regression test. test whether exec() leaks memory if one of the // arguments is invalid. the test passes if the kernel doesn't panic. -void -badarg(char *s) -{ - for(int i = 0; i < 50000; i++){ - char *argv[2]; - argv[0] = (char*)0xffffffff; - argv[1] = 0; - exec("echo", argv); - } - - exit(0); +void badarg(char *s) { + for (int i = 0; i < 50000; i++) { + char *argv[2]; + argv[0] = (char *)0xffffffff; + argv[1] = 0; + exec("echo", argv); + } + + exit(0); } struct test { - void (*f)(char *); - char *s; + void (*f)(char *); + char *s; } quicktests[] = { - {copyin, "copyin"}, - {copyout, "copyout"}, - {copyinstr1, "copyinstr1"}, - {copyinstr2, "copyinstr2"}, - {copyinstr3, "copyinstr3"}, - {rwsbrk, "rwsbrk" }, - {truncate1, "truncate1"}, - {truncate2, "truncate2"}, - {truncate3, "truncate3"}, - {openiputtest, "openiput"}, - {exitiputtest, "exitiput"}, - {iputtest, "iput"}, - {opentest, "opentest"}, - {writetest, "writetest"}, - {writebig, "writebig"}, - {createtest, "createtest"}, - {dirtest, "dirtest"}, - {exectest, "exectest"}, - {pipe1, "pipe1"}, - {killstatus, "killstatus"}, - {preempt, "preempt"}, - {exitwait, "exitwait"}, - {reparent, "reparent" }, - {twochildren, "twochildren"}, - {forkfork, "forkfork"}, - {forkforkfork, "forkforkfork"}, - {reparent2, "reparent2"}, - {mem, "mem"}, - {sharedfd, "sharedfd"}, - {fourfiles, "fourfiles"}, - {createdelete, "createdelete"}, - {unlinkread, "unlinkread"}, - {linktest, "linktest"}, - {concreate, "concreate"}, - {linkunlink, "linkunlink"}, - {subdir, "subdir"}, - {bigwrite, "bigwrite"}, - {bigfile, "bigfile"}, - {fourteen, "fourteen"}, - {rmdot, "rmdot"}, - {dirfile, "dirfile"}, - {iref, "iref"}, - {forktest, "forktest"}, - {sbrkbasic, "sbrkbasic"}, - {sbrkmuch, "sbrkmuch"}, - {kernmem, "kernmem"}, - {MAXVAplus, "MAXVAplus"}, - {sbrkfail, "sbrkfail"}, - {sbrkarg, "sbrkarg"}, - {validatetest, "validatetest"}, - {bsstest, "bsstest"}, - {bigargtest, "bigargtest"}, - {argptest, "argptest"}, - {stacktest, "stacktest"}, - {textwrite, "textwrite"}, - {pgbug, "pgbug" }, - {sbrkbugs, "sbrkbugs" }, - {sbrklast, "sbrklast"}, - {sbrk8000, "sbrk8000"}, - {badarg, "badarg" }, + {copyin, "copyin"}, + {copyout, "copyout"}, + {copyinstr1, "copyinstr1"}, + {copyinstr2, "copyinstr2"}, + {copyinstr3, "copyinstr3"}, + {rwsbrk, "rwsbrk"}, + {truncate1, "truncate1"}, + {truncate2, "truncate2"}, + {truncate3, "truncate3"}, + {openiputtest, "openiput"}, + {exitiputtest, "exitiput"}, + {iputtest, "iput"}, + {opentest, "opentest"}, + {writetest, "writetest"}, + {writebig, "writebig"}, + {createtest, "createtest"}, + {dirtest, "dirtest"}, + {exectest, "exectest"}, + {pipe1, "pipe1"}, + {killstatus, "killstatus"}, + {preempt, "preempt"}, + {exitwait, "exitwait"}, + {reparent, "reparent"}, + {twochildren, "twochildren"}, + {forkfork, "forkfork"}, + {forkforkfork, "forkforkfork"}, + {reparent2, "reparent2"}, + {mem, "mem"}, + {sharedfd, "sharedfd"}, + {fourfiles, "fourfiles"}, + {createdelete, "createdelete"}, + {unlinkread, "unlinkread"}, + {linktest, "linktest"}, + {concreate, "concreate"}, + {linkunlink, "linkunlink"}, + {subdir, "subdir"}, + {bigwrite, "bigwrite"}, + {bigfile, "bigfile"}, + {fourteen, "fourteen"}, + {rmdot, "rmdot"}, + {dirfile, "dirfile"}, + {iref, "iref"}, + {forktest, "forktest"}, + {sbrkbasic, "sbrkbasic"}, + {sbrkmuch, "sbrkmuch"}, + {kernmem, "kernmem"}, + {MAXVAplus, "MAXVAplus"}, + {sbrkfail, "sbrkfail"}, + {sbrkarg, "sbrkarg"}, + {validatetest, "validatetest"}, + {bsstest, "bsstest"}, + {bigargtest, "bigargtest"}, + {argptest, "argptest"}, + {stacktest, "stacktest"}, + {textwrite, "textwrite"}, + {pgbug, "pgbug"}, + {sbrkbugs, "sbrkbugs"}, + {sbrklast, "sbrklast"}, + {sbrk8000, "sbrk8000"}, + {badarg, "badarg"}, - { 0, 0}, + {0, 0}, }; // @@ -2644,98 +2524,94 @@ struct test { // // directory that uses indirect blocks -void -bigdir(char *s) -{ - enum { N = 500 }; - int i, fd; - char name[10]; +void bigdir(char *s) { + enum { N = 500 }; + int i, fd; + char name[10]; - unlink("bd"); + unlink("bd"); - fd = open("bd", O_CREATE); - if(fd < 0){ - printf("%s: bigdir create failed\n", s); - exit(1); - } - close(fd); + fd = open("bd", O_CREATE); + if (fd < 0) { + printf("%s: bigdir create failed\n", s); + exit(1); + } + close(fd); - for(i = 0; i < N; i++){ - name[0] = 'x'; - name[1] = '0' + (i / 64); - name[2] = '0' + (i % 64); - name[3] = '\0'; - if(link("bd", name) != 0){ - printf("%s: bigdir link(bd, %s) failed\n", s, name); - exit(1); - } - } + for (i = 0; i < N; i++) { + name[0] = 'x'; + name[1] = '0' + (i / 64); + name[2] = '0' + (i % 64); + name[3] = '\0'; + if (link("bd", name) != 0) { + printf("%s: bigdir link(bd, %s) failed\n", s, name); + exit(1); + } + } - unlink("bd"); - for(i = 0; i < N; i++){ - name[0] = 'x'; - name[1] = '0' + (i / 64); - name[2] = '0' + (i % 64); - name[3] = '\0'; - if(unlink(name) != 0){ - printf("%s: bigdir unlink failed", s); - exit(1); - } - } + unlink("bd"); + for (i = 0; i < N; i++) { + name[0] = 'x'; + name[1] = '0' + (i / 64); + name[2] = '0' + (i % 64); + name[3] = '\0'; + if (unlink(name) != 0) { + printf("%s: bigdir unlink failed", s); + exit(1); + } + } } // concurrent writes to try to provoke deadlock in the virtio disk // driver. -void -manywrites(char *s) -{ - int nchildren = 4; - int howmany = 30; // increase to look for deadlock - - for(int ci = 0; ci < nchildren; ci++){ - int pid = fork(); - if(pid < 0){ - printf("fork failed\n"); - exit(1); - } +void manywrites(char *s) { + int nchildren = 4; + int howmany = 30; // increase to look for deadlock - if(pid == 0){ - char name[3]; - name[0] = 'b'; - name[1] = 'a' + ci; - name[2] = '\0'; - unlink(name); - - for(int iters = 0; iters < howmany; iters++){ - for(int i = 0; i < ci+1; i++){ - int fd = open(name, O_CREATE | O_RDWR); - if(fd < 0){ - printf("%s: cannot create %s\n", s, name); - exit(1); - } - int sz = sizeof(buf); - int cc = write(fd, buf, sz); - if(cc != sz){ - printf("%s: write(%d) ret %d\n", s, sz, cc); - exit(1); - } - close(fd); - } - unlink(name); - } + for (int ci = 0; ci < nchildren; ci++) { + int pid = fork(); + if (pid < 0) { + printf("fork failed\n"); + exit(1); + } - unlink(name); - exit(0); - } - } + if (pid == 0) { + char name[3]; + name[0] = 'b'; + name[1] = 'a' + ci; + name[2] = '\0'; + unlink(name); - for(int ci = 0; ci < nchildren; ci++){ - int st = 0; - wait(&st); - if(st != 0) - exit(st); - } - exit(0); + for (int iters = 0; iters < howmany; iters++) { + for (int i = 0; i < ci + 1; i++) { + int fd = open(name, O_CREATE | O_RDWR); + if (fd < 0) { + printf("%s: cannot create %s\n", s, name); + exit(1); + } + int sz = sizeof(buf); + int cc = write(fd, buf, sz); + if (cc != sz) { + printf("%s: write(%d) ret %d\n", s, sz, cc); + exit(1); + } + close(fd); + } + unlink(name); + } + + unlink(name); + exit(0); + } + } + + for (int ci = 0; ci < nchildren; ci++) { + int st = 0; + wait(&st); + if (st != 0) + exit(st); + } + exit(0); } // regression test. does write() with an invalid buffer pointer cause @@ -2743,196 +2619,188 @@ manywrites(char *s) // file is deleted? if the kernel has this bug, it will panic: balloc: // out of blocks. assumed_free may need to be raised to be more than // the number of free blocks. this test takes a long time. -void -badwrite(char *s) -{ - int assumed_free = 600; - - unlink("junk"); - for(int i = 0; i < assumed_free; i++){ - int fd = open("junk", O_CREATE|O_WRONLY); - if(fd < 0){ - printf("open junk failed\n"); - exit(1); - } - write(fd, (char*)0xffffffffffL, 1); - close(fd); - unlink("junk"); - } +void badwrite(char *s) { + int assumed_free = 600; - int fd = open("junk", O_CREATE|O_WRONLY); - if(fd < 0){ - printf("open junk failed\n"); - exit(1); - } - if(write(fd, "x", 1) != 1){ - printf("write failed\n"); - exit(1); - } - close(fd); - unlink("junk"); + unlink("junk"); + for (int i = 0; i < assumed_free; i++) { + int fd = open("junk", O_CREATE | O_WRONLY); + if (fd < 0) { + printf("open junk failed\n"); + exit(1); + } + write(fd, (char *)0xffffffffffL, 1); + close(fd); + unlink("junk"); + } - exit(0); + int fd = open("junk", O_CREATE | O_WRONLY); + if (fd < 0) { + printf("open junk failed\n"); + exit(1); + } + if (write(fd, "x", 1) != 1) { + printf("write failed\n"); + exit(1); + } + close(fd); + unlink("junk"); + + exit(0); } // test the exec() code that cleans up if it runs out // of memory. it's really a test that such a condition // doesn't cause a panic. -void -execout(char *s) -{ - for(int avail = 0; avail < 15; avail++){ - int pid = fork(); - if(pid < 0){ - printf("fork failed\n"); - exit(1); - } else if(pid == 0){ - // allocate all of memory. - while(1){ - uint64 a = (uint64) sbrk(4096); - if(a == 0xffffffffffffffffLL) - break; - *(char*)(a + 4096 - 1) = 1; - } +void execout(char *s) { + for (int avail = 0; avail < 15; avail++) { + int pid = fork(); + if (pid < 0) { + printf("fork failed\n"); + exit(1); + } else if (pid == 0) { + // allocate all of memory. + while (1) { + uint64 a = (uint64)sbrk(4096); + if (a == 0xffffffffffffffffLL) + break; + *(char *)(a + 4096 - 1) = 1; + } - // free a few pages, in order to let exec() make some - // progress. - for(int i = 0; i < avail; i++) - sbrk(-4096); - - close(1); - char *args[] = { "echo", "x", 0 }; - exec("echo", args); - exit(0); - } else { - wait((int*)0); - } - } + // free a few pages, in order to let exec() make some + // progress. + for (int i = 0; i < avail; i++) + sbrk(-4096); - exit(0); + close(1); + char *args[] = {"echo", "x", 0}; + exec("echo", args); + exit(0); + } else { + wait((int *)0); + } + } + + exit(0); } // can the kernel tolerate running out of disk space? -void -diskfull(char *s) -{ - int fi; - int done = 0; +void diskfull(char *s) { + int fi; + int done = 0; - unlink("diskfulldir"); - - for(fi = 0; done == 0; fi++){ - char name[32]; - name[0] = 'b'; - name[1] = 'i'; - name[2] = 'g'; - name[3] = '0' + fi; - name[4] = '\0'; - unlink(name); - int fd = open(name, O_CREATE|O_RDWR|O_TRUNC); - if(fd < 0){ - // oops, ran out of inodes before running out of blocks. - printf("%s: could not create file %s\n", s, name); - done = 1; - break; - } - for(int i = 0; i < MAXFILE; i++){ - char buf[BSIZE]; - if(write(fd, buf, BSIZE) != BSIZE){ - done = 1; - close(fd); - break; - } - } - close(fd); - } + unlink("diskfulldir"); - // now that there are no free blocks, test that dirlink() - // merely fails (doesn't panic) if it can't extend - // directory content. one of these file creations - // is expected to fail. - int nzz = 128; - for(int i = 0; i < nzz; i++){ - char name[32]; - name[0] = 'z'; - name[1] = 'z'; - name[2] = '0' + (i / 32); - name[3] = '0' + (i % 32); - name[4] = '\0'; - unlink(name); - int fd = open(name, O_CREATE|O_RDWR|O_TRUNC); - if(fd < 0) - break; - close(fd); - } + for (fi = 0; done == 0; fi++) { + char name[32]; + name[0] = 'b'; + name[1] = 'i'; + name[2] = 'g'; + name[3] = '0' + fi; + name[4] = '\0'; + unlink(name); + int fd = open(name, O_CREATE | O_RDWR | O_TRUNC); + if (fd < 0) { + // oops, ran out of inodes before running out of blocks. + printf("%s: could not create file %s\n", s, name); + done = 1; + break; + } + for (int i = 0; i < MAXFILE; i++) { + char buf[BSIZE]; + if (write(fd, buf, BSIZE) != BSIZE) { + done = 1; + close(fd); + break; + } + } + close(fd); + } - // this mkdir() is expected to fail. - if(mkdir("diskfulldir") == 0) - printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n"); + // now that there are no free blocks, test that dirlink() + // merely fails (doesn't panic) if it can't extend + // directory content. one of these file creations + // is expected to fail. + int nzz = 128; + for (int i = 0; i < nzz; i++) { + char name[32]; + name[0] = 'z'; + name[1] = 'z'; + name[2] = '0' + (i / 32); + name[3] = '0' + (i % 32); + name[4] = '\0'; + unlink(name); + int fd = open(name, O_CREATE | O_RDWR | O_TRUNC); + if (fd < 0) + break; + close(fd); + } - unlink("diskfulldir"); + // this mkdir() is expected to fail. + if (mkdir("diskfulldir") == 0) + printf("%s: mkdir(diskfulldir) unexpectedly succeeded!\n"); - for(int i = 0; i < nzz; i++){ - char name[32]; - name[0] = 'z'; - name[1] = 'z'; - name[2] = '0' + (i / 32); - name[3] = '0' + (i % 32); - name[4] = '\0'; - unlink(name); - } + unlink("diskfulldir"); - for(int i = 0; i < fi; i++){ - char name[32]; - name[0] = 'b'; - name[1] = 'i'; - name[2] = 'g'; - name[3] = '0' + i; - name[4] = '\0'; - unlink(name); - } + for (int i = 0; i < nzz; i++) { + char name[32]; + name[0] = 'z'; + name[1] = 'z'; + name[2] = '0' + (i / 32); + name[3] = '0' + (i % 32); + name[4] = '\0'; + unlink(name); + } + + for (int i = 0; i < fi; i++) { + char name[32]; + name[0] = 'b'; + name[1] = 'i'; + name[2] = 'g'; + name[3] = '0' + i; + name[4] = '\0'; + unlink(name); + } } -void -outofinodes(char *s) -{ - int nzz = 32*32; - for(int i = 0; i < nzz; i++){ - char name[32]; - name[0] = 'z'; - name[1] = 'z'; - name[2] = '0' + (i / 32); - name[3] = '0' + (i % 32); - name[4] = '\0'; - unlink(name); - int fd = open(name, O_CREATE|O_RDWR|O_TRUNC); - if(fd < 0){ - // failure is eventually expected. - break; - } - close(fd); - } +void outofinodes(char *s) { + int nzz = 32 * 32; + for (int i = 0; i < nzz; i++) { + char name[32]; + name[0] = 'z'; + name[1] = 'z'; + name[2] = '0' + (i / 32); + name[3] = '0' + (i % 32); + name[4] = '\0'; + unlink(name); + int fd = open(name, O_CREATE | O_RDWR | O_TRUNC); + if (fd < 0) { + // failure is eventually expected. + break; + } + close(fd); + } - for(int i = 0; i < nzz; i++){ - char name[32]; - name[0] = 'z'; - name[1] = 'z'; - name[2] = '0' + (i / 32); - name[3] = '0' + (i % 32); - name[4] = '\0'; - unlink(name); - } + for (int i = 0; i < nzz; i++) { + char name[32]; + name[0] = 'z'; + name[1] = 'z'; + name[2] = '0' + (i / 32); + name[3] = '0' + (i % 32); + name[4] = '\0'; + unlink(name); + } } struct test slowtests[] = { - {bigdir, "bigdir"}, - {manywrites, "manywrites"}, - {badwrite, "badwrite" }, - {execout, "execout"}, - {diskfull, "diskfull"}, - {outofinodes, "outofinodes"}, - - { 0, 0}, + {bigdir, "bigdir"}, + {manywrites, "manywrites"}, + {badwrite, "badwrite"}, + {execout, "execout"}, + {diskfull, "diskfull"}, + {outofinodes, "outofinodes"}, + + {0, 0}, }; // @@ -2941,161 +2809,154 @@ struct test slowtests[] = { // run each test in its own process. run returns 1 if child's exit() // indicates success. -int -run(void f(char *), char *s) { - int pid; - int xstatus; +int run(void f(char *), char *s) { + int pid; + int xstatus; - printf("test %s: ", s); - if((pid = fork()) < 0) { - printf("runtest: fork error\n"); - exit(1); - } - if(pid == 0) { - f(s); - exit(0); - } else { - wait(&xstatus); - if(xstatus != 0) - printf("FAILED\n"); - else - printf("OK\n"); - return xstatus == 0; - } + printf("test %s: ", s); + if ((pid = fork()) < 0) { + printf("runtest: fork error\n"); + exit(1); + } + if (pid == 0) { + f(s); + exit(0); + } else { + wait(&xstatus); + if (xstatus != 0) + printf("FAILED\n"); + else + printf("OK\n"); + return xstatus == 0; + } } -int -runtests(struct test *tests, char *justone) { - for (struct test *t = tests; t->s != 0; t++) { - if((justone == 0) || strcmp(t->s, justone) == 0) { - if(!run(t->f, t->s)){ - printf("SOME TESTS FAILED\n"); - return 1; - } - } - } - return 0; +int runtests(struct test *tests, char *justone) { + for (struct test *t = tests; t->s != 0; t++) { + if ((justone == 0) || strcmp(t->s, justone) == 0) { + if (!run(t->f, t->s)) { + printf("SOME TESTS FAILED\n"); + return 1; + } + } + } + return 0; } - // // use sbrk() to count how many free physical memory pages there are. // touches the pages to force allocation. // because out of memory with lazy allocation results in the process // taking a fault and being killed, fork and report back. // -int -countfree() -{ - int fds[2]; +int countfree() { + int fds[2]; - if(pipe(fds) < 0){ - printf("pipe() failed in countfree()\n"); - exit(1); - } - - int pid = fork(); + if (pipe(fds) < 0) { + printf("pipe() failed in countfree()\n"); + exit(1); + } - if(pid < 0){ - printf("fork failed in countfree()\n"); - exit(1); - } + int pid = fork(); - if(pid == 0){ - close(fds[0]); - - while(1){ - uint64 a = (uint64) sbrk(4096); - if(a == 0xffffffffffffffff){ - break; - } + if (pid < 0) { + printf("fork failed in countfree()\n"); + exit(1); + } - // modify the memory to make sure it's really allocated. - *(char *)(a + 4096 - 1) = 1; + if (pid == 0) { + close(fds[0]); - // report back one more page. - if(write(fds[1], "x", 1) != 1){ - printf("write() failed in countfree()\n"); - exit(1); - } - } + while (1) { + uint64 a = (uint64)sbrk(4096); + if (a == 0xffffffffffffffff) { + break; + } - exit(0); - } + // modify the memory to make sure it's really allocated. + *(char *)(a + 4096 - 1) = 1; - close(fds[1]); + // report back one more page. + if (write(fds[1], "x", 1) != 1) { + printf("write() failed in countfree()\n"); + exit(1); + } + } - int n = 0; - while(1){ - char c; - int cc = read(fds[0], &c, 1); - if(cc < 0){ - printf("read() failed in countfree()\n"); - exit(1); - } - if(cc == 0) - break; - n += 1; - } + exit(0); + } - close(fds[0]); - wait((int*)0); - - return n; + close(fds[1]); + + int n = 0; + while (1) { + char c; + int cc = read(fds[0], &c, 1); + if (cc < 0) { + printf("read() failed in countfree()\n"); + exit(1); + } + if (cc == 0) + break; + n += 1; + } + + close(fds[0]); + wait((int *)0); + + return n; } -int -drivetests(int quick, int continuous, char *justone) { - do { - printf("usertests starting\n"); - int free0 = countfree(); - int free1 = 0; - if (runtests(quicktests, justone)) { - if(continuous != 2) { - return 1; - } - } - if(!quick) { - if (justone == 0) - printf("usertests slow tests starting\n"); - if (runtests(slowtests, justone)) { - if(continuous != 2) { - return 1; - } - } - } - if((free1 = countfree()) < free0) { - printf("FAILED -- lost some free pages %d (out of %d)\n", free1, free0); - if(continuous != 2) { - return 1; - } - } - } while(continuous); - return 0; +int drivetests(int quick, int continuous, char *justone) { + do { + printf("usertests starting\n"); + int free0 = countfree(); + int free1 = 0; + if (runtests(quicktests, justone)) { + if (continuous != 2) { + return 1; + } + } + if (!quick) { + if (justone == 0) + printf("usertests slow tests starting\n"); + if (runtests(slowtests, justone)) { + if (continuous != 2) { + return 1; + } + } + } + if ((free1 = countfree()) < free0) { + printf("FAILED -- lost some free pages %d (out of %d)\n", free1, + free0); + if (continuous != 2) { + return 1; + } + } + } while (continuous); + return 0; } -int -main(int argc, char *argv[]) -{ - int continuous = 0; - int quick = 0; - char *justone = 0; +int main(int argc, char *argv[]) { + int continuous = 0; + int quick = 0; + char *justone = 0; - if(argc == 2 && strcmp(argv[1], "-q") == 0){ - quick = 1; - } else if(argc == 2 && strcmp(argv[1], "-c") == 0){ - continuous = 1; - } else if(argc == 2 && strcmp(argv[1], "-C") == 0){ - continuous = 2; - } else if(argc == 2 && argv[1][0] != '-'){ - justone = argv[1]; - } else if(argc > 1){ - printf("Usage: usertests [-c] [-C] [-q] [testname]\n"); - exit(1); - } - if (drivetests(quick, continuous, justone)) { - exit(1); - } - printf("ALL TESTS PASSED\n"); - exit(0); + if (argc == 2 && strcmp(argv[1], "-q") == 0) { + quick = 1; + } else if (argc == 2 && strcmp(argv[1], "-c") == 0) { + continuous = 1; + } else if (argc == 2 && strcmp(argv[1], "-C") == 0) { + continuous = 2; + } else if (argc == 2 && argv[1][0] != '-') { + justone = argv[1]; + } else if (argc > 1) { + printf("Usage: usertests [-c] [-C] [-q] [testname]\n"); + exit(1); + } + if (drivetests(quick, continuous, justone)) { + exit(1); + } + printf("ALL TESTS PASSED\n"); + exit(0); } diff --git a/user/wc.c b/user/wc.c index 6a851ca..cb7d183 100644 --- a/user/wc.c +++ b/user/wc.c @@ -4,51 +4,47 @@ char buf[512]; -void -wc(int fd, char *name) -{ - int i, n; - int l, w, c, inword; +void wc(int fd, char *name) { + int i, n; + int l, w, c, inword; - l = w = c = 0; - inword = 0; - while((n = read(fd, buf, sizeof(buf))) > 0){ - for(i=0; i 0) { + for (i = 0; i < n; i++) { + c++; + if (buf[i] == '\n') + l++; + if (strchr(" \r\t\n\v", buf[i])) + inword = 0; + else if (!inword) { + w++; + inword = 1; + } + } + } + if (n < 0) { + printf("wc: read error\n"); + exit(1); + } + printf("%d %d %d %s\n", l, w, c, name); } -int -main(int argc, char *argv[]) -{ - int fd, i; +int main(int argc, char *argv[]) { + int fd, i; - if(argc <= 1){ - wc(0, ""); - exit(0); - } + if (argc <= 1) { + wc(0, ""); + exit(0); + } - for(i = 1; i < argc; i++){ - if((fd = open(argv[i], 0)) < 0){ - printf("wc: cannot open %s\n", argv[i]); - exit(1); - } - wc(fd, argv[i]); - close(fd); - } - exit(0); + for (i = 1; i < argc; i++) { + if ((fd = open(argv[i], 0)) < 0) { + printf("wc: cannot open %s\n", argv[i]); + exit(1); + } + wc(fd, argv[i]); + close(fd); + } + exit(0); } diff --git a/user/zombie.c b/user/zombie.c index 8b89a33..560dbc5 100644 --- a/user/zombie.c +++ b/user/zombie.c @@ -5,10 +5,8 @@ #include "kernel/stat.h" #include "user/user.h" -int -main(void) -{ - if(fork() > 0) - sleep(5); // Let child exit before parent. - exit(0); +int main(void) { + if (fork() > 0) + sleep(5); // Let child exit before parent. + exit(0); }