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
11 changed files with 159 additions and 86 deletions
33
bio.c
33
bio.c
|
@ -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
2
buf.h
|
@ -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
2
defs.h
|
@ -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
4
init.c
|
@ -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
5
sh.c
|
@ -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)
|
||||||
|
|
53
syscall.c
53
syscall.c
|
@ -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;
|
||||||
|
|
|
@ -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
11
ulib.c
|
@ -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
3
user.h
|
@ -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);
|
||||||
|
|
128
usertests.c
128
usertests.c
|
@ -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
3
usys.S
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue