fix getblk to actually lock the block

no more cons_put system calls
usertests tests two processes writing files
This commit is contained in:
rtm 2006-08-12 11:38:57 +00:00
parent 1f544842ce
commit 4357207237
11 changed files with 159 additions and 86 deletions

33
bio.c
View file

@ -17,24 +17,31 @@ binit(void)
} }
struct buf * struct buf *
getblk() getblk(uint dev, uint sector)
{ {
int i; struct buf *b;
acquire(&buf_table_lock); acquire(&buf_table_lock);
// XXX need to lock the block even if not caching, to
// avoid read modify write problems.
while(1){ while(1){
for(i = 0; i < NBUF; i++){ for(b = buf; b < buf+NBUF; b++)
if((buf[i].flags & B_BUSY) == 0){ if((b->flags & B_BUSY) && b->dev == dev && b->sector)
buf[i].flags |= B_BUSY; break;
release(&buf_table_lock);
return buf + i; if(b < buf+NBUF){
}
}
sleep(buf, &buf_table_lock); 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");
}
} }
} }
@ -45,7 +52,7 @@ bread(uint dev, uint sector)
struct buf *b; struct buf *b;
extern struct spinlock ide_lock; extern struct spinlock ide_lock;
b = getblk(); b = getblk(dev, sector);
acquire(&ide_lock); acquire(&ide_lock);
c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1); c = ide_start_rw(dev & 0xff, sector, b->data, 1, 1);

2
buf.h
View file

@ -1,5 +1,7 @@
struct buf { struct buf {
int flags; int flags;
uint dev;
uint sector;
uchar data[512]; uchar data[512];
}; };
#define B_BUSY 0x1 #define B_BUSY 0x1

2
defs.h
View file

@ -104,7 +104,7 @@ int ide_finish(void *);
// bio.c // bio.c
void binit(void); void binit(void);
struct buf; struct buf;
struct buf *getblk(void); struct buf * getblk(uint dev, uint sector);
struct buf *bread(uint, uint); struct buf *bread(uint, uint);
void bwrite(uint, struct buf *, uint); void bwrite(uint, struct buf *, uint);
void brelse(struct buf *); void brelse(struct buf *);

4
init.c
View file

@ -17,10 +17,10 @@ main(void)
open("console", 1); open("console", 1);
open("console", 1); open("console", 1);
write(1, "init...\n", 8); puts("init...\n");
while(1){ while(1){
write(1, "running sh...\n", 14); puts("running sh...\n");
pid = fork(); pid = fork();
if(pid == 0){ if(pid == 0){
exec("sh", sh_args); exec("sh", sh_args);

5
sh.c
View file

@ -12,7 +12,7 @@ main(void)
int pid; int pid;
while(1){ while(1){
write(1, "$ ", 2); puts("$ ");
gets(buf, sizeof(buf)); gets(buf, sizeof(buf));
if(buf[0] == '\0') if(buf[0] == '\0')
continue; continue;
@ -21,8 +21,7 @@ main(void)
args[0] = buf; args[0] = buf;
args[1] = 0; args[1] = 0;
exec(buf, args); exec(buf, args);
write(1, buf, strlen(buf)); printf(1, "%s: not found\n", buf);
write(1, ": not found\n", 12);
exit(); exit();
} }
if(pid > 0) if(pid > 0)

View file

@ -214,38 +214,6 @@ sys_kill(void)
return proc_kill(pid); 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<sizeof buf-1 && fetchbyte(cp, addr+i, &buf[i]) >= 0; i++)
if(buf[i] == 0)
break;
buf[i] = 0;
cprintf("%s", buf);
return 0;
}
int int
sys_open(void) sys_open(void)
{ {
@ -525,18 +493,6 @@ sys_block(void)
return 0; 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 void
syscall(void) syscall(void)
{ {
@ -554,9 +510,6 @@ syscall(void)
case SYS_wait: case SYS_wait:
ret = sys_wait(); ret = sys_wait();
break; break;
case SYS_cons_putc:
ret = sys_cons_putc();
break;
case SYS_pipe: case SYS_pipe:
ret = sys_pipe(); ret = sys_pipe();
break; break;
@ -575,12 +528,6 @@ syscall(void)
case SYS_kill: case SYS_kill:
ret = sys_kill(); ret = sys_kill();
break; break;
case SYS_panic:
ret = sys_panic();
break;
case SYS_cons_puts:
ret = sys_cons_puts();
break;
case SYS_exec: case SYS_exec:
ret = sys_exec(); ret = sys_exec();
break; break;

View file

@ -1,15 +1,12 @@
#define SYS_fork 1 #define SYS_fork 1
#define SYS_exit 2 #define SYS_exit 2
#define SYS_wait 3 #define SYS_wait 3
#define SYS_cons_putc 4
#define SYS_pipe 5 #define SYS_pipe 5
#define SYS_write 6 #define SYS_write 6
#define SYS_read 7 #define SYS_read 7
#define SYS_close 8 #define SYS_close 8
#define SYS_block 9 #define SYS_block 9
#define SYS_kill 10 #define SYS_kill 10
#define SYS_panic 11
#define SYS_cons_puts 12
#define SYS_exec 13 #define SYS_exec 13
#define SYS_open 14 #define SYS_open 14
#define SYS_mknod 15 #define SYS_mknod 15

11
ulib.c
View file

@ -26,6 +26,17 @@ strlen(char *s)
return n; return n;
} }
void *
memset(void *dst, int c, unsigned int n)
{
char *d = (char *) dst;
while(n-- > 0)
*d++ = c;
return dst;
}
char * char *
gets(char *buf, int max) gets(char *buf, int max)
{ {

3
user.h
View file

@ -14,9 +14,12 @@ int exec(char *, char **);
int open(char *, int); int open(char *, int);
int mknod (char*,short,short,short); int mknod (char*,short,short,short);
int unlink (char*); int unlink (char*);
struct stat;
int fstat (int fd, struct stat *stat); int fstat (int fd, struct stat *stat);
int puts(char*); int puts(char*);
char* strcpy(char*, char*); char* strcpy(char*, char*);
void printf(int fd, char *fmt, ...); void printf(int fd, char *fmt, ...);
char *gets(char *, int max); char *gets(char *, int max);
unsigned int strlen(char *); unsigned int strlen(char *);
void * memset(void *dst, int c, unsigned int n);

View file

@ -1,4 +1,5 @@
#include "user.h" #include "user.h"
#include "fcntl.h"
char buf[2048]; char buf[2048];
@ -18,7 +19,7 @@ pipe1(void)
for(i = 0; i < 1033; i++) for(i = 0; i < 1033; i++)
buf[i] = seq++; buf[i] = seq++;
if(write(fds[1], buf, 1033) != 1033){ if(write(fds[1], buf, 1033) != 1033){
panic("pipe1 oops 1\n"); printf(1, "pipe1 oops 1\n");
exit(); exit();
} }
} }
@ -30,7 +31,7 @@ pipe1(void)
while((n = read(fds[0], buf, cc)) > 0){ while((n = read(fds[0], buf, cc)) > 0){
for(i = 0; i < n; i++){ for(i = 0; i < n; i++){
if((buf[i] & 0xff) != (seq++ & 0xff)){ if((buf[i] & 0xff) != (seq++ & 0xff)){
panic("pipe1 oops 2\n"); printf(1, "pipe1 oops 2\n");
return; return;
} }
} }
@ -40,7 +41,7 @@ pipe1(void)
cc = sizeof(buf); cc = sizeof(buf);
} }
if(total != 5 * 1033) if(total != 5 * 1033)
panic("pipe1 oops 3\n"); printf(1, "pipe1 oops 3\n");
close(fds[0]); close(fds[0]);
wait(); wait();
} }
@ -69,7 +70,7 @@ preempt(void)
if(pid3 == 0){ if(pid3 == 0){
close(pfds[0]); close(pfds[0]);
if(write(pfds[1], "x", 1) != 1) if(write(pfds[1], "x", 1) != 1)
panic("preempt write error"); printf(1, "preempt write error");
close(pfds[1]); close(pfds[1]);
for(;;) for(;;)
; ;
@ -77,7 +78,7 @@ preempt(void)
close(pfds[1]); close(pfds[1]);
if(read(pfds[0], buf, sizeof(buf)) != 1){ if(read(pfds[0], buf, sizeof(buf)) != 1){
panic("preempt read error"); printf(1, "preempt read error");
return; return;
} }
close(pfds[0]); close(pfds[0]);
@ -99,12 +100,12 @@ exitwait(void)
for(i = 0; i < 100; i++){ for(i = 0; i < 100; i++){
pid = fork(); pid = fork();
if(pid < 0){ if(pid < 0){
panic("fork failed\n"); printf(1, "fork failed\n");
return; return;
} }
if(pid){ if(pid){
if(wait() != pid){ if(wait() != pid){
panic("wait wrong pid\n"); printf(1, "wait wrong pid\n");
return; return;
} }
} else { } else {
@ -114,15 +115,124 @@ exitwait(void)
puts("exitwait ok\n"); 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 int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
puts("usertests starting\n"); puts("usertests starting\n");
twofiles();
sharedfd();
pipe1(); pipe1();
preempt(); preempt();
exitwait(); exitwait();
panic("usertests succeeded"); puts("usertests finished\n");
return 0; exit();
} }

3
usys.S
View file

@ -11,15 +11,12 @@
STUB(fork) STUB(fork)
STUB(exit) STUB(exit)
STUB(wait) STUB(wait)
STUB(cons_putc)
STUB(pipe) STUB(pipe)
STUB(read) STUB(read)
STUB(write) STUB(write)
STUB(close) STUB(close)
STUB(block) STUB(block)
STUB(kill) STUB(kill)
STUB(panic)
STUB(cons_puts)
STUB(exec) STUB(exec)
STUB(open) STUB(open)
STUB(mknod) STUB(mknod)