]> Devi Nivas Git - cs3210-lab1.git/commitdiff
swtch saves callee-saved registers
authorrtm <rtm>
Sat, 1 Jul 2006 21:26:01 +0000 (21:26 +0000)
committerrtm <rtm>
Sat, 1 Jul 2006 21:26:01 +0000 (21:26 +0000)
swtch idles on per-CPU stack, not on calling process's stack
fix pipe bugs
usertest.c tests pipes, fork, exit, close

14 files changed:
Makefile
fd.c
kalloc.c
main.c
mp.c
pipe.c
proc.c
proc.h
syscall.c
syscall.h
trap.c
ulib.c
usertests.c
x86.h

index 0b716b43b492cdb5751858c449ae91add6f3d2a5..f82d260d731de34ad35dcf2d4c097a858c3838f3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ CC = i386-jos-elf-gcc
 LD = i386-jos-elf-ld
 OBJCOPY = i386-jos-elf-objcopy
 OBJDUMP = i386-jos-elf-objdump
-CFLAGS = -nostdinc -I. -O -Wall -MD
+CFLAGS = -nostdinc -I. -O2 -Wall -MD
 
 xv6.img : bootblock kernel
        dd if=/dev/zero of=xv6.img count=10000
diff --git a/fd.c b/fd.c
index 0546cef4a9a2f96bc2dd292d323a88d830d7cac2..8b5960533a8b357793ce89801701dce92327835f 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -37,19 +37,6 @@ fd_alloc()
   return 0;
 }
 
-void
-fd_close(struct fd *fd)
-{
-  if(fd->type == FD_CLOSED || fd->count <= 0)
-    panic("fd_close");
-  fd->count -= 1;
-  if(fd->count == 0){
-    if(fd->type == FD_PIPE)
-      pipe_close(fd->pipe, fd->writeable);
-    fd->type = FD_CLOSED;
-  }
-}
-
 /*
  * addr is a kernel address, pointing into some process's p->mem.
  */
@@ -78,3 +65,20 @@ fd_read(struct fd *fd, char *addr, int n)
     return -1;
   }
 }
+
+void
+fd_close(struct fd *fd)
+{
+  if(fd->count < 1 || fd->type == FD_CLOSED)
+    panic("fd_close");
+  fd->count -= 1;
+
+  if(fd->count == 0){
+    if(fd->type == FD_PIPE){
+      pipe_close(fd->pipe, fd->writeable);
+    } else {
+      panic("fd_close");
+    }
+    fd->type = FD_CLOSED;
+  }
+}
index 5ea38fdd6e454f2d9a256a7dedecce54619a0189..1944508eaa4ad677c6c9bfa84f12846366a6365e 100644 (file)
--- a/kalloc.c
+++ b/kalloc.c
@@ -45,10 +45,15 @@ kfree(char *cp, int len)
   struct run **rr;
   struct run *p = (struct run *) cp;
   struct run *pend = (struct run *) (cp + len);
+  int i;
 
   if(len % PAGE)
     panic("kfree");
 
+  // XXX fill with junk to help debug
+  for(i = 0; i < len; i++)
+    cp[i] = 1;
+
   rr = &freelist;
   while(*rr){
     struct run *rend = (struct run *) ((char *)(*rr) + (*rr)->len);
diff --git a/main.c b/main.c
index 979048c7a291040eea4fc728ee999b84db43f93f..4c2a2f97aa80d4ea9c0dcb0e8a7c1e7b827732a9 100644 (file)
--- a/main.c
+++ b/main.c
@@ -46,7 +46,7 @@ main()
   p = &proc[0];
   curproc[cpu()] = p;
   p->state = WAITING;
-  p->sz = PAGE;
+  p->sz = 4 * PAGE;
   p->mem = kalloc(p->sz);
   memset(p->mem, 0, p->sz);
   p->kstack = kalloc(KSTACKSIZE);
diff --git a/mp.c b/mp.c
index eb5afc9356f3a3d29231b616ea2a7ec53e4c2316..57b887d4fdd51d48403da70f960d2bd62da2ce91 100644 (file)
--- a/mp.c
+++ b/mp.c
@@ -6,6 +6,7 @@
 #include "x86.h"
 #include "traps.h"
 #include "mmu.h"
+#include "proc.h"
 
 /* 
  * Credit: Plan 9 sources, Intel MP spec, and Cliff Frey
@@ -92,16 +93,11 @@ enum {                                      /* LAPIC_TDCR */
 };
 
 #define APBOOTCODE 0x7000 // XXX hack
