From 4357207237e074b5a42ee9739eadd040fd1cf296 Mon Sep 17 00:00:00 2001 From: rtm Date: Sat, 12 Aug 2006 11:38:57 +0000 Subject: [PATCH] fix getblk to actually lock the block no more cons_put system calls usertests tests two processes writing files --- bio.c | 31 ++++++++----- buf.h | 2 + defs.h | 2 +- init.c | 4 +- sh.c | 5 +- syscall.c | 53 ---------------------- syscall.h | 3 -- ulib.c | 11 +++++ user.h | 3 ++ usertests.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++---- usys.S | 3 -- 11 files changed, 159 insertions(+), 86 deletions(-) diff --git a/bio.c b/bio.c index 2b17a52..7184a28 100644 --- a/bio.c +++ b/bio.c @@ -17,24 +17,31 @@ binit(void) } struct buf * -getblk() +getblk(uint dev, uint sector) { - int i; + struct buf *b; acquire(&buf_table_lock); - // XXX need to lock the block even if not caching, to - // avoid read modify write problems. - while(1){ - for(i = 0; i < NBUF; i++){ - if((buf[i].flags & B_BUSY) == 0){ - buf[i].flags |= B_BUSY; - release(&buf_table_lock); - return buf + i; + for(b = buf; b < buf+NBUF; b++) + if((b->flags & B_BUSY) && b->dev == dev && b->sector) + break; + + if(b < buf+NBUF){ + sleep(buf, &buf_table_lock); + } else { + for(b = buf; b < buf+NBUF; b++){ + if((b->flags & B_BUSY) == 0){ + b->flags |= B_BUSY; + b->dev = dev; + b->sector = sector; + release(&buf_table_lock); + return b; + } } + panic("getblk: no buffers"); } - sleep(buf, &buf_table_lock); } } @@ -45,7 +52,7 @@ bread(uint dev, uint sector) struct buf *b; extern struct spinlock ide_lock; - b = getblk(); + b = getblk(dev, sector); acquire(&ide_lock); c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1); diff --git a/buf.h b/buf.h index a4cea5e..e3f6b14 100644 --- a/buf.h +++ b/buf.h @@ -1,5 +1,7 @@ struct buf { int flags; + uint dev; + uint sector; uchar data[512]; }; #define B_BUSY 0x1 diff --git a/defs.h b/defs.h index 3674c45..f54d829 100644 --- a/defs.h +++ b/defs.h @@ -104,7 +104,7 @@ int ide_finish(void *); // bio.c void binit(void); struct buf; -struct buf *getblk(void); +struct buf * getblk(uint dev, uint sector); struct buf *bread(uint, uint); void bwrite(uint, struct buf *, uint); void brelse(struct buf *); diff --git a/init.c b/init.c index dcd0fda..0a4223c 100644 --- a/init.c +++ b/init.c @@ -17,10 +17,10 @@ main(void) open("console", 1); open("console", 1); - write(1, "init...\n", 8); + puts("init...\n"); while(1){ - write(1, "running sh...\n", 14); + puts("running sh...\n"); pid = fork(); if(pid == 0){ exec("sh", sh_args); diff --git a/sh.c b/sh.c index e9ed2d9..9d4a308 100644 --- a/sh.c +++ b/sh.c @@ -12,7 +12,7 @@ main(void) int pid; while(1){ - write(1, "$ ", 2); + puts("$ "); gets(buf, sizeof(buf)); if(buf[0] == '\0') continue; @@ -21,8 +21,7 @@ main(void) args[0] = buf; args[1] = 0; exec(buf, args); - write(1, buf, strlen(buf)); - write(1, ": not found\n", 12); + printf(1, "%s: not found\n", buf); exit(); } if(pid > 0) diff --git a/syscall.c b/syscall.c index 0f90bd6..48da287 100644 --- a/syscall.c +++ b/syscall.c @@ -214,38 +214,6 @@ sys_kill(void) return proc_kill(pid); } -int -sys_cons_putc(void) -{ - int c; - char buf[2]; - - if(fetcharg(0, &c) < 0) - return -1; - buf[0] = c; - buf[1] = 0; - cprintf("%s", buf); - return 0; -} - -int -sys_cons_puts(void) -{ - char buf[256]; - int i; - uint addr; - struct proc *cp = curproc[cpu()]; - - if(fetcharg(0, &addr) < 0) - return -1; - for(i=0; i= 0; i++) - if(buf[i] == 0) - break; - buf[i] = 0; - cprintf("%s", buf); - return 0; -} - int sys_open(void) { @@ -525,18 +493,6 @@ sys_block(void) return 0; } -int -sys_panic(void) -{ - struct proc *p = curproc[cpu()]; - uint addr; - - if(fetcharg(0, &addr) < 0) - return -1; - panic(p->mem + addr); - return 0; -} - void syscall(void) { @@ -554,9 +510,6 @@ syscall(void) case SYS_wait: ret = sys_wait(); break; - case SYS_cons_putc: - ret = sys_cons_putc(); - break; case SYS_pipe: ret = sys_pipe(); break; @@ -575,12 +528,6 @@ syscall(void) case SYS_kill: ret = sys_kill(); break; - case SYS_panic: - ret = sys_panic(); - break; - case SYS_cons_puts: - ret = sys_cons_puts(); - break; case SYS_exec: ret = sys_exec(); break; diff --git a/syscall.h b/syscall.h index 9924c7f..ca2855c 100644 --- a/syscall.h +++ b/syscall.h @@ -1,15 +1,12 @@ #define SYS_fork 1 #define SYS_exit 2 #define SYS_wait 3 -#define SYS_cons_putc 4 #define SYS_pipe 5 #define SYS_write 6 #define SYS_read 7 #define SYS_close 8 #define SYS_block 9 #define SYS_kill 10 -#define SYS_panic 11 -#define SYS_cons_puts 12 #define SYS_exec 13 #define SYS_open 14 #define SYS_mknod 15 diff --git a/ulib.c b/ulib.c index ccb9fd6..b759f45 100644 --- a/ulib.c +++ b/ulib.c @@ -26,6 +26,17 @@ strlen(char *s) return n; } +void * +memset(void *dst, int c, unsigned int n) +{ + char *d = (char *) dst; + + while(n-- > 0) + *d++ = c; + + return dst; +} + char * gets(char *buf, int max) { diff --git a/user.h b/user.h index d91b4df..9dd1684 100644 --- a/user.h +++ b/user.h @@ -14,9 +14,12 @@ int exec(char *, char **); int open(char *, int); int mknod (char*,short,short,short); int unlink (char*); +struct stat; int fstat (int fd, struct stat *stat); + int puts(char*); char* strcpy(char*, char*); void printf(int fd, char *fmt, ...); char *gets(char *, int max); unsigned int strlen(char *); +void * memset(void *dst, int c, unsigned int n); diff --git a/usertests.c b/usertests.c index cba362f..12fa6f8 100644 --- a/usertests.c +++ b/usertests.c @@ -1,4 +1,5 @@ #include "user.h" +#include "fcntl.h" char buf[2048]; @@ -18,7 +19,7 @@ pipe1(void) for(i = 0; i < 1033; i++) buf[i] = seq++; if(write(fds[1], buf, 1033) != 1033){ - panic("pipe1 oops 1\n"); + printf(1, "pipe1 oops 1\n"); exit(); } } @@ -30,7 +31,7 @@ pipe1(void) while((n = read(fds[0], buf, cc)) > 0){ for(i = 0; i < n; i++){ if((buf[i] & 0xff) != (seq++ & 0xff)){ - panic("pipe1 oops 2\n"); + printf(1, "pipe1 oops 2\n"); return; } } @@ -40,7 +41,7 @@ pipe1(void) cc = sizeof(buf); } if(total != 5 * 1033) - panic("pipe1 oops 3\n"); + printf(1, "pipe1 oops 3\n"); close(fds[0]); wait(); } @@ -69,7 +70,7 @@ preempt(void) if(pid3 == 0){ close(pfds[0]); if(write(pfds[1], "x", 1) != 1) - panic("preempt write error"); + printf(1, "preempt write error"); close(pfds[1]); for(;;) ; @@ -77,7 +78,7 @@ preempt(void) close(pfds[1]); if(read(pfds[0], buf, sizeof(buf)) != 1){ - panic("preempt read error"); + printf(1, "preempt read error"); return; } close(pfds[0]); @@ -99,12 +100,12 @@ exitwait(void) for(i = 0; i < 100; i++){ pid = fork(); if(pid < 0){ - panic("fork failed\n"); + printf(1, "fork failed\n"); return; } if(pid){ if(wait() != pid){ - panic("wait wrong pid\n"); + printf(1, "wait wrong pid\n"); return; } } else { @@ -114,15 +115,124 @@ exitwait(void) puts("exitwait ok\n"); } +// two processes write to the same file descriptor +// is the offset shared? does inode locking work? +void +sharedfd() +{ + int fd, pid, i, n, nc, np; + char buf[10]; + + unlink("sharedfd"); + fd = open("sharedfd", O_CREATE|O_RDWR); + if(fd < 0){ + printf(1, "usertests: cannot open sharedfd for writing"); + return; + } + pid = fork(); + memset(buf, pid==0?'c':'p', sizeof(buf)); + for(i = 0; i < 100; i++){ + if(write(fd, buf, sizeof(buf)) != sizeof(buf)){ + printf(1, "usertests: write sharedfd failed\n"); + break; + } + } + if(pid == 0) + exit(); + else + wait(); + close(fd); + fd = open("sharedfd", 0); + if(fd < 0){ + printf(1, "usertests: cannot open sharedfd for reading\n"); + return; + } + 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); + if(nc == 1000 && np == 1000) + printf(1, "sharedfd ok\n"); + else + printf(1, "sharedfd oops %d %d\n", nc, np); +} + +// two processes write two different files at the same +// time, to test block allocation. +void +twofiles() +{ + int fd, pid, i, j, n, total; + char *fname; + + unlink("f1"); + unlink("f2"); + + pid = fork(); + if(pid < 0){ + puts("fork failed\n"); + return; + } + + fname = pid ? "f1" : "f2"; + fd = open(fname, O_CREATE | O_RDWR); + if(fd < 0){ + puts("create failed\n"); + exit(); + } + + memset(buf, pid?'p':'c', 512); + for(i = 0; i < 12; i++){ + if((n = write(fd, buf, 500)) != 500){ + printf(1, "write failed %d\n", n); + exit(); + } + } + close(fd); + if(pid) + wait(); + else + exit(); + + for(i = 0; i < 2; i++){ + fd = open(i?"f1":"f2", 0); + total = 0; + while((n = read(fd, buf, sizeof(buf))) > 0){ + for(j = 0; j < n; j++){ + if(buf[j] != (i?'p':'c')){ + puts("wrong char\n"); + exit(); + } + } + total += n; + } + close(fd); + if(total != 12*500){ + printf(1, "wrong length %d\n", total); + exit(); + } + } + + puts("twofiles ok\n"); +} + int main(int argc, char *argv[]) { puts("usertests starting\n"); + twofiles(); + sharedfd(); pipe1(); preempt(); exitwait(); - panic("usertests succeeded"); - return 0; + puts("usertests finished\n"); + exit(); } diff --git a/usys.S b/usys.S index aa3a22e..f9565e5 100644 --- a/usys.S +++ b/usys.S @@ -11,15 +11,12 @@ STUB(fork) STUB(exit) STUB(wait) -STUB(cons_putc) STUB(pipe) STUB(read) STUB(write) STUB(close) STUB(block) STUB(kill) -STUB(panic) -STUB(cons_puts) STUB(exec) STUB(open) STUB(mknod)