summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-07-11 05:41:59 -0400
committerRobert Morris <[email protected]>2019-07-11 05:41:59 -0400
commit7797a384236cee31b924d27d8f814ef9543662cd (patch)
treec6222d9a40f9ce0bc9f589525d33e882f1670a6b
parent4bc900e78bdbff3ba22ccccd26833cf70fd300b1 (diff)
downloadxv6-labs-7797a384236cee31b924d27d8f814ef9543662cd.tar.gz
xv6-labs-7797a384236cee31b924d27d8f814ef9543662cd.tar.bz2
xv6-labs-7797a384236cee31b924d27d8f814ef9543662cd.zip
another test, to help with locking exercises
-rw-r--r--kernel/kalloc.c4
-rw-r--r--kernel/spinlock.c9
-rw-r--r--user/usertests.c39
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();