-#define MPSTACK 512
 
 static struct MP* mp;  // The MP floating point structure
 static uint32_t *lapicaddr;
-static struct cpu {
-  uint8_t apicid;       // Local APIC ID
-  int lintr[2];                // Local APIC
-  char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
-} cpus[NCPU];
-static int ncpu;
+struct cpu cpus[NCPU];
+int ncpu;
 static struct cpu *bcpu;
 
 static int
@@ -130,7 +126,7 @@ lapic_timerinit()
 void
 lapic_timerintr()
 {
-  cprintf("%d: timer interrupt!\n", cpu());
+  // cprintf("%d: timer interrupt!\n", cpu());
   lapic_write (LAPIC_EOI, 0);
 }
 
diff --git a/pipe.c b/pipe.c
index 9a81e0b9f43c94c4b0e9a5017611decf3b5c211a..3aed4e982087c10c99443125efc1488768344274 100644 (file)
--- a/pipe.c
+++ b/pipe.c
@@ -28,6 +28,10 @@ pipe_alloc(struct fd **fd1, struct fd **fd2)
     goto oops;
   if((p = (struct pipe *) kalloc(PAGE)) == 0)
     goto oops;
+  p->readopen = 1;
+  p->writeopen = 1;
+  p->writep = 0;
+  p->readp = 0;
   (*fd1)->type = FD_PIPE;
   (*fd1)->readable = 1;
   (*fd1)->writeable = 0;
@@ -54,10 +58,13 @@ pipe_alloc(struct fd **fd1, struct fd **fd2)
 void
 pipe_close(struct pipe *p, int writeable)
 {
-  if(writeable)
+  if(writeable){
     p->writeopen = 0;
-  else
+    wakeup(&p->readp);
+  } else {
     p->readopen = 0;
+    wakeup(&p->writep);
+  }
   if(p->readopen == 0 && p->writeopen == 0)
     kfree((char *) p, PAGE);
 }
@@ -71,11 +78,13 @@ pipe_write(struct pipe *p, char *addr, int n)
     while(((p->writep + 1) % PIPESIZE) == p->readp){
       if(p->readopen == 0)
         return -1;
+      wakeup(&p->readp);
       sleep(&p->writep);
     }
     p->data[p->writep] = addr[i];
     p->writep = (p->writep + 1) % PIPESIZE;
   }
+  wakeup(&p->readp);
   return i;
 }
 
@@ -96,5 +105,6 @@ pipe_read(struct pipe *p, char *addr, int n)
     addr[i] = p->data[p->readp];
     p->readp = (p->readp + 1) % PIPESIZE;
   }
+  wakeup(&p->writep);
   return i;
 }
diff --git a/proc.c b/proc.c
index 97e84e36d284efd7cef1a44d9824506939398d0f..8ad6a232343ceca1d9221d469f0ca2d391465355 100644 (file)
--- a/proc.c
+++ b/proc.c
@@ -104,37 +104,47 @@ swtch()
 {
   struct proc *np;
   struct proc *op = curproc[cpu()];
-  
+  unsigned sp;
+  int i;
+
+  // force push of callee-saved registers
+  asm volatile("nop" : : : "%edi", "%esi", "%ebx");
+
+  // save calling process's stack pointers
+  op->ebp = read_ebp();
+  op->esp = read_esp();
+
+  // don't execute on calling process's stack
+  sp = (unsigned) cpus[cpu()].mpstack + MPSTACK - 32;
+  asm volatile("movl %0, %%esp" : : "g" (sp));
+  asm volatile("movl %0, %%ebp" : : "g" (sp));
+
+  // gcc might store op on the stack
+  np = curproc[cpu()];
+  np = np + 1;
+
   while(1){
-    np = op + 1;
-    while(np != op){
+    for(i = 0; i < NPROC; i++){
+      if(np >= &proc[NPROC])
+        np = &proc[0];
       if(np->state == RUNNABLE)
         break;
       np++;
-      if(np == &proc[NPROC])
-        np = &proc[0];
     }
-    if(np->state == RUNNABLE)
+    if(i < NPROC)
       break;
-    // cprintf("swtch: nothing to run\n");
+    // cprintf("swtch %d: nothing to run %d %d\n",
+            // cpu(), proc[1].state, proc[2].state);
     release_spinlock(&kernel_lock);
     acquire_spinlock(&kernel_lock);
+    np = &proc[0];
   }
   
-  // XXX this may be too late, should probably save on the way
-  // in, in case some other CPU decided to run curproc
-  // before we got here. in fact setting state=WAITING and
-  // setting these variables had better be atomic w.r.t. other CPUs.
-  op->ebp = read_ebp();
-  op->esp = read_esp();
-
-  cprintf("cpu %d swtch %x -> %x\n", cpu(), op, np);
+  cprintf("cpu %d swtch %x -> %x\n", cpu(), curproc[cpu()], np);
 
   curproc[cpu()] = np;
   np->state = RUNNING;
 
-  // XXX callee-saved registers?
-
   // h/w sets busy bit in TSS descriptor sometimes, and faults
   // if it's set in LTR. so clear tss descriptor busy bit.
   np->gdt[SEG_TSS].sd_type = STS_T32A;
diff --git a/proc.h b/proc.h
index 14164dbc7ed38693da6e9dbb648e5888abb1893b..e371f7dbb575bbffc19e16f83f80943b9118c8bc 100644 (file)
--- a/proc.h
+++ b/proc.h
@@ -37,3 +37,14 @@ struct proc{
 
 extern struct proc proc[];
 extern struct proc *curproc[NCPU];
+
+#define MPSTACK 512
+
+struct cpu {
+  uint8_t apicid;       // Local APIC ID
+  int lintr[2];                // Local APIC
+  char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()
+};
+
+extern struct cpu cpus[NCPU];
+extern int ncpu;
index c27c22622f8614d813483a895606ca380e72e14d..63435311913ae56f271fa8eccd029f0cf765c9c2 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -91,7 +91,7 @@ sys_pipe()
 int
 sys_write()
 {
-  int fd, n;
+  int fd, n, ret;
   unsigned addr;
   struct proc *p = curproc[cpu()];
 
@@ -103,13 +103,14 @@ sys_write()
     return -1;
   if(addr + n > p->sz)
     return -1;
-  return fd_write(p->fds[fd], p->mem + addr, n);
+  ret = fd_write(p->fds[fd], p->mem + addr, n);
+  return ret;
 }
 
 int
 sys_read()
 {
-  int fd, n;
+  int fd, n, ret;
   unsigned addr;
   struct proc *p = curproc[cpu()];
 
@@ -121,7 +122,25 @@ sys_read()
     return -1;
   if(addr + n > p->sz)
     return -1;
-  return fd_read(p->fds[fd], p->mem + addr, n);
+  ret = fd_read(p->fds[fd], p->mem + addr, n);
+  return ret;
+}
+
+int
+sys_close()
+{
+  int fd;
+  struct proc *p = curproc[cpu()];
+
+  if(fetcharg(0, &fd) < 0)
+    return -1;
+  if(fd < 0 || fd >= NOFILE)
+    return -1;
+  if(p->fds[fd] == 0)
+    return -1;
+  fd_close(p->fds[fd]);
+  p->fds[fd] = 0;
+  return 0;
 }
 
 int
@@ -138,6 +157,14 @@ sys_exit()
 {
   struct proc *p;
   struct proc *cp = curproc[cpu()];
+  int fd;
+
+  for(fd = 0; fd < NOFILE; fd++){
+    if(cp->fds[fd]){
+      fd_close(cp->fds[fd]);
+      cp->fds[fd] = 0;
+    }
+  }
 
   cp->state = ZOMBIE;
 
@@ -227,6 +254,9 @@ syscall()
   case SYS_read:
     ret = sys_read();
     break;
+  case SYS_close:
+    ret = sys_close();
+    break;
   default:
     cprintf("unknown sys call %d\n", num);
     // XXX fault
index 65d5cedf1a4437a1b08a70845bac91c11532a55a..764b46f74316fe9ee8e299a63ea73437f37b9b4c 100644 (file)
--- a/syscall.h
+++ b/syscall.h
@@ -5,3 +5,4 @@
 #define SYS_pipe 5
 #define SYS_write 6
 #define SYS_read 7
+#define SYS_close 8
diff --git a/trap.c b/trap.c
index 01c2f14ec2880055a29edb23b63bc0bc35142b38..e36540da6f2820f1d1e081ee8aa1e4ed18138dbd 100644 (file)
--- a/trap.c
+++ b/trap.c
@@ -35,16 +35,28 @@ trap(struct Trapframe *tf)
 {
   int v = tf->tf_trapno;
 
+  if(tf->tf_cs == 0x8 && kernel_lock == cpu())
+    cprintf("cpu %d: trap from %x:%x with lock=%d\n",
+            cpu(), tf->tf_cs, tf->tf_eip, kernel_lock);
+
   acquire_spinlock(&kernel_lock); // released in trapret in trapasm.S
 
   if(v == T_SYSCALL){
-    curproc[cpu()]->tf = tf;
+    struct proc *cp = curproc[cpu()];
+    cp->tf = tf;
     syscall();
+    if(cp != curproc[cpu()])
+      panic("trap ret wrong curproc");
+    if(cp->state != RUNNING)
+      panic("trap ret but not RUNNING");
+    if(tf != cp->tf)
+      panic("trap ret wrong tf");
+    if(read_esp() < cp->kstack || read_esp() >= cp->kstack + KSTACKSIZE)
+      panic("trap ret esp wrong");
     return;
   }
 
   if(v == (IRQ_OFFSET + IRQ_TIMER)){
-    curproc[cpu()]->tf = tf;
     lapic_timerintr();
     return;
   }
diff --git a/ulib.c b/ulib.c
index 694501ee5b706445b1da1f49f46d91ab1b272a99..d99acdd62c3b24b332f6178e200aed00a029eb00 100644 (file)
--- a/ulib.c
+++ b/ulib.c
@@ -5,6 +5,13 @@ fork()
   asm("int $48");
 }
 
+int
+exit()
+{
+  asm("mov $2, %eax");
+  asm("int $48");
+}
+
 void
 cons_putc(int c)
 {
@@ -42,3 +49,10 @@ write(int fd, char *buf, int n)
   asm("mov $6, %eax");
   asm("int $48");
 }
+
+int
+close(int fd)
+{
+  asm("mov $8, %eax");
+  asm("int $48");
+}
index 62eefda30a6ffc38698157ed4a738654b80dc40f..37540dbbdb2acce751e53e442c5d4c3736a2c9b5 100644 (file)
@@ -1,22 +1,48 @@
 // simple fork and pipe read/write
 
-char buf[32];
+char buf[2048];
 
 void
 pipe1()
 {
   int fds[2], pid;
+  int seq = 0, i, n, cc, total;
 
   pipe(fds);
-  pid = pipe();
+  pid = fork();
   if(pid == 0){
-    write(fds[1], "xyz", 4);
+    close(fds[0]);
+    for(n = 0; n < 5; n++){
+      for(i = 0; i < 1033; i++)
+        buf[i] = seq++;
+      if(write(fds[1], buf, 1033) != 1033){
+        puts("pipe1 oops 1\n");
+        exit(1);
+      }
+    }
+    exit(0);
   } else {
-    read(fds[0], buf, sizeof(buf));
-    if(buf[0] != 'x' || buf[1] != 'y'){
-      puts("pipe1 oops\n");
-      return;
+    close(fds[1]);
+    total = 0;
+    cc = 1;
+    while(1){
+      n = read(fds[0], buf, cc);
+      if(n < 1)
+        break;
+      for(i = 0; i < n; i++){
+        if((buf[i] & 0xff) != (seq++ & 0xff)){
+          puts("pipe1 oops 2\n");
+          return;
+        }
+      }
+      total += n;
+      cc = cc * 2;
+      if(cc > sizeof(buf))
+        cc = sizeof(buf);
     }
+    if(total != 5 * 1033)
+      puts("pipe1 oops 3\n");
+    close(fds[0]);
   }
   puts("pipe1 ok\n");
 }
diff --git a/x86.h b/x86.h
index b905f83f4fe5d982dc5942e590dfd16b06acee4b..7bc677fe69896b10ce03f2ed5dd2bf98a25311a0 100644 (file)
--- a/x86.h
+++ b/x86.h
@@ -244,6 +244,30 @@ read_esp(void)
         return esp;
 }
 
+static __inline uint32_t
+read_esi(void)
+{
+        uint32_t esi;
+        __asm __volatile("movl %%esi,%0" : "=r" (esi));
+        return esi;
+}
+
+static __inline uint32_t
+read_edi(void)
+{
+        uint32_t edi;
+        __asm __volatile("movl %%edi,%0" : "=r" (edi));
+        return edi;
+}
+
+static __inline uint32_t
+read_ebx(void)
+{
+        uint32_t ebx;
+        __asm __volatile("movl %%ebx,%0" : "=r" (ebx));
+        return ebx;
+}
+
 static __inline void
 cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
 {
@@ -280,6 +304,20 @@ read_tsc(void)
         return tsc;
 }
 
+// disable interrupts
+static __inline void
+cli(void)
+{
+        __asm __volatile("cli");
+}
+
+// enable interrupts
+static __inline void
+sti(void)
+{
+        __asm __volatile("sti");
+}
+
 struct PushRegs {
     /* registers as pushed by pusha */
     uint32_t reg_edi;