diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | fd.c | 30 | ||||
| -rw-r--r-- | kalloc.c | 5 | ||||
| -rw-r--r-- | main.c | 2 | ||||
| -rw-r--r-- | mp.c | 12 | ||||
| -rw-r--r-- | pipe.c | 14 | ||||
| -rw-r--r-- | proc.c | 44 | ||||
| -rw-r--r-- | proc.h | 11 | ||||
| -rw-r--r-- | syscall.c | 38 | ||||
| -rw-r--r-- | syscall.h | 1 | ||||
| -rw-r--r-- | trap.c | 16 | ||||
| -rw-r--r-- | ulib.c | 14 | ||||
| -rw-r--r-- | usertests.c | 40 | ||||
| -rw-r--r-- | x86.h | 38 | 
14 files changed, 212 insertions, 55 deletions
@@ -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 @@ -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; +  } +} @@ -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); @@ -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); @@ -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);  } @@ -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;  } @@ -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; @@ -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; @@ -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 @@ -5,3 +5,4 @@  #define SYS_pipe 5  #define SYS_write 6  #define SYS_read 7 +#define SYS_close 8 @@ -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;    } @@ -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"); +} diff --git a/usertests.c b/usertests.c index 62eefda..37540db 100644 --- a/usertests.c +++ b/usertests.c @@ -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");  } @@ -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;  | 
