fix getblk to actually lock the block
no more cons_put system calls usertests tests two processes writing files
This commit is contained in:
parent
1f544842ce
commit
4357207237
33
bio.c
33
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
|
2
buf.h
2
buf.h
|
@ -1,5 +1,7 @@
|
|||
struct buf {
|
||||
int flags;
|
||||
uint dev;
|
||||
uint sector;
|
||||
uchar data[512];
|
||||
};
|
||||
#define B_BUSY 0x1
|
||||
|
|
2
defs.h
2
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 *);
|
||||
|
|
4
init.c
4
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);
|
||||
|
|
5
sh.c
5
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)
|
||||
|
|
53
syscall.c
53
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<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
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
11
ulib.c
11
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)
|
||||
{
|
||||
|
|
3
user.h
3
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);
|
||||
|
|
128
usertests.c
128
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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue