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 *
 | 
			
		||||
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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										3
									
								
								usys.S
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue