From 4357207237e074b5a42ee9739eadd040fd1cf296 Mon Sep 17 00:00:00 2001
From: rtm <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<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;
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)
-- 
GitLab