diff options
| -rw-r--r-- | kernel/kalloc.c | 4 | ||||
| -rw-r--r-- | kernel/spinlock.c | 9 | ||||
| -rw-r--r-- | user/usertests.c | 39 | 
3 files changed, 47 insertions, 5 deletions
| diff --git a/kernel/kalloc.c b/kernel/kalloc.c index afadb02..d72e0ab 100644 --- a/kernel/kalloc.c +++ b/kernel/kalloc.c @@ -55,8 +55,9 @@ kfree(void *pa)    // Fill with junk to catch dangling refs.    memset(pa, 1, PGSIZE); -  acquire(&kmem.lock);    r = (struct run*)pa; + +  acquire(&kmem.lock);    r->next = kmem.freelist;    kmem.freelist = r;    release(&kmem.lock); @@ -75,6 +76,7 @@ kalloc(void)    if(r)      kmem.freelist = r->next;    release(&kmem.lock); +    if(r)      memset((char*)r, 5, PGSIZE); // fill with junk    return (void*)r; diff --git a/kernel/spinlock.c b/kernel/spinlock.c index 52bd504..83512bb 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c @@ -25,7 +25,7 @@ acquire(struct spinlock *lk)    if(holding(lk))      panic("acquire"); -  // On RISC-V, this turns into an atomic swap: +  // On RISC-V, sync_lock_test_and_set turns into an atomic swap:    //   a5 = 1    //   s1 = &lk->locked    //   amoswap.w.aq a5, a5, (s1) @@ -57,9 +57,10 @@ release(struct spinlock *lk)    __sync_synchronize();    // Release the lock, equivalent to lk->locked = 0. -  // This code can't use a C assignment, since it might -  // not be atomic. -  // On RISC-V, this turns into an atomic swap: +  // This code doesn't use a C assignment, since the C standard +  // implies that an assignment might be implemented with +  // multiple store instructions. +  // On RISC-V, sync_lock_release turns into an atomic swap:    //   s1 = &lk->locked    //   amoswap.w zero, zero, (s1)    __sync_lock_release(&lk->locked); diff --git a/user/usertests.c b/user/usertests.c index 9d46b1a..5cc5099 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -506,6 +506,44 @@ twochildren(void)    printf(1, "twochildren ok\n");  } +// concurrent forks to try to expose locking bugs. +void +forkfork(void) +{ +  int ppid = getpid(); +   +  printf(1, "forkfork test\n"); + +  for(int i = 0; i < 2; i++){ +    int pid = fork(); +    if(pid < 0){ +      printf(1, "fork failed"); +      exit(); +    } +    if(pid == 0){ +      for(int j = 0; j < 200; j++){ +        int pid1 = fork(); +        if(pid1 < 0){ +          printf(1, "fork failed\n"); +          kill(ppid); +          exit(); +        } +        if(pid1 == 0){ +          exit(); +        } +        wait(); +      } +      exit(); +    } +  } + +  for(int i = 0; i < 2; i++){ +    wait(); +  } + +  printf(1, "forkfork ok\n"); +} +  void  forkforkfork(void)  { @@ -1858,6 +1896,7 @@ main(int argc, char *argv[])    reparent();    twochildren(); +  forkfork();    forkforkfork();    argptest(); | 
